diff options
author | Ingo Molnar <mingo@kernel.org> | 2013-11-14 08:28:30 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-11-14 08:28:30 +0100 |
commit | 555a098af6086256bc64d3806519f37ccae936e0 (patch) | |
tree | 4f13126483fc1202d23f1ba55045fac41d19118e /drivers/nfc | |
parent | d969135aae1434547f41853f0e8eaa622e8b8816 (diff) | |
parent | f0d55cc1a65852e6647d4f5d707c1c9b5471ce3c (diff) |
Merge branch 'linus' into perf/urgent
Merge dependencies to apply a fix.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/nfc')
-rw-r--r-- | drivers/nfc/Kconfig | 10 | ||||
-rw-r--r-- | drivers/nfc/Makefile | 1 | ||||
-rw-r--r-- | drivers/nfc/mei_phy.c | 6 | ||||
-rw-r--r-- | drivers/nfc/microread/i2c.c | 32 | ||||
-rw-r--r-- | drivers/nfc/microread/mei.c | 4 | ||||
-rw-r--r-- | drivers/nfc/microread/microread.c | 7 | ||||
-rw-r--r-- | drivers/nfc/nfcsim.c | 38 | ||||
-rw-r--r-- | drivers/nfc/nfcwilink.c | 97 | ||||
-rw-r--r-- | drivers/nfc/pn533.c | 604 | ||||
-rw-r--r-- | drivers/nfc/pn544/i2c.c | 42 | ||||
-rw-r--r-- | drivers/nfc/pn544/pn544.c | 129 | ||||
-rw-r--r-- | drivers/nfc/port100.c | 1529 |
12 files changed, 2171 insertions, 328 deletions
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index b0b64ccb7d7..c1fb2060333 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig @@ -46,6 +46,16 @@ config NFC_SIM If unsure, say N. +config NFC_PORT100 + tristate "Sony NFC Port-100 Series USB device support" + depends on USB + depends on NFC_DIGITAL + help + This adds support for Sony Port-100 chip based USB devices such as the + RC-S380 dongle. + + If unsure, say N. + source "drivers/nfc/pn544/Kconfig" source "drivers/nfc/microread/Kconfig" diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index be7636abcb3..c715fe8582a 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile @@ -8,5 +8,6 @@ obj-$(CONFIG_NFC_PN533) += pn533.o obj-$(CONFIG_NFC_WILINK) += nfcwilink.o obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o obj-$(CONFIG_NFC_SIM) += nfcsim.o +obj-$(CONFIG_NFC_PORT100) += port100.o ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c index 606bf55e76e..85f90090cc1 100644 --- a/drivers/nfc/mei_phy.c +++ b/drivers/nfc/mei_phy.c @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/slab.h> #include <linux/nfc.h> @@ -60,13 +62,13 @@ int nfc_mei_phy_enable(void *phy_id) r = mei_cl_enable_device(phy->device); if (r < 0) { - pr_err("MEI_PHY: Could not enable device\n"); + pr_err("Could not enable device\n"); return r; } r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy); if (r) { - pr_err("MEY_PHY: Event cb registration failed\n"); + pr_err("Event cb registration failed\n"); mei_cl_disable_device(phy->device); phy->powered = 0; diff --git a/drivers/nfc/microread/i2c.c b/drivers/nfc/microread/i2c.c index 101089495bf..696e3467ecc 100644 --- a/drivers/nfc/microread/i2c.c +++ b/drivers/nfc/microread/i2c.c @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/i2c.h> #include <linux/delay.h> @@ -95,12 +97,8 @@ static int check_crc(struct sk_buff *skb) crc = crc ^ skb->data[i]; if (crc != skb->data[skb->len-1]) { - pr_err(MICROREAD_I2C_DRIVER_NAME - ": CRC error 0x%x != 0x%x\n", - crc, skb->data[skb->len-1]); - - pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); - + pr_err("CRC error 0x%x != 0x%x\n", crc, skb->data[skb->len-1]); + pr_info("%s: BAD CRC\n", __func__); return -EPERM; } @@ -160,18 +158,15 @@ static int microread_i2c_read(struct microread_i2c_phy *phy, u8 tmp[MICROREAD_I2C_LLC_MAX_SIZE - 1]; struct i2c_client *client = phy->i2c_dev; - pr_debug("%s\n", __func__); - r = i2c_master_recv(client, &len, 1); if (r != 1) { - dev_err(&client->dev, "cannot read len byte\n"); + nfc_err(&client->dev, "cannot read len byte\n"); return -EREMOTEIO; } if ((len < MICROREAD_I2C_LLC_MIN_SIZE) || (len > MICROREAD_I2C_LLC_MAX_SIZE)) { - dev_err(&client->dev, "invalid len byte\n"); - pr_err("invalid len byte\n"); + nfc_err(&client->dev, "invalid len byte\n"); r = -EBADMSG; goto flush; } @@ -228,7 +223,6 @@ static irqreturn_t microread_i2c_irq_thread_fn(int irq, void *phy_id) } client = phy->i2c_dev; - dev_dbg(&client->dev, "IRQ\n"); if (phy->hard_fault != 0) return IRQ_HANDLED; @@ -263,20 +257,18 @@ static int microread_i2c_probe(struct i2c_client *client, dev_get_platdata(&client->dev); int r; - dev_dbg(&client->dev, "client %p", client); + dev_dbg(&client->dev, "client %p\n", client); if (!pdata) { - dev_err(&client->dev, "client %p: missing platform data", + nfc_err(&client->dev, "client %p: missing platform data\n", client); return -EINVAL; } phy = devm_kzalloc(&client->dev, sizeof(struct microread_i2c_phy), GFP_KERNEL); - if (!phy) { - dev_err(&client->dev, "Can't allocate microread phy"); + if (!phy) return -ENOMEM; - } i2c_set_clientdata(client, phy); phy->i2c_dev = client; @@ -285,7 +277,7 @@ static int microread_i2c_probe(struct i2c_client *client, IRQF_TRIGGER_RISING | IRQF_ONESHOT, MICROREAD_I2C_DRIVER_NAME, phy); if (r) { - dev_err(&client->dev, "Unable to register IRQ handler"); + nfc_err(&client->dev, "Unable to register IRQ handler\n"); return r; } @@ -296,7 +288,7 @@ static int microread_i2c_probe(struct i2c_client *client, if (r < 0) goto err_irq; - dev_info(&client->dev, "Probed"); + nfc_info(&client->dev, "Probed"); return 0; @@ -310,8 +302,6 @@ static int microread_i2c_remove(struct i2c_client *client) { struct microread_i2c_phy *phy = i2c_get_clientdata(client); - dev_dbg(&client->dev, "%s\n", __func__); - microread_remove(phy->hdev); free_irq(client->irq, phy); diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index cdf1bc53b25..72fafec3d46 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/nfc.h> @@ -59,8 +61,6 @@ static int microread_mei_remove(struct mei_cl_device *device) { struct nfc_mei_phy *phy = mei_cl_get_drvdata(device); - pr_info("Removing microread\n"); - microread_remove(phy->hdev); nfc_mei_phy_free(phy); diff --git a/drivers/nfc/microread/microread.c b/drivers/nfc/microread/microread.c index cdb9f6de132..970ded6bfcf 100644 --- a/drivers/nfc/microread/microread.c +++ b/drivers/nfc/microread/microread.c @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/delay.h> #include <linux/slab.h> @@ -546,7 +548,7 @@ exit: kfree_skb(skb); if (r) - pr_err("Failed to handle discovered target err=%d", r); + pr_err("Failed to handle discovered target err=%d\n", r); } static int microread_event_received(struct nfc_hci_dev *hdev, u8 gate, @@ -656,7 +658,6 @@ int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, info = kzalloc(sizeof(struct microread_info), GFP_KERNEL); if (!info) { - pr_err("Cannot allocate memory for microread_info.\n"); r = -ENOMEM; goto err_info_alloc; } @@ -686,7 +687,7 @@ int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, MICROREAD_CMD_TAILROOM, phy_payload); if (!info->hdev) { - pr_err("Cannot allocate nfc hdev.\n"); + pr_err("Cannot allocate nfc hdev\n"); r = -ENOMEM; goto err_alloc_hdev; } diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c index 9a53f13c88d..93111fa8d28 100644 --- a/drivers/nfc/nfcsim.c +++ b/drivers/nfc/nfcsim.c @@ -19,10 +19,10 @@ #include <linux/nfc.h> #include <net/nfc/nfc.h> -#define DEV_ERR(_dev, fmt, args...) nfc_dev_err(&_dev->nfc_dev->dev, \ +#define DEV_ERR(_dev, fmt, args...) nfc_err(&_dev->nfc_dev->dev, \ "%s: " fmt, __func__, ## args) -#define DEV_DBG(_dev, fmt, args...) nfc_dev_dbg(&_dev->nfc_dev->dev, \ +#define DEV_DBG(_dev, fmt, args...) dev_dbg(&_dev->nfc_dev->dev, \ "%s: " fmt, __func__, ## args) #define NFCSIM_VERSION "0.1" @@ -64,7 +64,7 @@ static struct workqueue_struct *wq; static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown) { - DEV_DBG(dev, "shutdown=%d", shutdown); + DEV_DBG(dev, "shutdown=%d\n", shutdown); mutex_lock(&dev->lock); @@ -84,7 +84,7 @@ static int nfcsim_target_found(struct nfcsim *dev) { struct nfc_target nfc_tgt; - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); memset(&nfc_tgt, 0, sizeof(struct nfc_target)); @@ -98,7 +98,7 @@ static int nfcsim_dev_up(struct nfc_dev *nfc_dev) { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); mutex_lock(&dev->lock); @@ -113,7 +113,7 @@ static int nfcsim_dev_down(struct nfc_dev *nfc_dev) { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); mutex_lock(&dev->lock); @@ -143,7 +143,7 @@ static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev, remote_gb = nfc_get_local_general_bytes(peer->nfc_dev, &remote_gb_len); if (!remote_gb) { - DEV_ERR(peer, "Can't get remote general bytes"); + DEV_ERR(peer, "Can't get remote general bytes\n"); mutex_unlock(&peer->lock); return -EINVAL; @@ -155,7 +155,7 @@ static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev, rc = nfc_set_remote_general_bytes(nfc_dev, remote_gb, remote_gb_len); if (rc) { - DEV_ERR(dev, "Can't set remote general bytes"); + DEV_ERR(dev, "Can't set remote general bytes\n"); mutex_unlock(&dev->lock); return rc; } @@ -172,7 +172,7 @@ static int nfcsim_dep_link_down(struct nfc_dev *nfc_dev) { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); nfcsim_cleanup_dev(dev, 0); @@ -188,7 +188,7 @@ static int nfcsim_start_poll(struct nfc_dev *nfc_dev, mutex_lock(&dev->lock); if (dev->polling_mode != NFCSIM_POLL_NONE) { - DEV_ERR(dev, "Already in polling mode"); + DEV_ERR(dev, "Already in polling mode\n"); rc = -EBUSY; goto exit; } @@ -200,7 +200,7 @@ static int nfcsim_start_poll(struct nfc_dev *nfc_dev, dev->polling_mode |= NFCSIM_POLL_TARGET; if (dev->polling_mode == NFCSIM_POLL_NONE) { - DEV_ERR(dev, "Unsupported polling mode"); + DEV_ERR(dev, "Unsupported polling mode\n"); rc = -EINVAL; goto exit; } @@ -210,7 +210,7 @@ static int nfcsim_start_poll(struct nfc_dev *nfc_dev, queue_delayed_work(wq, &dev->poll_work, 0); - DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X", im_protocols, + DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X\n", im_protocols, tm_protocols); rc = 0; @@ -224,7 +224,7 @@ static void nfcsim_stop_poll(struct nfc_dev *nfc_dev) { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, "Stop poll"); + DEV_DBG(dev, "Stop poll\n"); mutex_lock(&dev->lock); @@ -240,7 +240,7 @@ static int nfcsim_activate_target(struct nfc_dev *nfc_dev, { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); return -ENOTSUPP; } @@ -250,7 +250,7 @@ static void nfcsim_deactivate_target(struct nfc_dev *nfc_dev, { struct nfcsim *dev = nfc_get_drvdata(nfc_dev); - DEV_DBG(dev, ""); + DEV_DBG(dev, "\n"); } static void nfcsim_wq_recv(struct work_struct *work) @@ -267,7 +267,7 @@ static void nfcsim_wq_recv(struct work_struct *work) if (dev->initiator) { if (!dev->cb) { - DEV_ERR(dev, "Null recv callback"); + DEV_ERR(dev, "Null recv callback\n"); dev_kfree_skb(dev->clone_skb); goto exit; } @@ -310,7 +310,7 @@ static int nfcsim_tx(struct nfc_dev *nfc_dev, struct nfc_target *target, peer->clone_skb = skb_clone(skb, GFP_KERNEL); if (!peer->clone_skb) { - DEV_ERR(dev, "skb_clone failed"); + DEV_ERR(dev, "skb_clone failed\n"); mutex_unlock(&peer->lock); err = -ENOMEM; goto exit; @@ -397,13 +397,13 @@ static void nfcsim_wq_poll(struct work_struct *work) nfcsim_set_polling_mode(dev); if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { - DEV_DBG(dev, "Not polling"); + DEV_DBG(dev, "Not polling\n"); goto unlock; } DEV_DBG(dev, "Polling as %s", dev->curr_polling_mode == NFCSIM_POLL_INITIATOR ? - "initiator" : "target"); + "initiator\n" : "target\n"); if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) goto sched_work; diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c index 59f95d8fc98..71308645593 100644 --- a/drivers/nfc/nfcwilink.c +++ b/drivers/nfc/nfcwilink.c @@ -146,13 +146,11 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) unsigned long comp_ret; int rc; - nfc_dev_dbg(&drv->pdev->dev, "get_bts_file_name entry"); - skb = nfcwilink_skb_alloc(sizeof(struct nci_vs_nfcc_info_cmd), GFP_KERNEL); if (!skb) { - nfc_dev_err(&drv->pdev->dev, - "no memory for nci_vs_nfcc_info_cmd"); + nfc_err(&drv->pdev->dev, + "no memory for nci_vs_nfcc_info_cmd\n"); return -ENOMEM; } @@ -170,21 +168,19 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) comp_ret = wait_for_completion_timeout(&drv->completed, msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT)); - nfc_dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld", - comp_ret); + dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld\n", + comp_ret); if (comp_ret == 0) { - nfc_dev_err(&drv->pdev->dev, - "timeout on wait_for_completion_timeout"); + nfc_err(&drv->pdev->dev, + "timeout on wait_for_completion_timeout\n"); return -ETIMEDOUT; } - nfc_dev_dbg(&drv->pdev->dev, "nci_vs_nfcc_info_rsp: plen %d, status %d", - drv->nfcc_info.plen, - drv->nfcc_info.status); + dev_dbg(&drv->pdev->dev, "nci_vs_nfcc_info_rsp: plen %d, status %d\n", + drv->nfcc_info.plen, drv->nfcc_info.status); if ((drv->nfcc_info.plen != 5) || (drv->nfcc_info.status != 0)) { - nfc_dev_err(&drv->pdev->dev, - "invalid nci_vs_nfcc_info_rsp"); + nfc_err(&drv->pdev->dev, "invalid nci_vs_nfcc_info_rsp\n"); return -EINVAL; } @@ -195,7 +191,7 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) drv->nfcc_info.sw_ver_z, drv->nfcc_info.patch_id); - nfc_dev_info(&drv->pdev->dev, "nfcwilink FW file name: %s", file_name); + nfc_info(&drv->pdev->dev, "nfcwilink FW file name: %s\n", file_name); return 0; } @@ -207,15 +203,13 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) unsigned long comp_ret; int rc; - nfc_dev_dbg(&drv->pdev->dev, "send_bts_cmd entry"); - /* verify valid cmd for the NFC channel */ if ((len <= sizeof(struct nfcwilink_hdr)) || (len > BTS_FILE_CMD_MAX_LEN) || (hdr->chnl != NFCWILINK_CHNL) || (hdr->opcode != NFCWILINK_OPCODE)) { - nfc_dev_err(&drv->pdev->dev, - "ignoring invalid bts cmd, len %d, chnl %d, opcode %d", + nfc_err(&drv->pdev->dev, + "ignoring invalid bts cmd, len %d, chnl %d, opcode %d\n", len, hdr->chnl, hdr->opcode); return 0; } @@ -226,7 +220,7 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) skb = nfcwilink_skb_alloc(len, GFP_KERNEL); if (!skb) { - nfc_dev_err(&drv->pdev->dev, "no memory for bts cmd"); + nfc_err(&drv->pdev->dev, "no memory for bts cmd\n"); return -ENOMEM; } @@ -238,11 +232,11 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) comp_ret = wait_for_completion_timeout(&drv->completed, msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT)); - nfc_dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld", - comp_ret); + dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld\n", + comp_ret); if (comp_ret == 0) { - nfc_dev_err(&drv->pdev->dev, - "timeout on wait_for_completion_timeout"); + nfc_err(&drv->pdev->dev, + "timeout on wait_for_completion_timeout\n"); return -ETIMEDOUT; } @@ -257,8 +251,6 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) __u8 *ptr; int len, rc; - nfc_dev_dbg(&drv->pdev->dev, "download_fw entry"); - set_bit(NFCWILINK_FW_DOWNLOAD, &drv->flags); rc = nfcwilink_get_bts_file_name(drv, file_name); @@ -267,7 +259,7 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) rc = request_firmware(&fw, file_name, &drv->pdev->dev); if (rc) { - nfc_dev_err(&drv->pdev->dev, "request_firmware failed %d", rc); + nfc_err(&drv->pdev->dev, "request_firmware failed %d\n", rc); /* if the file is not found, don't exit with failure */ if (rc == -ENOENT) @@ -280,14 +272,14 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) ptr = (__u8 *)fw->data; if ((len == 0) || (ptr == NULL)) { - nfc_dev_dbg(&drv->pdev->dev, - "request_firmware returned size %d", len); + dev_dbg(&drv->pdev->dev, + "request_firmware returned size %d\n", len); goto release_fw; } if (__le32_to_cpu(((struct bts_file_hdr *)ptr)->magic) != BTS_FILE_HDR_MAGIC) { - nfc_dev_err(&drv->pdev->dev, "wrong bts magic number"); + nfc_err(&drv->pdev->dev, "wrong bts magic number\n"); rc = -EINVAL; goto release_fw; } @@ -302,8 +294,8 @@ static int nfcwilink_download_fw(struct nfcwilink *drv) action_len = __le16_to_cpu(((struct bts_file_action *)ptr)->len); - nfc_dev_dbg(&drv->pdev->dev, "bts_file_action type %d, len %d", - action_type, action_len); + dev_dbg(&drv->pdev->dev, "bts_file_action type %d, len %d\n", + action_type, action_len); switch (action_type) { case BTS_FILE_ACTION_TYPE_SEND_CMD: @@ -333,8 +325,6 @@ static void nfcwilink_register_complete(void *priv_data, char data) { struct nfcwilink *drv = priv_data; - nfc_dev_dbg(&drv->pdev->dev, "register_complete entry"); - /* store ST registration status */ drv->st_register_cb_status = data; @@ -356,7 +346,7 @@ static long nfcwilink_receive(void *priv_data, struct sk_buff *skb) return -EFAULT; } - nfc_dev_dbg(&drv->pdev->dev, "receive entry, len %d", skb->len); + dev_dbg(&drv->pdev->dev, "receive entry, len %d\n", skb->len); /* strip the ST header (apart for the chnl byte, which is not received in the hdr) */ @@ -370,7 +360,7 @@ static long nfcwilink_receive(void *priv_data, struct sk_buff *skb) /* Forward skb to NCI core layer */ rc = nci_recv_frame(drv->ndev, skb); if (rc < 0) { - nfc_dev_err(&drv->pdev->dev, "nci_recv_frame failed %d", rc); + nfc_err(&drv->pdev->dev, "nci_recv_frame failed %d\n", rc); return rc; } @@ -396,8 +386,6 @@ static int nfcwilink_open(struct nci_dev *ndev) unsigned long comp_ret; int rc; - nfc_dev_dbg(&drv->pdev->dev, "open entry"); - if (test_and_set_bit(NFCWILINK_RUNNING, &drv->flags)) { rc = -EBUSY; goto exit; @@ -415,9 +403,9 @@ static int nfcwilink_open(struct nci_dev *ndev) &drv->completed, msecs_to_jiffies(NFCWILINK_REGISTER_TIMEOUT)); - nfc_dev_dbg(&drv->pdev->dev, - "wait_for_completion_timeout returned %ld", - comp_ret); + dev_dbg(&drv->pdev->dev, + "wait_for_completion_timeout returned %ld\n", + comp_ret); if (comp_ret == 0) { /* timeout */ @@ -425,13 +413,12 @@ static int nfcwilink_open(struct nci_dev *ndev) goto clear_exit; } else if (drv->st_register_cb_status != 0) { rc = drv->st_register_cb_status; - nfc_dev_err(&drv->pdev->dev, - "st_register_cb failed %d", rc); + nfc_err(&drv->pdev->dev, + "st_register_cb failed %d\n", rc); goto clear_exit; } } else { - nfc_dev_err(&drv->pdev->dev, - "st_register failed %d", rc); + nfc_err(&drv->pdev->dev, "st_register failed %d\n", rc); goto clear_exit; } } @@ -441,8 +428,8 @@ static int nfcwilink_open(struct nci_dev *ndev) drv->st_write = nfcwilink_proto.write; if (nfcwilink_download_fw(drv)) { - nfc_dev_err(&drv->pdev->dev, "nfcwilink_download_fw failed %d", - rc); + nfc_err(&drv->pdev->dev, "nfcwilink_download_fw failed %d\n", + rc); /* open should succeed, even if the FW download failed */ } @@ -460,14 +447,12 @@ static int nfcwilink_close(struct nci_dev *ndev) struct nfcwilink *drv = nci_get_drvdata(ndev); int rc; - nfc_dev_dbg(&drv->pdev->dev, "close entry"); - if (!test_and_clear_bit(NFCWILINK_RUNNING, &drv->flags)) return 0; rc = st_unregister(&nfcwilink_proto); if (rc) - nfc_dev_err(&drv->pdev->dev, "st_unregister failed %d", rc); + nfc_err(&drv->pdev->dev, "st_unregister failed %d\n", rc); drv->st_write = NULL; @@ -480,7 +465,7 @@ static int nfcwilink_send(struct nci_dev *ndev, struct sk_buff *skb) struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000}; long len; - nfc_dev_dbg(&drv->pdev->dev, "send entry, len %d", skb->len); + dev_dbg(&drv->pdev->dev, "send entry, len %d\n", skb->len); if (!test_bit(NFCWILINK_RUNNING, &drv->flags)) { kfree_skb(skb); @@ -498,7 +483,7 @@ static int nfcwilink_send(struct nci_dev *ndev, struct sk_buff *skb) len = drv->st_write(skb); if (len < 0) { kfree_skb(skb); - nfc_dev_err(&drv->pdev->dev, "st_write failed %ld", len); + nfc_err(&drv->pdev->dev, "st_write failed %ld\n", len); return -EFAULT; } @@ -517,8 +502,6 @@ static int nfcwilink_probe(struct platform_device *pdev) int rc; __u32 protocols; - nfc_dev_dbg(&pdev->dev, "probe entry"); - drv = devm_kzalloc(&pdev->dev, sizeof(struct nfcwilink), GFP_KERNEL); if (!drv) { rc = -ENOMEM; @@ -538,7 +521,7 @@ static int nfcwilink_probe(struct platform_device *pdev) NFCWILINK_HDR_LEN, 0); if (!drv->ndev) { - nfc_dev_err(&pdev->dev, "nci_allocate_device failed"); + nfc_err(&pdev->dev, "nci_allocate_device failed\n"); rc = -ENOMEM; goto exit; } @@ -548,7 +531,7 @@ static int nfcwilink_probe(struct platform_device *pdev) rc = nci_register_device(drv->ndev); if (rc < 0) { - nfc_dev_err(&pdev->dev, "nci_register_device failed %d", rc); + nfc_err(&pdev->dev, "nci_register_device failed %d\n", rc); goto free_dev_exit; } @@ -568,8 +551,6 @@ static int nfcwilink_remove(struct platform_device *pdev) struct nfcwilink *drv = dev_get_drvdata(&pdev->dev); struct nci_dev *ndev; - nfc_dev_dbg(&pdev->dev, "remove entry"); - if (!drv) return -EFAULT; @@ -578,8 +559,6 @@ static int nfcwilink_remove(struct platform_device *pdev) nci_unregister_device(ndev); nci_free_device(ndev); - dev_set_drvdata(&pdev->dev, NULL); - return 0; } diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 5df730be88a..2daf04c0733 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -150,6 +150,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table); #define PN533_CMD_TG_INIT_AS_TARGET 0x8c #define PN533_CMD_TG_GET_DATA 0x86 #define PN533_CMD_TG_SET_DATA 0x8e +#define PN533_CMD_TG_SET_META_DATA 0x94 #define PN533_CMD_UNDEF 0xff #define PN533_CMD_RESPONSE(cmd) (cmd + 1) @@ -373,6 +374,8 @@ struct pn533 { struct delayed_work poll_work; struct work_struct mi_rx_work; struct work_struct mi_tx_work; + struct work_struct mi_tm_rx_work; + struct work_struct mi_tm_tx_work; struct work_struct tg_work; struct work_struct rf_work; @@ -387,6 +390,7 @@ struct pn533 { struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; u8 poll_mod_count; u8 poll_mod_curr; + u8 poll_dep; u32 poll_protocols; u32 listen_protocols; struct timer_list listen_timer; @@ -722,32 +726,32 @@ static void pn533_recv_response(struct urb *urb) break; /* success */ case -ECONNRESET: case -ENOENT: - nfc_dev_dbg(&dev->interface->dev, - "The urb has been canceled (status %d)", - urb->status); + dev_dbg(&dev->interface->dev, + "The urb has been canceled (status %d)\n", + urb->status); goto sched_wq; case -ESHUTDOWN: default: - nfc_dev_err(&dev->interface->dev, - "Urb failure (status %d)", urb->status); + nfc_err(&dev->interface->dev, + "Urb failure (status %d)\n", urb->status); goto sched_wq; } in_frame = dev->in_urb->transfer_buffer; - nfc_dev_dbg(&dev->interface->dev, "Received a frame."); + dev_dbg(&dev->interface->dev, "Received a frame\n"); print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame, dev->ops->rx_frame_size(in_frame), false); if (!dev->ops->rx_is_frame_valid(in_frame, dev)) { - nfc_dev_err(&dev->interface->dev, "Received an invalid frame"); + nfc_err(&dev->interface->dev, "Received an invalid frame\n"); cmd->status = -EIO; goto sched_wq; } if (!pn533_rx_frame_is_cmd_response(dev, in_frame)) { - nfc_dev_err(&dev->interface->dev, - "It it not the response to the last command"); + nfc_err(&dev->interface->dev, + "It it not the response to the last command\n"); cmd->status = -EIO; goto sched_wq; } @@ -777,29 +781,29 @@ static void pn533_recv_ack(struct urb *urb) break; /* success */ case -ECONNRESET: case -ENOENT: - nfc_dev_dbg(&dev->interface->dev, - "The urb has been stopped (status %d)", - urb->status); + dev_dbg(&dev->interface->dev, + "The urb has been stopped (status %d)\n", + urb->status); goto sched_wq; case -ESHUTDOWN: default: - nfc_dev_err(&dev->interface->dev, - "Urb failure (status %d)", urb->status); + nfc_err(&dev->interface->dev, + "Urb failure (status %d)\n", urb->status); goto sched_wq; } in_frame = dev->in_urb->transfer_buffer; if (!pn533_std_rx_frame_is_ack(in_frame)) { - nfc_dev_err(&dev->interface->dev, "Received an invalid ack"); + nfc_err(&dev->interface->dev, "Received an invalid ack\n"); cmd->status = -EIO; goto sched_wq; } rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); if (rc) { - nfc_dev_err(&dev->interface->dev, - "usb_submit_urb failed with result %d", rc); + nfc_err(&dev->interface->dev, + "usb_submit_urb failed with result %d\n", rc); cmd->status = rc; goto sched_wq; } @@ -823,8 +827,6 @@ static int pn533_send_ack(struct pn533 *dev, gfp_t flags) /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - dev->out_urb->transfer_buffer = ack; dev->out_urb->transfer_buffer_length = sizeof(ack); rc = usb_submit_urb(dev->out_urb, flags); @@ -927,7 +929,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, struct pn533_cmd *cmd; int rc = 0; - nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", cmd_code); + dev_dbg(&dev->interface->dev, "Sending command 0x%x\n", cmd_code); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) @@ -954,8 +956,8 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, goto unlock; } - nfc_dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x", __func__, - cmd_code); + dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x\n", + __func__, cmd_code); INIT_LIST_HEAD(&cmd->queue); list_add_tail(&cmd->queue, &dev->cmd_queue); @@ -1168,14 +1170,14 @@ static void pn533_send_complete(struct urb *urb) break; /* success */ case -ECONNRESET: case -ENOENT: - nfc_dev_dbg(&dev->interface->dev, - "The urb has been stopped (status %d)", - urb->status); + dev_dbg(&dev->interface->dev, + "The urb has been stopped (status %d)\n", + urb->status); break; case -ESHUTDOWN: default: - nfc_dev_err(&dev->interface->dev, - "Urb failure (status %d)", urb->status); + nfc_err(&dev->interface->dev, "Urb failure (status %d)\n", + urb->status); } } @@ -1452,8 +1454,8 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, struct nfc_target nfc_tgt; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s - modulation=%d", __func__, - dev->poll_mod_curr); + dev_dbg(&dev->interface->dev, "%s: modulation=%d\n", + __func__, dev->poll_mod_curr); if (tg != 1) return -EPROTO; @@ -1475,8 +1477,8 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, rc = pn533_target_found_type_b(&nfc_tgt, tgdata, tgdata_len); break; default: - nfc_dev_err(&dev->interface->dev, - "Unknown current poll modulation"); + nfc_err(&dev->interface->dev, + "Unknown current poll modulation\n"); return -EPROTO; } @@ -1484,14 +1486,14 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, return rc; if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { - nfc_dev_dbg(&dev->interface->dev, - "The Tg found doesn't have the desired protocol"); + dev_dbg(&dev->interface->dev, + "The Tg found doesn't have the desired protocol\n"); return -EAGAIN; } - nfc_dev_dbg(&dev->interface->dev, - "Target found - supported protocols: 0x%x", - nfc_tgt.supported_protocols); + dev_dbg(&dev->interface->dev, + "Target found - supported protocols: 0x%x\n", + nfc_tgt.supported_protocols); dev->tgt_available_prots = nfc_tgt.supported_protocols; @@ -1548,7 +1550,8 @@ static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) u8 nbtg, tg, *tgdata; int rc, tgdata_len; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + /* Toggle the DEP polling */ + dev->poll_dep = 1; nbtg = resp->data[0]; tg = resp->data[1]; @@ -1624,37 +1627,130 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) #define PN533_CMD_DATAEXCH_HEAD_LEN 1 #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 +static void pn533_wq_tm_mi_recv(struct work_struct *work); +static struct sk_buff *pn533_build_response(struct pn533 *dev); + static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, struct sk_buff *resp) { - u8 status; + struct sk_buff *skb; + u8 status, ret, mi; + int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); - if (IS_ERR(resp)) + if (IS_ERR(resp)) { + skb_queue_purge(&dev->resp_q); return PTR_ERR(resp); + } status = resp->data[0]; + + ret = status & PN533_CMD_RET_MASK; + mi = status & PN533_CMD_MI_MASK; + skb_pull(resp, sizeof(status)); - if (status != 0) { - nfc_tm_deactivated(dev->nfc_dev); - dev->tgt_mode = 0; - dev_kfree_skb(resp); - return 0; + if (ret != PN533_CMD_RET_SUCCESS) { + rc = -EIO; + goto error; } - return nfc_tm_data_received(dev->nfc_dev, resp); + skb_queue_tail(&dev->resp_q, resp); + + if (mi) { + queue_work(dev->wq, &dev->mi_tm_rx_work); + return -EINPROGRESS; + } + + skb = pn533_build_response(dev); + if (!skb) { + rc = -EIO; + goto error; + } + + return nfc_tm_data_received(dev->nfc_dev, skb); + +error: + nfc_tm_deactivated(dev->nfc_dev); + dev->tgt_mode = 0; + skb_queue_purge(&dev->resp_q); + dev_kfree_skb(resp); + + return rc; +} + +static void pn533_wq_tm_mi_recv(struct work_struct *work) +{ + struct pn533 *dev = container_of(work, struct pn533, mi_tm_rx_work); + struct sk_buff *skb; + int rc; + + dev_dbg(&dev->interface->dev, "%s\n", __func__); + + skb = pn533_alloc_skb(dev, 0); + if (!skb) + return; + + rc = pn533_send_cmd_direct_async(dev, + PN533_CMD_TG_GET_DATA, + skb, + pn533_tm_get_data_complete, + NULL); + + if (rc < 0) + dev_kfree_skb(skb); + + return; +} + +static int pn533_tm_send_complete(struct pn533 *dev, void *arg, + struct sk_buff *resp); +static void pn533_wq_tm_mi_send(struct work_struct *work) +{ + struct pn533 *dev = container_of(work, struct pn533, mi_tm_tx_work); + struct sk_buff *skb; + int rc; + + dev_dbg(&dev->interface->dev, "%s\n", __func__); + + /* Grab the first skb in the queue */ + skb = skb_dequeue(&dev->fragment_skb); + if (skb == NULL) { /* No more data */ + /* Reset the queue for future use */ + skb_queue_head_init(&dev->fragment_skb); + goto error; + } + + /* last entry - remove MI bit */ + if (skb_queue_len(&dev->fragment_skb) == 0) { + rc = pn533_send_cmd_direct_async(dev, PN533_CMD_TG_SET_DATA, + skb, pn533_tm_send_complete, NULL); + } else + rc = pn533_send_cmd_direct_async(dev, + PN533_CMD_TG_SET_META_DATA, + skb, pn533_tm_send_complete, NULL); + + if (rc == 0) /* success */ + return; + + dev_err(&dev->interface->dev, + "Error %d when trying to perform set meta data_exchange", rc); + + dev_kfree_skb(skb); + +error: + pn533_send_ack(dev, GFP_KERNEL); + queue_work(dev->wq, &dev->cmd_work); } static void pn533_wq_tg_get_data(struct work_struct *work) { struct pn533 *dev = container_of(work, struct pn533, tg_work); - struct sk_buff *skb; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, 0); if (!skb) @@ -1676,7 +1772,7 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) size_t gb_len; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (resp->len < ATR_REQ_GB_OFFSET + 1) return -EINVAL; @@ -1684,8 +1780,8 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) mode = resp->data[0]; cmd = &resp->data[1]; - nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x len %d\n", - mode, resp->len); + dev_dbg(&dev->interface->dev, "Target mode 0x%x len %d\n", + mode, resp->len); if ((mode & PN533_INIT_TARGET_RESP_FRAME_MASK) == PN533_INIT_TARGET_RESP_ACTIVE) @@ -1700,8 +1796,8 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, comm_mode, gb, gb_len); if (rc < 0) { - nfc_dev_err(&dev->interface->dev, - "Error when signaling target activation"); + nfc_err(&dev->interface->dev, + "Error when signaling target activation\n"); return rc; } @@ -1715,7 +1811,7 @@ static void pn533_listen_mode_timer(unsigned long data) { struct pn533 *dev = (struct pn533 *)data; - nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout"); + dev_dbg(&dev->interface->dev, "Listen mode timeout\n"); dev->cancel_listen = 1; @@ -1730,13 +1826,12 @@ static int pn533_rf_complete(struct pn533 *dev, void *arg, { int rc = 0; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); - nfc_dev_err(&dev->interface->dev, "%s RF setting error %d", - __func__, rc); + nfc_err(&dev->interface->dev, "RF setting error %d", rc); return rc; } @@ -1754,7 +1849,7 @@ static void pn533_wq_rf(struct work_struct *work) struct sk_buff *skb; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, 2); if (!skb) @@ -1767,25 +1862,136 @@ static void pn533_wq_rf(struct work_struct *work) pn533_rf_complete, NULL); if (rc < 0) { dev_kfree_skb(skb); - nfc_dev_err(&dev->interface->dev, "RF setting error %d", rc); + nfc_err(&dev->interface->dev, "RF setting error %d\n", rc); } return; } +static int pn533_poll_dep_complete(struct pn533 *dev, void *arg, + struct sk_buff *resp) +{ + struct pn533_cmd_jump_dep_response *rsp; + struct nfc_target nfc_target; + u8 target_gt_len; + int rc; + + if (IS_ERR(resp)) + return PTR_ERR(resp); + + rsp = (struct pn533_cmd_jump_dep_response *)resp->data; + + rc = rsp->status & PN533_CMD_RET_MASK; + if (rc != PN533_CMD_RET_SUCCESS) { + /* Not target found, turn radio off */ + queue_work(dev->wq, &dev->rf_work); + + dev_kfree_skb(resp); + return 0; + } + + dev_dbg(&dev->interface->dev, "Creating new target"); + + nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; + nfc_target.nfcid1_len = 10; + memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len); + rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1); + if (rc) + goto error; + + dev->tgt_available_prots = 0; + dev->tgt_active_prot = NFC_PROTO_NFC_DEP; + + /* ATR_RES general bytes are located at offset 17 */ + target_gt_len = resp->len - 17; + rc = nfc_set_remote_general_bytes(dev->nfc_dev, + rsp->gt, target_gt_len); + if (!rc) { + rc = nfc_dep_link_is_up(dev->nfc_dev, + dev->nfc_dev->targets[0].idx, + 0, NFC_RF_INITIATOR); + + if (!rc) + pn533_poll_reset_mod_list(dev); + } +error: + dev_kfree_skb(resp); + return rc; +} + +#define PASSIVE_DATA_LEN 5 +static int pn533_poll_dep(struct nfc_dev *nfc_dev) +{ + struct pn533 *dev = nfc_get_drvdata(nfc_dev); + struct sk_buff *skb; + int rc, skb_len; + u8 *next, nfcid3[NFC_NFCID3_MAXSIZE]; + u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; + + dev_dbg(&dev->interface->dev, "%s", __func__); + + if (!dev->gb) { + dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len); + + if (!dev->gb || !dev->gb_len) { + dev->poll_dep = 0; + queue_work(dev->wq, &dev->rf_work); + } + } + + skb_len = 3 + dev->gb_len; /* ActPass + BR + Next */ + skb_len += PASSIVE_DATA_LEN; + + /* NFCID3 */ + skb_len += NFC_NFCID3_MAXSIZE; + nfcid3[0] = 0x1; + nfcid3[1] = 0xfe; + get_random_bytes(nfcid3 + 2, 6); + + skb = pn533_alloc_skb(dev, skb_len); + if (!skb) + return -ENOMEM; + + *skb_put(skb, 1) = 0x01; /* Active */ + *skb_put(skb, 1) = 0x02; /* 424 kbps */ + + next = skb_put(skb, 1); /* Next */ + *next = 0; + + /* Copy passive data */ + memcpy(skb_put(skb, PASSIVE_DATA_LEN), passive_data, PASSIVE_DATA_LEN); + *next |= 1; + + /* Copy NFCID3 (which is NFCID2 from SENSF_RES) */ + memcpy(skb_put(skb, NFC_NFCID3_MAXSIZE), nfcid3, + NFC_NFCID3_MAXSIZE); + *next |= 2; + + memcpy(skb_put(skb, dev->gb_len), dev->gb, dev->gb_len); + *next |= 4; /* We have some Gi */ + + rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb, + pn533_poll_dep_complete, NULL); + + if (rc < 0) + dev_kfree_skb(skb); + + return rc; +} + static int pn533_poll_complete(struct pn533 *dev, void *arg, struct sk_buff *resp) { struct pn533_poll_modulations *cur_mod; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); - nfc_dev_err(&dev->interface->dev, "%s Poll complete error %d", - __func__, rc); + nfc_err(&dev->interface->dev, "%s Poll complete error %d\n", + __func__, rc); if (rc == -ENOENT) { if (dev->poll_mod_count != 0) @@ -1793,8 +1999,8 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, else goto stop_poll; } else if (rc < 0) { - nfc_dev_err(&dev->interface->dev, - "Error %d when running poll", rc); + nfc_err(&dev->interface->dev, + "Error %d when running poll\n", rc); goto stop_poll; } } @@ -1813,7 +2019,7 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, goto done; if (!dev->poll_mod_count) { - nfc_dev_dbg(&dev->interface->dev, "Polling has been stopped."); + dev_dbg(&dev->interface->dev, "Polling has been stopped\n"); goto done; } @@ -1826,7 +2032,7 @@ done: return rc; stop_poll: - nfc_dev_err(&dev->interface->dev, "Polling operation has been stopped"); + nfc_err(&dev->interface->dev, "Polling operation has been stopped\n"); pn533_poll_reset_mod_list(dev); dev->poll_protocols = 0; @@ -1856,8 +2062,13 @@ static int pn533_send_poll_frame(struct pn533 *dev) mod = dev->poll_mod_active[dev->poll_mod_curr]; - nfc_dev_dbg(&dev->interface->dev, "%s mod len %d\n", - __func__, mod->len); + dev_dbg(&dev->interface->dev, "%s mod len %d\n", + __func__, mod->len); + + if (dev->poll_dep) { + dev->poll_dep = 0; + return pn533_poll_dep(dev->nfc_dev); + } if (mod->len == 0) { /* Listen mode */ cmd_code = PN533_CMD_TG_INIT_AS_TARGET; @@ -1868,7 +2079,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) } if (!skb) { - nfc_dev_err(&dev->interface->dev, "Failed to allocate skb."); + nfc_err(&dev->interface->dev, "Failed to allocate skb\n"); return -ENOMEM; } @@ -1876,7 +2087,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) NULL); if (rc < 0) { dev_kfree_skb(skb); - nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); + nfc_err(&dev->interface->dev, "Polling loop error %d\n", rc); } return rc; @@ -1890,9 +2101,9 @@ static void pn533_wq_poll(struct work_struct *work) cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; - nfc_dev_dbg(&dev->interface->dev, - "%s cancel_listen %d modulation len %d", - __func__, dev->cancel_listen, cur_mod->len); + dev_dbg(&dev->interface->dev, + "%s cancel_listen %d modulation len %d\n", + __func__, dev->cancel_listen, cur_mod->len); if (dev->cancel_listen == 1) { dev->cancel_listen = 0; @@ -1913,21 +2124,23 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, u32 im_protocols, u32 tm_protocols) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); + struct pn533_poll_modulations *cur_mod; u8 rand_mod; + int rc; - nfc_dev_dbg(&dev->interface->dev, - "%s: im protocols 0x%x tm protocols 0x%x", - __func__, im_protocols, tm_protocols); + dev_dbg(&dev->interface->dev, + "%s: im protocols 0x%x tm protocols 0x%x\n", + __func__, im_protocols, tm_protocols); if (dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, - "Cannot poll with a target already activated"); + nfc_err(&dev->interface->dev, + "Cannot poll with a target already activated\n"); return -EBUSY; } if (dev->tgt_mode) { - nfc_dev_err(&dev->interface->dev, - "Cannot poll while already being activated"); + nfc_err(&dev->interface->dev, + "Cannot poll while already being activated\n"); return -EBUSY; } @@ -1946,20 +2159,26 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, rand_mod %= dev->poll_mod_count; dev->poll_mod_curr = rand_mod; - return pn533_send_poll_frame(dev); + cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; + + rc = pn533_send_poll_frame(dev); + + /* Start listen timer */ + if (!rc && cur_mod->len == 0 && dev->poll_mod_count > 1) + mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ); + + return rc; } static void pn533_stop_poll(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - del_timer(&dev->listen_timer); if (!dev->poll_mod_count) { - nfc_dev_dbg(&dev->interface->dev, - "Polling operation was not running"); + dev_dbg(&dev->interface->dev, + "Polling operation was not running\n"); return; } @@ -1973,11 +2192,10 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) struct pn533_cmd_activate_response *rsp; u16 gt_len; int rc; - struct sk_buff *skb; struct sk_buff *resp; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/ if (!skb) @@ -1993,8 +2211,8 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) rsp = (struct pn533_cmd_activate_response *)resp->data; rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { - nfc_dev_err(&dev->interface->dev, - "Target activation failed (error 0x%x)", rc); + nfc_err(&dev->interface->dev, + "Target activation failed (error 0x%x)\n", rc); dev_kfree_skb(resp); return -EIO; } @@ -2013,39 +2231,38 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, struct pn533 *dev = nfc_get_drvdata(nfc_dev); int rc; - nfc_dev_dbg(&dev->interface->dev, "%s - protocol=%u", __func__, - protocol); + dev_dbg(&dev->interface->dev, "%s: protocol=%u\n", __func__, protocol); if (dev->poll_mod_count) { - nfc_dev_err(&dev->interface->dev, - "Cannot activate while polling"); + nfc_err(&dev->interface->dev, + "Cannot activate while polling\n"); return -EBUSY; } if (dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, - "There is already an active target"); + nfc_err(&dev->interface->dev, + "There is already an active target\n"); return -EBUSY; } if (!dev->tgt_available_prots) { - nfc_dev_err(&dev->interface->dev, - "There is no available target to activate"); + nfc_err(&dev->interface->dev, + "There is no available target to activate\n"); return -EINVAL; } if (!(dev->tgt_available_prots & (1 << protocol))) { - nfc_dev_err(&dev->interface->dev, - "Target doesn't support requested proto %u", - protocol); + nfc_err(&dev->interface->dev, + "Target doesn't support requested proto %u\n", + protocol); return -EINVAL; } if (protocol == NFC_PROTO_NFC_DEP) { rc = pn533_activate_target_nfcdep(dev); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Activating target with DEP failed %d", rc); + nfc_err(&dev->interface->dev, + "Activating target with DEP failed %d\n", rc); return rc; } } @@ -2060,16 +2277,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, struct nfc_target *target) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - struct sk_buff *skb; struct sk_buff *resp; - int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (!dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, "There is no active target"); + nfc_err(&dev->interface->dev, "There is no active target\n"); return; } @@ -2088,8 +2303,8 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, rc = resp->data[0] & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) - nfc_dev_err(&dev->interface->dev, - "Error 0x%x when releasing the target", rc); + nfc_err(&dev->interface->dev, + "Error 0x%x when releasing the target\n", rc); dev_kfree_skb(resp); return; @@ -2111,8 +2326,8 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (dev->tgt_available_prots && !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { - nfc_dev_err(&dev->interface->dev, - "The target does not support DEP"); + nfc_err(&dev->interface->dev, + "The target does not support DEP\n"); rc = -EINVAL; goto error; } @@ -2121,15 +2336,15 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { - nfc_dev_err(&dev->interface->dev, - "Bringing DEP link up failed (error 0x%x)", rc); + nfc_err(&dev->interface->dev, + "Bringing DEP link up failed (error 0x%x)\n", rc); goto error; } if (!dev->tgt_available_prots) { struct nfc_target nfc_target; - nfc_dev_dbg(&dev->interface->dev, "Creating new target"); + dev_dbg(&dev->interface->dev, "Creating new target\n"); nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; nfc_target.nfcid1_len = 10; @@ -2158,7 +2373,6 @@ error: } static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf); -#define PASSIVE_DATA_LEN 5 static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, u8 comm_mode, u8 *gb, size_t gb_len) { @@ -2166,20 +2380,19 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, struct sk_buff *skb; int rc, skb_len; u8 *next, *arg, nfcid3[NFC_NFCID3_MAXSIZE]; - u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (dev->poll_mod_count) { - nfc_dev_err(&dev->interface->dev, - "Cannot bring the DEP link up while polling"); + nfc_err(&dev->interface->dev, + "Cannot bring the DEP link up while polling\n"); return -EBUSY; } if (dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, - "There is already an active target"); + nfc_err(&dev->interface->dev, + "There is already an active target\n"); return -EBUSY; } @@ -2249,7 +2462,7 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); pn533_poll_reset_mod_list(dev); @@ -2274,7 +2487,7 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) struct sk_buff *skb, *tmp, *t; unsigned int skb_len = 0, tmp_len = 0; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (skb_queue_empty(&dev->resp_q)) return NULL; @@ -2287,8 +2500,8 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) skb_queue_walk_safe(&dev->resp_q, tmp, t) skb_len += tmp->len; - nfc_dev_dbg(&dev->interface->dev, "%s total length %d\n", - __func__, skb_len); + dev_dbg(&dev->interface->dev, "%s total length %d\n", + __func__, skb_len); skb = alloc_skb(skb_len, GFP_KERNEL); if (skb == NULL) @@ -2315,7 +2528,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, int rc = 0; u8 status, ret, mi; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); @@ -2329,8 +2542,8 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, skb_pull(resp, sizeof(status)); if (ret != PN533_CMD_RET_SUCCESS) { - nfc_dev_err(&dev->interface->dev, - "Exchanging data failed (error 0x%x)", ret); + nfc_err(&dev->interface->dev, + "Exchanging data failed (error 0x%x)\n", ret); rc = -EIO; goto error; } @@ -2388,14 +2601,17 @@ static int pn533_fill_fragment_skbs(struct pn533 *dev, struct sk_buff *skb) break; } - /* Reserve the TG/MI byte */ - skb_reserve(frag, 1); + if (!dev->tgt_mode) { + /* Reserve the TG/MI byte */ + skb_reserve(frag, 1); - /* MI + TG */ - if (frag_size == PN533_CMD_DATAFRAME_MAXLEN) - *skb_push(frag, sizeof(u8)) = (PN533_CMD_MI_MASK | 1); - else - *skb_push(frag, sizeof(u8)) = 1; /* TG */ + /* MI + TG */ + if (frag_size == PN533_CMD_DATAFRAME_MAXLEN) + *skb_push(frag, sizeof(u8)) = + (PN533_CMD_MI_MASK | 1); + else + *skb_push(frag, sizeof(u8)) = 1; /* TG */ + } memcpy(skb_put(frag, frag_size), skb->data, frag_size); @@ -2420,11 +2636,11 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, struct pn533_data_exchange_arg *arg = NULL; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (!dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, - "Can't exchange data if there is no active target"); + nfc_err(&dev->interface->dev, + "Can't exchange data if there is no active target\n"); rc = -EINVAL; goto error; } @@ -2487,13 +2703,18 @@ static int pn533_tm_send_complete(struct pn533 *dev, void *arg, { u8 status; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); if (IS_ERR(resp)) return PTR_ERR(resp); status = resp->data[0]; + /* Prepare for the next round */ + if (skb_queue_len(&dev->fragment_skb) > 0) { + queue_work(dev->wq, &dev->mi_tm_tx_work); + return -EINPROGRESS; + } dev_kfree_skb(resp); if (status != 0) { @@ -2514,19 +2735,34 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) struct pn533 *dev = nfc_get_drvdata(nfc_dev); int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); + /* let's split in multiple chunks if size's too big */ if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { - nfc_dev_err(&dev->interface->dev, - "Data length greater than the max allowed: %d", - PN533_CMD_DATAEXCH_DATA_MAXLEN); - return -ENOSYS; + rc = pn533_fill_fragment_skbs(dev, skb); + if (rc <= 0) + goto error; + + /* get the first skb */ + skb = skb_dequeue(&dev->fragment_skb); + if (!skb) { + rc = -EIO; + goto error; + } + + rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_META_DATA, skb, + pn533_tm_send_complete, NULL); + } else { + /* Send th skb */ + rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_DATA, skb, + pn533_tm_send_complete, NULL); } - rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_DATA, skb, - pn533_tm_send_complete, NULL); - if (rc < 0) +error: + if (rc < 0) { dev_kfree_skb(skb); + skb_queue_purge(&dev->fragment_skb); + } return rc; } @@ -2534,11 +2770,10 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) static void pn533_wq_mi_recv(struct work_struct *work) { struct pn533 *dev = container_of(work, struct pn533, mi_rx_work); - struct sk_buff *skb; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN); if (!skb) @@ -2570,8 +2805,8 @@ static void pn533_wq_mi_recv(struct work_struct *work) if (rc == 0) /* success */ return; - nfc_dev_err(&dev->interface->dev, - "Error %d when trying to perform data_exchange", rc); + nfc_err(&dev->interface->dev, + "Error %d when trying to perform data_exchange\n", rc); dev_kfree_skb(skb); kfree(dev->cmd_complete_mi_arg); @@ -2587,7 +2822,7 @@ static void pn533_wq_mi_send(struct work_struct *work) struct sk_buff *skb; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); /* Grab the first skb in the queue */ skb = skb_dequeue(&dev->fragment_skb); @@ -2625,8 +2860,8 @@ static void pn533_wq_mi_send(struct work_struct *work) if (rc == 0) /* success */ return; - nfc_dev_err(&dev->interface->dev, - "Error %d when trying to perform data_exchange", rc); + nfc_err(&dev->interface->dev, + "Error %d when trying to perform data_exchange\n", rc); dev_kfree_skb(skb); kfree(dev->cmd_complete_dep_arg); @@ -2641,10 +2876,9 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, { struct sk_buff *skb; struct sk_buff *resp; - int skb_len; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */ @@ -2691,7 +2925,7 @@ static int pn533_pasori_fw_reset(struct pn533 *dev) struct sk_buff *skb; struct sk_buff *resp; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, sizeof(u8)); if (!skb) @@ -2717,7 +2951,7 @@ static void pn533_acr122_poweron_rdr_resp(struct urb *urb) { struct pn533_acr122_poweron_rdr_arg *arg = urb->context; - nfc_dev_dbg(&urb->dev->dev, "%s", __func__); + dev_dbg(&urb->dev->dev, "%s\n", __func__); print_hex_dump_debug("ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1, urb->transfer_buffer, urb->transfer_buffer_length, @@ -2737,7 +2971,7 @@ static int pn533_acr122_poweron_rdr(struct pn533 *dev) void *cntx; struct pn533_acr122_poweron_rdr_arg arg; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(&dev->interface->dev, "%s\n", __func__); init_completion(&arg.done); cntx = dev->in_urb->context; /* backup context */ @@ -2755,16 +2989,15 @@ static int pn533_acr122_poweron_rdr(struct pn533 *dev) rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Reader power on cmd error %d", rc); + nfc_err(&dev->interface->dev, + "Reader power on cmd error %d\n", rc); return rc; } rc = usb_submit_urb(dev->in_urb, GFP_KERNEL); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Can't submit for reader power on cmd response %d", - rc); + nfc_err(&dev->interface->dev, + "Can't submit reader poweron cmd response %d\n", rc); return rc; } @@ -2785,20 +3018,19 @@ static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf) rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD, (u8 *)&rf_field, 1); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error on setting RF field"); + nfc_err(&dev->interface->dev, "Error on setting RF field\n"); return rc; } return rc; } -int pn533_dev_up(struct nfc_dev *nfc_dev) +static int pn533_dev_up(struct nfc_dev *nfc_dev) { return pn533_rf_field(nfc_dev, 1); } -int pn533_dev_down(struct nfc_dev *nfc_dev) +static int pn533_dev_down(struct nfc_dev *nfc_dev) { return pn533_rf_field(nfc_dev, 0); } @@ -2839,16 +3071,16 @@ static int pn533_setup(struct pn533 *dev) break; default: - nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n", - dev->device_type); + nfc_err(&dev->interface->dev, "Unknown device type %d\n", + dev->device_type); return -EINVAL; } rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES, (u8 *)&max_retries, sizeof(max_retries)); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error on setting MAX_RETRIES config"); + nfc_err(&dev->interface->dev, + "Error on setting MAX_RETRIES config\n"); return rc; } @@ -2856,8 +3088,7 @@ static int pn533_setup(struct pn533 *dev) rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, (u8 *)&timing, sizeof(timing)); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error on setting RF timings"); + nfc_err(&dev->interface->dev, "Error on setting RF timings\n"); return rc; } @@ -2871,8 +3102,8 @@ static int pn533_setup(struct pn533 *dev) rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI, pasori_cfg, 3); if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error while settings PASORI config"); + nfc_err(&dev->interface->dev, + "Error while settings PASORI config\n"); return rc; } @@ -2917,8 +3148,8 @@ static int pn533_probe(struct usb_interface *interface, } if (!in_endpoint || !out_endpoint) { - nfc_dev_err(&interface->dev, - "Could not find bulk-in or bulk-out endpoint"); + nfc_err(&interface->dev, + "Could not find bulk-in or bulk-out endpoint\n"); rc = -ENODEV; goto error; } @@ -2941,6 +3172,8 @@ static int pn533_probe(struct usb_interface *interface, INIT_WORK(&dev->mi_rx_work, pn533_wq_mi_recv); INIT_WORK(&dev->mi_tx_work, pn533_wq_mi_send); INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); + INIT_WORK(&dev->mi_tm_rx_work, pn533_wq_tm_mi_recv); + INIT_WORK(&dev->mi_tm_tx_work, pn533_wq_tm_mi_send); INIT_DELAYED_WORK(&dev->poll_work, pn533_wq_poll); INIT_WORK(&dev->rf_work, pn533_wq_rf); dev->wq = alloc_ordered_workqueue("pn533", 0); @@ -2978,16 +3211,15 @@ static int pn533_probe(struct usb_interface *interface, rc = pn533_acr122_poweron_rdr(dev); if (rc < 0) { - nfc_dev_err(&dev->interface->dev, - "Couldn't poweron the reader (error %d)", - rc); + nfc_err(&dev->interface->dev, + "Couldn't poweron the reader (error %d)\n", rc); goto destroy_wq; } break; default: - nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n", - dev->device_type); + nfc_err(&dev->interface->dev, "Unknown device type %d\n", + dev->device_type); rc = -EINVAL; goto destroy_wq; } @@ -2997,9 +3229,9 @@ static int pn533_probe(struct usb_interface *interface, if (rc < 0) goto destroy_wq; - nfc_dev_info(&dev->interface->dev, - "NXP PN5%02X firmware ver %d.%d now attached", - fw_ver.ic, fw_ver.ver, fw_ver.rev); + nfc_info(&dev->interface->dev, + "NXP PN5%02X firmware ver %d.%d now attached\n", + fw_ver.ic, fw_ver.ver, fw_ver.rev); dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, @@ -3070,7 +3302,7 @@ static void pn533_disconnect(struct usb_interface *interface) usb_free_urb(dev->out_urb); kfree(dev); - nfc_dev_info(&interface->dev, "NXP PN533 NFC device disconnected"); + nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n"); } static struct usb_driver pn533_driver = { diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index 01e27d4bdd0..b158ee1c2ac 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/crc-ccitt.h> #include <linux/module.h> #include <linux/i2c.h> @@ -151,8 +153,7 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 }; int count = sizeof(rset_cmd); - pr_info(DRIVER_DESC ": %s\n", __func__); - dev_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n"); + nfc_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n"); /* Disable fw download */ gpio_set_value(phy->gpio_fw, 0); @@ -173,7 +174,7 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) dev_dbg(&phy->i2c_dev->dev, "Sending reset cmd\n"); ret = i2c_master_send(phy->i2c_dev, rset_cmd, count); if (ret == count) { - dev_info(&phy->i2c_dev->dev, + nfc_info(&phy->i2c_dev->dev, "nfc_en polarity : active %s\n", (polarity == 0 ? "low" : "high")); goto out; @@ -181,7 +182,7 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) } } - dev_err(&phy->i2c_dev->dev, + nfc_err(&phy->i2c_dev->dev, "Could not detect nfc_en polarity, fallback to active high\n"); out: @@ -201,7 +202,7 @@ static int pn544_hci_i2c_enable(void *phy_id) { struct pn544_i2c_phy *phy = phy_id; - pr_info(DRIVER_DESC ": %s\n", __func__); + pr_info("%s\n", __func__); pn544_hci_i2c_enable_mode(phy, PN544_HCI_MODE); @@ -214,8 +215,6 @@ static void pn544_hci_i2c_disable(void *phy_id) { struct pn544_i2c_phy *phy = phy_id; - pr_info(DRIVER_DESC ": %s\n", __func__); - gpio_set_value(phy->gpio_fw, 0); gpio_set_value(phy->gpio_en, !phy->en_polarity); usleep_range(10000, 15000); @@ -298,11 +297,9 @@ static int check_crc(u8 *buf, int buflen) crc = ~crc; if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) { - pr_err(PN544_HCI_I2C_DRIVER_NAME - ": CRC error 0x%x != 0x%x 0x%x\n", + pr_err("CRC error 0x%x != 0x%x 0x%x\n", crc, buf[len - 1], buf[len - 2]); - - pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); + pr_info("%s: BAD CRC\n", __func__); print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, 16, 2, buf, buflen, false); return -EPERM; @@ -328,13 +325,13 @@ static int pn544_hci_i2c_read(struct pn544_i2c_phy *phy, struct sk_buff **skb) r = i2c_master_recv(client, &len, 1); if (r != 1) { - dev_err(&client->dev, "cannot read len byte\n"); + nfc_err(&client->dev, "cannot read len byte\n"); return -EREMOTEIO; } if ((len < (PN544_HCI_I2C_LLC_MIN_SIZE - 1)) || (len > (PN544_HCI_I2C_LLC_MAX_SIZE - 1))) { - dev_err(&client->dev, "invalid len byte\n"); + nfc_err(&client->dev, "invalid len byte\n"); r = -EBADMSG; goto flush; } @@ -386,7 +383,7 @@ static int pn544_hci_i2c_fw_read_status(struct pn544_i2c_phy *phy) r = i2c_master_recv(client, (char *) &response, sizeof(response)); if (r != sizeof(response)) { - dev_err(&client->dev, "cannot read fw status\n"); + nfc_err(&client->dev, "cannot read fw status\n"); return -EIO; } @@ -478,8 +475,7 @@ static int pn544_hci_i2c_fw_download(void *phy_id, const char *firmware_name) { struct pn544_i2c_phy *phy = phy_id; - pr_info(DRIVER_DESC ": Starting Firmware Download (%s)\n", - firmware_name); + pr_info("Starting Firmware Download (%s)\n", firmware_name); strcpy(phy->firmware_name, firmware_name); @@ -493,7 +489,7 @@ static int pn544_hci_i2c_fw_download(void *phy_id, const char *firmware_name) static void pn544_hci_i2c_fw_work_complete(struct pn544_i2c_phy *phy, int result) { - pr_info(DRIVER_DESC ": Firmware Download Complete, result=%d\n", result); + pr_info("Firmware Download Complete, result=%d\n", result); pn544_hci_i2c_disable(phy); @@ -694,14 +690,14 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, dev_dbg(&client->dev, "IRQ: %d\n", client->irq); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(&client->dev, "Need I2C_FUNC_I2C\n"); + nfc_err(&client->dev, "Need I2C_FUNC_I2C\n"); return -ENODEV; } phy = devm_kzalloc(&client->dev, sizeof(struct pn544_i2c_phy), GFP_KERNEL); if (!phy) { - dev_err(&client->dev, + nfc_err(&client->dev, "Cannot allocate memory for pn544 i2c phy.\n"); return -ENOMEM; } @@ -714,18 +710,18 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, pdata = client->dev.platform_data; if (pdata == NULL) { - dev_err(&client->dev, "No platform data\n"); + nfc_err(&client->dev, "No platform data\n"); return -EINVAL; } if (pdata->request_resources == NULL) { - dev_err(&client->dev, "request_resources() missing\n"); + nfc_err(&client->dev, "request_resources() missing\n"); return -EINVAL; } r = pdata->request_resources(client); if (r) { - dev_err(&client->dev, "Cannot get platform resources\n"); + nfc_err(&client->dev, "Cannot get platform resources\n"); return r; } @@ -739,7 +735,7 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, IRQF_TRIGGER_RISING | IRQF_ONESHOT, PN544_HCI_I2C_DRIVER_NAME, phy); if (r < 0) { - dev_err(&client->dev, "Unable to register IRQ handler\n"); + nfc_err(&client->dev, "Unable to register IRQ handler\n"); goto err_rti; } diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 078e62feba1..74cfa0a88b9 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/delay.h> #include <linux/slab.h> #include <linux/module.h> @@ -41,6 +43,7 @@ enum pn544_state { /* Proprietary commands */ #define PN544_WRITE 0x3f +#define PN544_TEST_SWP 0x21 /* Proprietary gates, events, commands and registers */ @@ -81,14 +84,17 @@ enum pn544_state { #define PN544_PL_NFCT_DEACTIVATED 0x09 #define PN544_SWP_MGMT_GATE 0xA0 +#define PN544_SWP_DEFAULT_MODE 0x01 #define PN544_NFC_WI_MGMT_GATE 0xA1 +#define PN544_NFC_ESE_DEFAULT_MODE 0x01 #define PN544_HCI_EVT_SND_DATA 0x01 #define PN544_HCI_EVT_ACTIVATED 0x02 #define PN544_HCI_EVT_DEACTIVATED 0x03 #define PN544_HCI_EVT_RCV_DATA 0x04 #define PN544_HCI_EVT_CONTINUE_MI 0x05 +#define PN544_HCI_EVT_SWITCH_MODE 0x03 #define PN544_HCI_CMD_ATTREQUEST 0x12 #define PN544_HCI_CMD_CONTINUE_ACTIVATION 0x13 @@ -187,13 +193,6 @@ static int pn544_hci_ready(struct nfc_hci_dev *hdev) {{0x9e, 0xb4}, 0x00}, - {{0x9e, 0xd9}, 0xff}, - {{0x9e, 0xda}, 0xff}, - {{0x9e, 0xdb}, 0x23}, - {{0x9e, 0xdc}, 0x21}, - {{0x9e, 0xdd}, 0x22}, - {{0x9e, 0xde}, 0x24}, - {{0x9c, 0x01}, 0x08}, {{0x9e, 0xaa}, 0x01}, @@ -394,7 +393,7 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { hdev->gb = nfc_get_local_general_bytes(hdev->ndev, &hdev->gb_len); - pr_debug("generate local bytes %p", hdev->gb); + pr_debug("generate local bytes %p\n", hdev->gb); if (hdev->gb == NULL || hdev->gb_len == 0) { im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; @@ -696,7 +695,7 @@ static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, struct nfc_target *target) { - pr_debug("supported protocol %d", target->supported_protocols); + pr_debug("supported protocol %d\b", target->supported_protocols); if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_ISO14443_B_MASK)) { return nfc_hci_send_cmd(hdev, target->hci_reader_gate, @@ -733,7 +732,7 @@ static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, struct sk_buff *rgb_skb = NULL; int r; - pr_debug("hci event %d", event); + pr_debug("hci event %d\n", event); switch (event) { case PN544_HCI_EVT_ACTIVATED: if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) { @@ -764,7 +763,7 @@ static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, } if (skb->data[0] != 0) { - pr_debug("data0 %d", skb->data[0]); + pr_debug("data0 %d\n", skb->data[0]); r = -EPROTO; goto exit; } @@ -792,6 +791,108 @@ static int pn544_hci_fw_download(struct nfc_hci_dev *hdev, return info->fw_download(info->phy_id, firmware_name); } +static int pn544_hci_discover_se(struct nfc_hci_dev *hdev) +{ + u32 se_idx = 0; + u8 ese_mode = 0x01; /* Default mode */ + struct sk_buff *res_skb; + int r; + + r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_TEST_SWP, + NULL, 0, &res_skb); + + if (r == 0) { + if (res_skb->len == 2 && res_skb->data[0] == 0x00) + nfc_add_se(hdev->ndev, se_idx++, NFC_SE_UICC); + + kfree_skb(res_skb); + } + + r = nfc_hci_send_event(hdev, PN544_NFC_WI_MGMT_GATE, + PN544_HCI_EVT_SWITCH_MODE, + &ese_mode, 1); + if (r == 0) + nfc_add_se(hdev->ndev, se_idx++, NFC_SE_EMBEDDED); + + return !se_idx; +} + +#define PN544_SE_MODE_OFF 0x00 +#define PN544_SE_MODE_ON 0x01 +static int pn544_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx) +{ + struct nfc_se *se; + u8 enable = PN544_SE_MODE_ON; + static struct uicc_gatelist { + u8 head; + u8 adr[2]; + u8 value; + } uicc_gatelist[] = { + {0x00, {0x9e, 0xd9}, 0x23}, + {0x00, {0x9e, 0xda}, 0x21}, + {0x00, {0x9e, 0xdb}, 0x22}, + {0x00, {0x9e, 0xdc}, 0x24}, + }; + struct uicc_gatelist *p = uicc_gatelist; + int count = ARRAY_SIZE(uicc_gatelist); + struct sk_buff *res_skb; + int r; + + se = nfc_find_se(hdev->ndev, se_idx); + + switch (se->type) { + case NFC_SE_UICC: + while (count--) { + r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, + PN544_WRITE, (u8 *)p, 4, &res_skb); + if (r < 0) + return r; + + if (res_skb->len != 1) { + kfree_skb(res_skb); + return -EPROTO; + } + + if (res_skb->data[0] != p->value) { + kfree_skb(res_skb); + return -EIO; + } + + kfree_skb(res_skb); + + p++; + } + + return nfc_hci_set_param(hdev, PN544_SWP_MGMT_GATE, + PN544_SWP_DEFAULT_MODE, &enable, 1); + case NFC_SE_EMBEDDED: + return nfc_hci_set_param(hdev, PN544_NFC_WI_MGMT_GATE, + PN544_NFC_ESE_DEFAULT_MODE, &enable, 1); + + default: + return -EINVAL; + } +} + +static int pn544_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx) +{ + struct nfc_se *se; + u8 disable = PN544_SE_MODE_OFF; + + se = nfc_find_se(hdev->ndev, se_idx); + + switch (se->type) { + case NFC_SE_UICC: + return nfc_hci_set_param(hdev, PN544_SWP_MGMT_GATE, + PN544_SWP_DEFAULT_MODE, &disable, 1); + case NFC_SE_EMBEDDED: + return nfc_hci_set_param(hdev, PN544_NFC_WI_MGMT_GATE, + PN544_NFC_ESE_DEFAULT_MODE, &disable, 1); + default: + return -EINVAL; + } +} + static struct nfc_hci_ops pn544_hci_ops = { .open = pn544_hci_open, .close = pn544_hci_close, @@ -807,6 +908,9 @@ static struct nfc_hci_ops pn544_hci_ops = { .check_presence = pn544_hci_check_presence, .event_received = pn544_hci_event_received, .fw_download = pn544_hci_fw_download, + .discover_se = pn544_hci_discover_se, + .enable_se = pn544_hci_enable_se, + .disable_se = pn544_hci_disable_se, }; int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, @@ -820,7 +924,6 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL); if (!info) { - pr_err("Cannot allocate memory for pn544_hci_info.\n"); r = -ENOMEM; goto err_info_alloc; } @@ -853,7 +956,7 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, phy_headroom + PN544_CMDS_HEADROOM, phy_tailroom, phy_payload); if (!info->hdev) { - pr_err("Cannot allocate nfc hdev.\n"); + pr_err("Cannot allocate nfc hdev\n"); r = -ENOMEM; goto err_alloc_hdev; } diff --git a/drivers/nfc/port100.c b/drivers/nfc/port100.c new file mode 100644 index 00000000000..8a0571eb262 --- /dev/null +++ b/drivers/nfc/port100.c @@ -0,0 +1,1529 @@ +/* + * Sony NFC Port-100 Series driver + * Copyright (c) 2013, Intel Corporation. + * + * Partly based/Inspired by Stephen Tiedemann's nfcpy + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include <linux/module.h> +#include <linux/usb.h> +#include <net/nfc/digital.h> + +#define VERSION "0.1" + +#define SONY_VENDOR_ID 0x054c +#define RCS380_PRODUCT_ID 0x06c1 + +#define PORT100_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ + NFC_PROTO_MIFARE_MASK | \ + NFC_PROTO_FELICA_MASK | \ + NFC_PROTO_NFC_DEP_MASK) + +#define PORT100_CAPABILITIES (NFC_DIGITAL_DRV_CAPS_IN_CRC | \ + NFC_DIGITAL_DRV_CAPS_TG_CRC) + +/* Standard port100 frame definitions */ +#define PORT100_FRAME_HEADER_LEN (sizeof(struct port100_frame) \ + + 2) /* data[0] CC, data[1] SCC */ +#define PORT100_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/ + +#define PORT100_COMM_RF_HEAD_MAX_LEN (sizeof(struct port100_tg_comm_rf_cmd)) + +/* + * Max extended frame payload len, excluding CC and SCC + * which are already in PORT100_FRAME_HEADER_LEN. + */ +#define PORT100_FRAME_MAX_PAYLOAD_LEN 1001 + +#define PORT100_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2), + Postamble (1) */ +static u8 ack_frame[PORT100_FRAME_ACK_SIZE] = { + 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 +}; + +#define PORT100_FRAME_CHECKSUM(f) (f->data[le16_to_cpu(f->datalen)]) +#define PORT100_FRAME_POSTAMBLE(f) (f->data[le16_to_cpu(f->datalen) + 1]) + +/* start of frame */ +#define PORT100_FRAME_SOF 0x00FF +#define PORT100_FRAME_EXT 0xFFFF +#define PORT100_FRAME_ACK 0x00FF + +/* Port-100 command: in or out */ +#define PORT100_FRAME_DIRECTION(f) (f->data[0]) /* CC */ +#define PORT100_FRAME_DIR_OUT 0xD6 +#define PORT100_FRAME_DIR_IN 0xD7 + +/* Port-100 sub-command */ +#define PORT100_FRAME_CMD(f) (f->data[1]) /* SCC */ + +#define PORT100_CMD_GET_FIRMWARE_VERSION 0x20 +#define PORT100_CMD_GET_COMMAND_TYPE 0x28 +#define PORT100_CMD_SET_COMMAND_TYPE 0x2A + +#define PORT100_CMD_IN_SET_RF 0x00 +#define PORT100_CMD_IN_SET_PROTOCOL 0x02 +#define PORT100_CMD_IN_COMM_RF 0x04 + +#define PORT100_CMD_TG_SET_RF 0x40 +#define PORT100_CMD_TG_SET_PROTOCOL 0x42 +#define PORT100_CMD_TG_SET_RF_OFF 0x46 +#define PORT100_CMD_TG_COMM_RF 0x48 + +#define PORT100_CMD_SWITCH_RF 0x06 + +#define PORT100_CMD_RESPONSE(cmd) (cmd + 1) + +#define PORT100_CMD_TYPE_IS_SUPPORTED(mask, cmd_type) \ + ((mask) & (0x01 << (cmd_type))) +#define PORT100_CMD_TYPE_0 0 +#define PORT100_CMD_TYPE_1 1 + +#define PORT100_CMD_STATUS_OK 0x00 +#define PORT100_CMD_STATUS_TIMEOUT 0x80 + +#define PORT100_MDAA_TGT_HAS_BEEN_ACTIVATED_MASK 0x01 +#define PORT100_MDAA_TGT_WAS_ACTIVATED_MASK 0x02 + +struct port100; + +typedef void (*port100_send_async_complete_t)(struct port100 *dev, void *arg, + struct sk_buff *resp); + +/** + * Setting sets structure for in_set_rf command + * + * @in_*_set_number: Represent the entry indexes in the port-100 RF Base Table. + * This table contains multiple RF setting sets required for RF + * communication. + * + * @in_*_comm_type: Theses fields set the communication type to be used. + */ +struct port100_in_rf_setting { + u8 in_send_set_number; + u8 in_send_comm_type; + u8 in_recv_set_number; + u8 in_recv_comm_type; +} __packed; + +#define PORT100_COMM_TYPE_IN_212F 0x01 +#define PORT100_COMM_TYPE_IN_424F 0x02 +#define PORT100_COMM_TYPE_IN_106A 0x03 + +static const struct port100_in_rf_setting in_rf_settings[] = { + [NFC_DIGITAL_RF_TECH_212F] = { + .in_send_set_number = 1, + .in_send_comm_type = PORT100_COMM_TYPE_IN_212F, + .in_recv_set_number = 15, + .in_recv_comm_type = PORT100_COMM_TYPE_IN_212F, + }, + [NFC_DIGITAL_RF_TECH_424F] = { + .in_send_set_number = 1, + .in_send_comm_type = PORT100_COMM_TYPE_IN_424F, + .in_recv_set_number = 15, + .in_recv_comm_type = PORT100_COMM_TYPE_IN_424F, + }, + [NFC_DIGITAL_RF_TECH_106A] = { + .in_send_set_number = 2, + .in_send_comm_type = PORT100_COMM_TYPE_IN_106A, + .in_recv_set_number = 15, + .in_recv_comm_type = PORT100_COMM_TYPE_IN_106A, + }, +}; + +/** + * Setting sets structure for tg_set_rf command + * + * @tg_set_number: Represents the entry index in the port-100 RF Base Table. + * This table contains multiple RF setting sets required for RF + * communication. this field is used for both send and receive + * settings. + * + * @tg_comm_type: Sets the communication type to be used to send and receive + * data. + */ +struct port100_tg_rf_setting { + u8 tg_set_number; + u8 tg_comm_type; +} __packed; + +#define PORT100_COMM_TYPE_TG_106A 0x0B +#define PORT100_COMM_TYPE_TG_212F 0x0C +#define PORT100_COMM_TYPE_TG_424F 0x0D + +static const struct port100_tg_rf_setting tg_rf_settings[] = { + [NFC_DIGITAL_RF_TECH_106A] = { + .tg_set_number = 8, + .tg_comm_type = PORT100_COMM_TYPE_TG_106A, + }, + [NFC_DIGITAL_RF_TECH_212F] = { + .tg_set_number = 8, + .tg_comm_type = PORT100_COMM_TYPE_TG_212F, + }, + [NFC_DIGITAL_RF_TECH_424F] = { + .tg_set_number = 8, + .tg_comm_type = PORT100_COMM_TYPE_TG_424F, + }, +}; + +#define PORT100_IN_PROT_INITIAL_GUARD_TIME 0x00 +#define PORT100_IN_PROT_ADD_CRC 0x01 +#define PORT100_IN_PROT_CHECK_CRC 0x02 +#define PORT100_IN_PROT_MULTI_CARD 0x03 +#define PORT100_IN_PROT_ADD_PARITY 0x04 +#define PORT100_IN_PROT_CHECK_PARITY 0x05 +#define PORT100_IN_PROT_BITWISE_AC_RECV_MODE 0x06 +#define PORT100_IN_PROT_VALID_BIT_NUMBER 0x07 +#define PORT100_IN_PROT_CRYPTO1 0x08 +#define PORT100_IN_PROT_ADD_SOF 0x09 +#define PORT100_IN_PROT_CHECK_SOF 0x0A +#define PORT100_IN_PROT_ADD_EOF 0x0B +#define PORT100_IN_PROT_CHECK_EOF 0x0C +#define PORT100_IN_PROT_DEAF_TIME 0x0E +#define PORT100_IN_PROT_CRM 0x0F +#define PORT100_IN_PROT_CRM_MIN_LEN 0x10 +#define PORT100_IN_PROT_T1_TAG_FRAME 0x11 +#define PORT100_IN_PROT_RFCA 0x12 +#define PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR 0x13 +#define PORT100_IN_PROT_END 0x14 + +#define PORT100_IN_MAX_NUM_PROTOCOLS 19 + +#define PORT100_TG_PROT_TU 0x00 +#define PORT100_TG_PROT_RF_OFF 0x01 +#define PORT100_TG_PROT_CRM 0x02 +#define PORT100_TG_PROT_END 0x03 + +#define PORT100_TG_MAX_NUM_PROTOCOLS 3 + +struct port100_protocol { + u8 number; + u8 value; +} __packed; + +static struct port100_protocol +in_protocols[][PORT100_IN_MAX_NUM_PROTOCOLS + 1] = { + [NFC_DIGITAL_FRAMING_NFCA_SHORT] = { + { PORT100_IN_PROT_INITIAL_GUARD_TIME, 6 }, + { PORT100_IN_PROT_ADD_CRC, 0 }, + { PORT100_IN_PROT_CHECK_CRC, 0 }, + { PORT100_IN_PROT_MULTI_CARD, 0 }, + { PORT100_IN_PROT_ADD_PARITY, 0 }, + { PORT100_IN_PROT_CHECK_PARITY, 1 }, + { PORT100_IN_PROT_BITWISE_AC_RECV_MODE, 0 }, + { PORT100_IN_PROT_VALID_BIT_NUMBER, 7 }, + { PORT100_IN_PROT_CRYPTO1, 0 }, + { PORT100_IN_PROT_ADD_SOF, 0 }, + { PORT100_IN_PROT_CHECK_SOF, 0 }, + { PORT100_IN_PROT_ADD_EOF, 0 }, + { PORT100_IN_PROT_CHECK_EOF, 0 }, + { PORT100_IN_PROT_DEAF_TIME, 4 }, + { PORT100_IN_PROT_CRM, 0 }, + { PORT100_IN_PROT_CRM_MIN_LEN, 0 }, + { PORT100_IN_PROT_T1_TAG_FRAME, 0 }, + { PORT100_IN_PROT_RFCA, 0 }, + { PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR, 6 }, + { PORT100_IN_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCA_STANDARD] = { + { PORT100_IN_PROT_INITIAL_GUARD_TIME, 6 }, + { PORT100_IN_PROT_ADD_CRC, 0 }, + { PORT100_IN_PROT_CHECK_CRC, 0 }, + { PORT100_IN_PROT_MULTI_CARD, 0 }, + { PORT100_IN_PROT_ADD_PARITY, 1 }, + { PORT100_IN_PROT_CHECK_PARITY, 1 }, + { PORT100_IN_PROT_BITWISE_AC_RECV_MODE, 0 }, + { PORT100_IN_PROT_VALID_BIT_NUMBER, 8 }, + { PORT100_IN_PROT_CRYPTO1, 0 }, + { PORT100_IN_PROT_ADD_SOF, 0 }, + { PORT100_IN_PROT_CHECK_SOF, 0 }, + { PORT100_IN_PROT_ADD_EOF, 0 }, + { PORT100_IN_PROT_CHECK_EOF, 0 }, + { PORT100_IN_PROT_DEAF_TIME, 4 }, + { PORT100_IN_PROT_CRM, 0 }, + { PORT100_IN_PROT_CRM_MIN_LEN, 0 }, + { PORT100_IN_PROT_T1_TAG_FRAME, 0 }, + { PORT100_IN_PROT_RFCA, 0 }, + { PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR, 6 }, + { PORT100_IN_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A] = { + { PORT100_IN_PROT_INITIAL_GUARD_TIME, 6 }, + { PORT100_IN_PROT_ADD_CRC, 1 }, + { PORT100_IN_PROT_CHECK_CRC, 1 }, + { PORT100_IN_PROT_MULTI_CARD, 0 }, + { PORT100_IN_PROT_ADD_PARITY, 1 }, + { PORT100_IN_PROT_CHECK_PARITY, 1 }, + { PORT100_IN_PROT_BITWISE_AC_RECV_MODE, 0 }, + { PORT100_IN_PROT_VALID_BIT_NUMBER, 8 }, + { PORT100_IN_PROT_CRYPTO1, 0 }, + { PORT100_IN_PROT_ADD_SOF, 0 }, + { PORT100_IN_PROT_CHECK_SOF, 0 }, + { PORT100_IN_PROT_ADD_EOF, 0 }, + { PORT100_IN_PROT_CHECK_EOF, 0 }, + { PORT100_IN_PROT_DEAF_TIME, 4 }, + { PORT100_IN_PROT_CRM, 0 }, + { PORT100_IN_PROT_CRM_MIN_LEN, 0 }, + { PORT100_IN_PROT_T1_TAG_FRAME, 0 }, + { PORT100_IN_PROT_RFCA, 0 }, + { PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR, 6 }, + { PORT100_IN_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCA_T1T] = { + /* nfc_digital_framing_nfca_short */ + { PORT100_IN_PROT_ADD_CRC, 2 }, + { PORT100_IN_PROT_CHECK_CRC, 2 }, + { PORT100_IN_PROT_VALID_BIT_NUMBER, 8 }, + { PORT100_IN_PROT_T1_TAG_FRAME, 2 }, + { PORT100_IN_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCA_T2T] = { + /* nfc_digital_framing_nfca_standard */ + { PORT100_IN_PROT_ADD_CRC, 1 }, + { PORT100_IN_PROT_CHECK_CRC, 0 }, + { PORT100_IN_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCA_NFC_DEP] = { + /* nfc_digital_framing_nfca_standard */ + { PORT100_IN_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCF] = { + { PORT100_IN_PROT_INITIAL_GUARD_TIME, 18 }, + { PORT100_IN_PROT_ADD_CRC, 1 }, + { PORT100_IN_PROT_CHECK_CRC, 1 }, + { PORT100_IN_PROT_MULTI_CARD, 0 }, + { PORT100_IN_PROT_ADD_PARITY, 0 }, + { PORT100_IN_PROT_CHECK_PARITY, 0 }, + { PORT100_IN_PROT_BITWISE_AC_RECV_MODE, 0 }, + { PORT100_IN_PROT_VALID_BIT_NUMBER, 8 }, + { PORT100_IN_PROT_CRYPTO1, 0 }, + { PORT100_IN_PROT_ADD_SOF, 0 }, + { PORT100_IN_PROT_CHECK_SOF, 0 }, + { PORT100_IN_PROT_ADD_EOF, 0 }, + { PORT100_IN_PROT_CHECK_EOF, 0 }, + { PORT100_IN_PROT_DEAF_TIME, 4 }, + { PORT100_IN_PROT_CRM, 0 }, + { PORT100_IN_PROT_CRM_MIN_LEN, 0 }, + { PORT100_IN_PROT_T1_TAG_FRAME, 0 }, + { PORT100_IN_PROT_RFCA, 0 }, + { PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR, 6 }, + { PORT100_IN_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCF_T3T] = { + /* nfc_digital_framing_nfcf */ + { PORT100_IN_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCF_NFC_DEP] = { + /* nfc_digital_framing_nfcf */ + { PORT100_IN_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED] = { + { PORT100_IN_PROT_END, 0 }, + }, +}; + +static struct port100_protocol +tg_protocols[][PORT100_TG_MAX_NUM_PROTOCOLS + 1] = { + [NFC_DIGITAL_FRAMING_NFCA_SHORT] = { + { PORT100_TG_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCA_STANDARD] = { + { PORT100_TG_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A] = { + { PORT100_TG_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCA_T1T] = { + { PORT100_TG_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCA_T2T] = { + { PORT100_TG_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCA_NFC_DEP] = { + { PORT100_TG_PROT_TU, 1 }, + { PORT100_TG_PROT_RF_OFF, 0 }, + { PORT100_TG_PROT_CRM, 7 }, + { PORT100_TG_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCF] = { + { PORT100_TG_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCF_T3T] = { + { PORT100_TG_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFCF_NFC_DEP] = { + { PORT100_TG_PROT_TU, 1 }, + { PORT100_TG_PROT_RF_OFF, 0 }, + { PORT100_TG_PROT_CRM, 7 }, + { PORT100_TG_PROT_END, 0 }, + }, + [NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED] = { + { PORT100_TG_PROT_RF_OFF, 1 }, + { PORT100_TG_PROT_END, 0 }, + }, +}; + +struct port100 { + struct nfc_digital_dev *nfc_digital_dev; + + int skb_headroom; + int skb_tailroom; + + struct usb_device *udev; + struct usb_interface *interface; + + struct urb *out_urb; + struct urb *in_urb; + + struct work_struct cmd_complete_work; + + u8 cmd_type; + + /* The digital stack serializes commands to be sent. There is no need + * for any queuing/locking mechanism at driver level. + */ + struct port100_cmd *cmd; +}; + +struct port100_cmd { + u8 code; + int status; + struct sk_buff *req; + struct sk_buff *resp; + int resp_len; + port100_send_async_complete_t complete_cb; + void *complete_cb_context; +}; + +struct port100_frame { + u8 preamble; + __be16 start_frame; + __be16 extended_frame; + __le16 datalen; + u8 datalen_checksum; + u8 data[]; +} __packed; + +struct port100_ack_frame { + u8 preamble; + __be16 start_frame; + __be16 ack_frame; + u8 postambule; +} __packed; + +struct port100_cb_arg { + nfc_digital_cmd_complete_t complete_cb; + void *complete_arg; + u8 mdaa; +}; + +struct port100_tg_comm_rf_cmd { + __le16 guard_time; + __le16 send_timeout; + u8 mdaa; + u8 nfca_param[6]; + u8 nfcf_param[18]; + u8 mf_halted; + u8 arae_flag; + __le16 recv_timeout; + u8 data[]; +} __packed; + +struct port100_tg_comm_rf_res { + u8 comm_type; + u8 ar_status; + u8 target_activated; + __le32 status; + u8 data[]; +} __packed; + +/* The rule: value + checksum = 0 */ +static inline u8 port100_checksum(u16 value) +{ + return ~(((u8 *)&value)[0] + ((u8 *)&value)[1]) + 1; +} + +/* The rule: sum(data elements) + checksum = 0 */ +static u8 port100_data_checksum(u8 *data, int datalen) +{ + u8 sum = 0; + int i; + + for (i = 0; i < datalen; i++) + sum += data[i]; + + return port100_checksum(sum); +} + +static void port100_tx_frame_init(void *_frame, u8 cmd_code) +{ + struct port100_frame *frame = _frame; + + frame->preamble = 0; + frame->start_frame = cpu_to_be16(PORT100_FRAME_SOF); + frame->extended_frame = cpu_to_be16(PORT100_FRAME_EXT); + PORT100_FRAME_DIRECTION(frame) = PORT100_FRAME_DIR_OUT; + PORT100_FRAME_CMD(frame) = cmd_code; + frame->datalen = cpu_to_le16(2); +} + +static void port100_tx_frame_finish(void *_frame) +{ + struct port100_frame *frame = _frame; + + frame->datalen_checksum = port100_checksum(le16_to_cpu(frame->datalen)); + + PORT100_FRAME_CHECKSUM(frame) = + port100_data_checksum(frame->data, le16_to_cpu(frame->datalen)); + + PORT100_FRAME_POSTAMBLE(frame) = 0; +} + +static void port100_tx_update_payload_len(void *_frame, int len) +{ + struct port100_frame *frame = _frame; + + frame->datalen = cpu_to_le16(le16_to_cpu(frame->datalen) + len); +} + +static bool port100_rx_frame_is_valid(void *_frame) +{ + u8 checksum; + struct port100_frame *frame = _frame; + + if (frame->start_frame != cpu_to_be16(PORT100_FRAME_SOF) || + frame->extended_frame != cpu_to_be16(PORT100_FRAME_EXT)) + return false; + + checksum = port100_checksum(le16_to_cpu(frame->datalen)); + if (checksum != frame->datalen_checksum) + return false; + + checksum = port100_data_checksum(frame->data, + le16_to_cpu(frame->datalen)); + if (checksum != PORT100_FRAME_CHECKSUM(frame)) + return false; + + return true; +} + +static bool port100_rx_frame_is_ack(struct port100_ack_frame *frame) +{ + return (frame->start_frame == cpu_to_be16(PORT100_FRAME_SOF) && + frame->ack_frame == cpu_to_be16(PORT100_FRAME_ACK)); +} + +static inline int port100_rx_frame_size(void *frame) +{ + struct port100_frame *f = frame; + + return sizeof(struct port100_frame) + le16_to_cpu(f->datalen) + + PORT100_FRAME_TAIL_LEN; +} + +static bool port100_rx_frame_is_cmd_response(struct port100 *dev, void *frame) +{ + struct port100_frame *f = frame; + + return (PORT100_FRAME_CMD(f) == PORT100_CMD_RESPONSE(dev->cmd->code)); +} + +static void port100_recv_response(struct urb *urb) +{ + struct port100 *dev = urb->context; + struct port100_cmd *cmd = dev->cmd; + u8 *in_frame; + + cmd->status = urb->status; + + switch (urb->status) { + case 0: + break; /* success */ + case -ECONNRESET: + case -ENOENT: + nfc_err(&dev->interface->dev, + "The urb has been canceled (status %d)", urb->status); + goto sched_wq; + case -ESHUTDOWN: + default: + nfc_err(&dev->interface->dev, "Urb failure (status %d)", + urb->status); + goto sched_wq; + } + + in_frame = dev->in_urb->transfer_buffer; + + if (!port100_rx_frame_is_valid(in_frame)) { + nfc_err(&dev->interface->dev, "Received an invalid frame"); + cmd->status = -EIO; + goto sched_wq; + } + + print_hex_dump_debug("PORT100 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame, + port100_rx_frame_size(in_frame), false); + + if (!port100_rx_frame_is_cmd_response(dev, in_frame)) { + nfc_err(&dev->interface->dev, + "It's not the response to the last command"); + cmd->status = -EIO; + goto sched_wq; + } + +sched_wq: + schedule_work(&dev->cmd_complete_work); +} + +static int port100_submit_urb_for_response(struct port100 *dev, gfp_t flags) +{ + dev->in_urb->complete = port100_recv_response; + + return usb_submit_urb(dev->in_urb, flags); +} + +static void port100_recv_ack(struct urb *urb) +{ + struct port100 *dev = urb->context; + struct port100_cmd *cmd = dev->cmd; + struct port100_ack_frame *in_frame; + int rc; + + cmd->status = urb->status; + + switch (urb->status) { + case 0: + break; /* success */ + case -ECONNRESET: + case -ENOENT: + nfc_err(&dev->interface->dev, + "The urb has been stopped (status %d)", urb->status); + goto sched_wq; + case -ESHUTDOWN: + default: + nfc_err(&dev->interface->dev, "Urb failure (status %d)", + urb->status); + goto sched_wq; + } + + in_frame = dev->in_urb->transfer_buffer; + + if (!port100_rx_frame_is_ack(in_frame)) { + nfc_err(&dev->interface->dev, "Received an invalid ack"); + cmd->status = -EIO; + goto sched_wq; + } + + rc = port100_submit_urb_for_response(dev, GFP_ATOMIC); + if (rc) { + nfc_err(&dev->interface->dev, + "usb_submit_urb failed with result %d", rc); + cmd->status = rc; + goto sched_wq; + } + + return; + +sched_wq: + schedule_work(&dev->cmd_complete_work); +} + +static int port100_submit_urb_for_ack(struct port100 *dev, gfp_t flags) +{ + dev->in_urb->complete = port100_recv_ack; + + return usb_submit_urb(dev->in_urb, flags); +} + +static int port100_send_ack(struct port100 *dev) +{ + int rc; + + dev->out_urb->transfer_buffer = ack_frame; + dev->out_urb->transfer_buffer_length = sizeof(ack_frame); + rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); + + return rc; +} + +static int port100_send_frame_async(struct port100 *dev, struct sk_buff *out, + struct sk_buff *in, int in_len) +{ + int rc; + + dev->out_urb->transfer_buffer = out->data; + dev->out_urb->transfer_buffer_length = out->len; + + dev->in_urb->transfer_buffer = in->data; + dev->in_urb->transfer_buffer_length = in_len; + + print_hex_dump_debug("PORT100 TX: ", DUMP_PREFIX_NONE, 16, 1, + out->data, out->len, false); + + rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); + if (rc) + return rc; + + rc = port100_submit_urb_for_ack(dev, GFP_KERNEL); + if (rc) + goto error; + + return 0; + +error: + usb_unlink_urb(dev->out_urb); + return rc; +} + +static void port100_build_cmd_frame(struct port100 *dev, u8 cmd_code, + struct sk_buff *skb) +{ + /* payload is already there, just update datalen */ + int payload_len = skb->len; + + skb_push(skb, PORT100_FRAME_HEADER_LEN); + skb_put(skb, PORT100_FRAME_TAIL_LEN); + + port100_tx_frame_init(skb->data, cmd_code); + port100_tx_update_payload_len(skb->data, payload_len); + port100_tx_frame_finish(skb->data); +} + +static void port100_send_async_complete(struct port100 *dev) +{ + struct port100_cmd *cmd = dev->cmd; + int status = cmd->status; + + struct sk_buff *req = cmd->req; + struct sk_buff *resp = cmd->resp; + + dev_kfree_skb(req); + + dev->cmd = NULL; + + if (status < 0) { + cmd->complete_cb(dev, cmd->complete_cb_context, + ERR_PTR(status)); + dev_kfree_skb(resp); + goto done; + } + + skb_put(resp, port100_rx_frame_size(resp->data)); + skb_pull(resp, PORT100_FRAME_HEADER_LEN); + skb_trim(resp, resp->len - PORT100_FRAME_TAIL_LEN); + + cmd->complete_cb(dev, cmd->complete_cb_context, resp); + +done: + kfree(cmd); +} + +static int port100_send_cmd_async(struct port100 *dev, u8 cmd_code, + struct sk_buff *req, + port100_send_async_complete_t complete_cb, + void *complete_cb_context) +{ + struct port100_cmd *cmd; + struct sk_buff *resp; + int rc; + int resp_len = PORT100_FRAME_HEADER_LEN + + PORT100_FRAME_MAX_PAYLOAD_LEN + + PORT100_FRAME_TAIL_LEN; + + resp = alloc_skb(resp_len, GFP_KERNEL); + if (!resp) + return -ENOMEM; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + dev_kfree_skb(resp); + return -ENOMEM; + } + + cmd->code = cmd_code; + cmd->req = req; + cmd->resp = resp; + cmd->resp_len = resp_len; + cmd->complete_cb = complete_cb; + cmd->complete_cb_context = complete_cb_context; + + port100_build_cmd_frame(dev, cmd_code, req); + + dev->cmd = cmd; + + rc = port100_send_frame_async(dev, req, resp, resp_len); + if (rc) { + kfree(cmd); + dev_kfree_skb(resp); + dev->cmd = NULL; + } + + return rc; +} + +struct port100_sync_cmd_response { + struct sk_buff *resp; + struct completion done; +}; + +static void port100_wq_cmd_complete(struct work_struct *work) +{ + struct port100 *dev = container_of(work, struct port100, + cmd_complete_work); + + port100_send_async_complete(dev); +} + +static void port100_send_sync_complete(struct port100 *dev, void *_arg, + struct sk_buff *resp) +{ + struct port100_sync_cmd_response *arg = _arg; + + arg->resp = resp; + complete(&arg->done); +} + +static struct sk_buff *port100_send_cmd_sync(struct port100 *dev, u8 cmd_code, + struct sk_buff *req) +{ + int rc; + struct port100_sync_cmd_response arg; + + init_completion(&arg.done); + + rc = port100_send_cmd_async(dev, cmd_code, req, + port100_send_sync_complete, &arg); + if (rc) { + dev_kfree_skb(req); + return ERR_PTR(rc); + } + + wait_for_completion(&arg.done); + + return arg.resp; +} + +static void port100_send_complete(struct urb *urb) +{ + struct port100 *dev = urb->context; + + switch (urb->status) { + case 0: + break; /* success */ + case -ECONNRESET: + case -ENOENT: + nfc_err(&dev->interface->dev, + "The urb has been stopped (status %d)", urb->status); + break; + case -ESHUTDOWN: + default: + nfc_err(&dev->interface->dev, "Urb failure (status %d)", + urb->status); + } +} + +static void port100_abort_cmd(struct nfc_digital_dev *ddev) +{ + struct port100 *dev = nfc_digital_get_drvdata(ddev); + + /* An ack will cancel the last issued command */ + port100_send_ack(dev); + + /* cancel the urb request */ + usb_kill_urb(dev->in_urb); +} + +static struct sk_buff *port100_alloc_skb(struct port100 *dev, unsigned int size) +{ + struct sk_buff *skb; + + skb = alloc_skb(dev->skb_headroom + dev->skb_tailroom + size, + GFP_KERNEL); + if (skb) + skb_reserve(skb, dev->skb_headroom); + + return skb; +} + +static int port100_set_command_type(struct port100 *dev, u8 command_type) +{ + struct sk_buff *skb; + struct sk_buff *resp; + int rc; + + skb = port100_alloc_skb(dev, 1); + if (!skb) + return -ENOMEM; + + *skb_put(skb, sizeof(u8)) = command_type; + + resp = port100_send_cmd_sync(dev, PORT100_CMD_SET_COMMAND_TYPE, skb); + if (IS_ERR(resp)) + return PTR_ERR(resp); + + rc = resp->data[0]; + + dev_kfree_skb(resp); + + return rc; +} + +static u64 port100_get_command_type_mask(struct port100 *dev) +{ + struct sk_buff *skb; + struct sk_buff *resp; + u64 mask; + + skb = port100_alloc_skb(dev, 0); + if (!skb) + return -ENOMEM; + + resp = port100_send_cmd_sync(dev, PORT100_CMD_GET_COMMAND_TYPE, skb); + if (IS_ERR(resp)) + return PTR_ERR(resp); + + if (resp->len < 8) + mask = 0; + else + mask = be64_to_cpu(*(__be64 *)resp->data); + + dev_kfree_skb(resp); + + return mask; +} + +static u16 port100_get_firmware_version(struct port100 *dev) +{ + struct sk_buff *skb; + struct sk_buff *resp; + u16 fw_ver; + + skb = port100_alloc_skb(dev, 0); + if (!skb) + return 0; + + resp = port100_send_cmd_sync(dev, PORT100_CMD_GET_FIRMWARE_VERSION, + skb); + if (IS_ERR(resp)) + return 0; + + fw_ver = le16_to_cpu(*(__le16 *)resp->data); + + dev_kfree_skb(resp); + + return fw_ver; +} + +static int port100_switch_rf(struct nfc_digital_dev *ddev, bool on) +{ + struct port100 *dev = nfc_digital_get_drvdata(ddev); + struct sk_buff *skb, *resp; + + skb = port100_alloc_skb(dev, 1); + if (!skb) + return -ENOMEM; + + *skb_put(skb, 1) = on ? 1 : 0; + + resp = port100_send_cmd_sync(dev, PORT100_CMD_SWITCH_RF, skb); + + if (IS_ERR(resp)) + return PTR_ERR(resp); + + dev_kfree_skb(resp); + + return 0; +} + +static int port100_in_set_rf(struct nfc_digital_dev *ddev, u8 rf) +{ + struct port100 *dev = nfc_digital_get_drvdata(ddev); + struct sk_buff *skb; + struct sk_buff *resp; + int rc; + + if (rf >= NFC_DIGITAL_RF_TECH_LAST) + return -EINVAL; + + skb = port100_alloc_skb(dev, sizeof(struct port100_in_rf_setting)); + if (!skb) + return -ENOMEM; + + memcpy(skb_put(skb, sizeof(struct port100_in_rf_setting)), + &in_rf_settings[rf], + sizeof(struct port100_in_rf_setting)); + + resp = port100_send_cmd_sync(dev, PORT100_CMD_IN_SET_RF, skb); + + if (IS_ERR(resp)) + return PTR_ERR(resp); + + rc = resp->data[0]; + + dev_kfree_skb(resp); + + return rc; +} + +static int port100_in_set_framing(struct nfc_digital_dev *ddev, int param) +{ + struct port100 *dev = nfc_digital_get_drvdata(ddev); + struct port100_protocol *protocols; + struct sk_buff *skb; + struct sk_buff *resp; + int num_protocols; + size_t size; + int rc; + + if (param >= NFC_DIGITAL_FRAMING_LAST) + return -EINVAL; + + protocols = in_protocols[param]; + + num_protocols = 0; + while (protocols[num_protocols].number != PORT100_IN_PROT_END) + num_protocols++; + + if (!num_protocols) + return 0; + + size = sizeof(struct port100_protocol) * num_protocols; + + skb = port100_alloc_skb(dev, size); + if (!skb) + return -ENOMEM; + + memcpy(skb_put(skb, size), protocols, size); + + resp = port100_send_cmd_sync(dev, PORT100_CMD_IN_SET_PROTOCOL, skb); + + if (IS_ERR(resp)) + return PTR_ERR(resp); + + rc = resp->data[0]; + + dev_kfree_skb(resp); + + return rc; +} + +static int port100_in_configure_hw(struct nfc_digital_dev *ddev, int type, + int param) +{ + if (type == NFC_DIGITAL_CONFIG_RF_TECH) + return port100_in_set_rf(ddev, param); + + if (type == NFC_DIGITAL_CONFIG_FRAMING) + return port100_in_set_framing(ddev, param); + + return -EINVAL; +} + +static void port100_in_comm_rf_complete(struct port100 *dev, void *arg, + struct sk_buff *resp) +{ + struct port100_cb_arg *cb_arg = arg; + nfc_digital_cmd_complete_t cb = cb_arg->complete_cb; + u32 status; + int rc; + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + goto exit; + } + + if (resp->len < 4) { + nfc_err(&dev->interface->dev, + "Invalid packet length received.\n"); + rc = -EIO; + goto error; + } + + status = le32_to_cpu(*(__le32 *)resp->data); + + skb_pull(resp, sizeof(u32)); + + if (status == PORT100_CMD_STATUS_TIMEOUT) { + rc = -ETIMEDOUT; + goto error; + } + + if (status != PORT100_CMD_STATUS_OK) { + nfc_err(&dev->interface->dev, + "in_comm_rf failed with status 0x%08x\n", status); + rc = -EIO; + goto error; + } + + /* Remove collision bits byte */ + skb_pull(resp, 1); + + goto exit; + +error: + kfree_skb(resp); + resp = ERR_PTR(rc); + +exit: + cb(dev->nfc_digital_dev, cb_arg->complete_arg, resp); + + kfree(cb_arg); +} + +static int port100_in_send_cmd(struct nfc_digital_dev *ddev, + struct sk_buff *skb, u16 _timeout, + nfc_digital_cmd_complete_t cb, void *arg) +{ + struct port100 *dev = nfc_digital_get_drvdata(ddev); + struct port100_cb_arg *cb_arg; + __le16 timeout; + + cb_arg = kzalloc(sizeof(struct port100_cb_arg), GFP_KERNEL); + if (!cb_arg) + return -ENOMEM; + + cb_arg->complete_cb = cb; + cb_arg->complete_arg = arg; + + timeout = cpu_to_le16(_timeout * 10); + + memcpy(skb_push(skb, sizeof(__le16)), &timeout, sizeof(__le16)); + + return port100_send_cmd_async(dev, PORT100_CMD_IN_COMM_RF, skb, + port100_in_comm_rf_complete, cb_arg); +} + +static int port100_tg_set_rf(struct nfc_digital_dev *ddev, u8 rf) +{ + struct port100 *dev = nfc_digital_get_drvdata(ddev); + struct sk_buff *skb; + struct sk_buff *resp; + int rc; + + if (rf >= NFC_DIGITAL_RF_TECH_LAST) + return -EINVAL; + + skb = port100_alloc_skb(dev, sizeof(struct port100_tg_rf_setting)); + if (!skb) + return -ENOMEM; + + memcpy(skb_put(skb, sizeof(struct port100_tg_rf_setting)), + &tg_rf_settings[rf], + sizeof(struct port100_tg_rf_setting)); + + resp = port100_send_cmd_sync(dev, PORT100_CMD_TG_SET_RF, skb); + + if (IS_ERR(resp)) + return PTR_ERR(resp); + + rc = resp->data[0]; + + dev_kfree_skb(resp); + + return rc; +} + +static int port100_tg_set_framing(struct nfc_digital_dev *ddev, int param) +{ + struct port100 *dev = nfc_digital_get_drvdata(ddev); + struct port100_protocol *protocols; + struct sk_buff *skb; + struct sk_buff *resp; + int rc; + int num_protocols; + size_t size; + + if (param >= NFC_DIGITAL_FRAMING_LAST) + return -EINVAL; + + protocols = tg_protocols[param]; + + num_protocols = 0; + while (protocols[num_protocols].number != PORT100_TG_PROT_END) + num_protocols++; + + if (!num_protocols) + return 0; + + size = sizeof(struct port100_protocol) * num_protocols; + + skb = port100_alloc_skb(dev, size); + if (!skb) + return -ENOMEM; + + memcpy(skb_put(skb, size), protocols, size); + + resp = port100_send_cmd_sync(dev, PORT100_CMD_TG_SET_PROTOCOL, skb); + + if (IS_ERR(resp)) + return PTR_ERR(resp); + + rc = resp->data[0]; + + dev_kfree_skb(resp); + + return rc; +} + +static int port100_tg_configure_hw(struct nfc_digital_dev *ddev, int type, + int param) +{ + if (type == NFC_DIGITAL_CONFIG_RF_TECH) + return port100_tg_set_rf(ddev, param); + + if (type == NFC_DIGITAL_CONFIG_FRAMING) + return port100_tg_set_framing(ddev, param); + + return -EINVAL; +} + +static bool port100_tg_target_activated(struct port100 *dev, u8 tgt_activated) +{ + u8 mask; + + switch (dev->cmd_type) { + case PORT100_CMD_TYPE_0: + mask = PORT100_MDAA_TGT_HAS_BEEN_ACTIVATED_MASK; + break; + case PORT100_CMD_TYPE_1: + mask = PORT100_MDAA_TGT_HAS_BEEN_ACTIVATED_MASK | + PORT100_MDAA_TGT_WAS_ACTIVATED_MASK; + break; + default: + nfc_err(&dev->interface->dev, "Unknonwn command type.\n"); + return false; + } + + return ((tgt_activated & mask) == mask); +} + +static void port100_tg_comm_rf_complete(struct port100 *dev, void *arg, + struct sk_buff *resp) +{ + u32 status; + struct port100_cb_arg *cb_arg = arg; + nfc_digital_cmd_complete_t cb = cb_arg->complete_cb; + struct port100_tg_comm_rf_res *hdr; + + if (IS_ERR(resp)) + goto exit; + + hdr = (struct port100_tg_comm_rf_res *)resp->data; + + status = le32_to_cpu(hdr->status); + + if (cb_arg->mdaa && + !port100_tg_target_activated(dev, hdr->target_activated)) { + kfree_skb(resp); + resp = ERR_PTR(-ETIMEDOUT); + + goto exit; + } + + skb_pull(resp, sizeof(struct port100_tg_comm_rf_res)); + + if (status != PORT100_CMD_STATUS_OK) { + kfree_skb(resp); + + if (status == PORT100_CMD_STATUS_TIMEOUT) + resp = ERR_PTR(-ETIMEDOUT); + else + resp = ERR_PTR(-EIO); + } + +exit: + cb(dev->nfc_digital_dev, cb_arg->complete_arg, resp); + + kfree(cb_arg); +} + +static int port100_tg_send_cmd(struct nfc_digital_dev *ddev, + struct sk_buff *skb, u16 timeout, + nfc_digital_cmd_complete_t cb, void *arg) +{ + struct port100 *dev = nfc_digital_get_drvdata(ddev); + struct port100_tg_comm_rf_cmd *hdr; + struct port100_cb_arg *cb_arg; + + cb_arg = kzalloc(sizeof(struct port100_cb_arg), GFP_KERNEL); + if (!cb_arg) + return -ENOMEM; + + cb_arg->complete_cb = cb; + cb_arg->complete_arg = arg; + + skb_push(skb, sizeof(struct port100_tg_comm_rf_cmd)); + + hdr = (struct port100_tg_comm_rf_cmd *)skb->data; + + memset(hdr, 0, sizeof(struct port100_tg_comm_rf_cmd)); + hdr->guard_time = cpu_to_le16(500); + hdr->send_timeout = cpu_to_le16(0xFFFF); + hdr->recv_timeout = cpu_to_le16(timeout); + + return port100_send_cmd_async(dev, PORT100_CMD_TG_COMM_RF, skb, + port100_tg_comm_rf_complete, cb_arg); +} + +static int port100_listen_mdaa(struct nfc_digital_dev *ddev, + struct digital_tg_mdaa_params *params, + u16 timeout, + nfc_digital_cmd_complete_t cb, void *arg) +{ + struct port100 *dev = nfc_digital_get_drvdata(ddev); + struct port100_tg_comm_rf_cmd *hdr; + struct port100_cb_arg *cb_arg; + struct sk_buff *skb; + int rc; + + rc = port100_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, + NFC_DIGITAL_RF_TECH_106A); + if (rc) + return rc; + + rc = port100_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, + NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); + if (rc) + return rc; + + cb_arg = kzalloc(sizeof(struct port100_cb_arg), GFP_KERNEL); + if (!cb_arg) + return -ENOMEM; + + cb_arg->complete_cb = cb; + cb_arg->complete_arg = arg; + cb_arg->mdaa = 1; + + skb = port100_alloc_skb(dev, 0); + if (!skb) { + kfree(cb_arg); + return -ENOMEM; + } + + skb_push(skb, sizeof(struct port100_tg_comm_rf_cmd)); + hdr = (struct port100_tg_comm_rf_cmd *)skb->data; + + memset(hdr, 0, sizeof(struct port100_tg_comm_rf_cmd)); + + hdr->guard_time = 0; + hdr->send_timeout = cpu_to_le16(0xFFFF); + hdr->mdaa = 1; + hdr->nfca_param[0] = (params->sens_res >> 8) & 0xFF; + hdr->nfca_param[1] = params->sens_res & 0xFF; + memcpy(hdr->nfca_param + 2, params->nfcid1, 3); + hdr->nfca_param[5] = params->sel_res; + memcpy(hdr->nfcf_param, params->nfcid2, 8); + hdr->nfcf_param[16] = (params->sc >> 8) & 0xFF; + hdr->nfcf_param[17] = params->sc & 0xFF; + hdr->recv_timeout = cpu_to_le16(timeout); + + return port100_send_cmd_async(dev, PORT100_CMD_TG_COMM_RF, skb, + port100_tg_comm_rf_complete, cb_arg); +} + +static int port100_listen(struct nfc_digital_dev *ddev, u16 timeout, + nfc_digital_cmd_complete_t cb, void *arg) +{ + struct port100 *dev = nfc_digital_get_drvdata(ddev); + struct sk_buff *skb; + + skb = port100_alloc_skb(dev, 0); + if (!skb) + return -ENOMEM; + + return port100_tg_send_cmd(ddev, skb, timeout, cb, arg); +} + +static struct nfc_digital_ops port100_digital_ops = { + .in_configure_hw = port100_in_configure_hw, + .in_send_cmd = port100_in_send_cmd, + + .tg_listen_mdaa = port100_listen_mdaa, + .tg_listen = port100_listen, + .tg_configure_hw = port100_tg_configure_hw, + .tg_send_cmd = port100_tg_send_cmd, + + .switch_rf = port100_switch_rf, + .abort_cmd = port100_abort_cmd, +}; + +static const struct usb_device_id port100_table[] = { + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = SONY_VENDOR_ID, + .idProduct = RCS380_PRODUCT_ID, + }, + { } +}; +MODULE_DEVICE_TABLE(usb, port100_table); + +static int port100_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct port100 *dev; + int rc; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int in_endpoint; + int out_endpoint; + u16 fw_version; + u64 cmd_type_mask; + int i; + + dev = devm_kzalloc(&interface->dev, sizeof(struct port100), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + dev->udev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; + usb_set_intfdata(interface, dev); + + in_endpoint = out_endpoint = 0; + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) + in_endpoint = endpoint->bEndpointAddress; + + if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) + out_endpoint = endpoint->bEndpointAddress; + } + + if (!in_endpoint || !out_endpoint) { + nfc_err(&interface->dev, + "Could not find bulk-in or bulk-out endpoint\n"); + rc = -ENODEV; + goto error; + } + + dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); + dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); + + if (!dev->in_urb || !dev->out_urb) { + nfc_err(&interface->dev, "Could not allocate USB URBs\n"); + rc = -ENOMEM; + goto error; + } + + usb_fill_bulk_urb(dev->in_urb, dev->udev, + usb_rcvbulkpipe(dev->udev, in_endpoint), + NULL, 0, NULL, dev); + usb_fill_bulk_urb(dev->out_urb, dev->udev, + usb_sndbulkpipe(dev->udev, out_endpoint), + NULL, 0, port100_send_complete, dev); + + dev->skb_headroom = PORT100_FRAME_HEADER_LEN + + PORT100_COMM_RF_HEAD_MAX_LEN; + dev->skb_tailroom = PORT100_FRAME_TAIL_LEN; + + INIT_WORK(&dev->cmd_complete_work, port100_wq_cmd_complete); + + /* The first thing to do with the Port-100 is to set the command type + * to be used. If supported we use command type 1. 0 otherwise. + */ + cmd_type_mask = port100_get_command_type_mask(dev); + if (!cmd_type_mask) { + nfc_err(&interface->dev, + "Could not get supported command types.\n"); + rc = -ENODEV; + goto error; + } + + if (PORT100_CMD_TYPE_IS_SUPPORTED(cmd_type_mask, PORT100_CMD_TYPE_1)) + dev->cmd_type = PORT100_CMD_TYPE_1; + else + dev->cmd_type = PORT100_CMD_TYPE_0; + + rc = port100_set_command_type(dev, dev->cmd_type); + if (rc) { + nfc_err(&interface->dev, + "The device does not support command type %u.\n", + dev->cmd_type); + goto error; + } + + fw_version = port100_get_firmware_version(dev); + if (!fw_version) + nfc_err(&interface->dev, + "Could not get device firmware version.\n"); + + nfc_info(&interface->dev, + "Sony NFC Port-100 Series attached (firmware v%x.%02x)\n", + (fw_version & 0xFF00) >> 8, fw_version & 0xFF); + + dev->nfc_digital_dev = nfc_digital_allocate_device(&port100_digital_ops, + PORT100_PROTOCOLS, + PORT100_CAPABILITIES, + dev->skb_headroom, + dev->skb_tailroom); + if (!dev->nfc_digital_dev) { + nfc_err(&interface->dev, + "Could not allocate nfc_digital_dev.\n"); + rc = -ENOMEM; + goto error; + } + + nfc_digital_set_parent_dev(dev->nfc_digital_dev, &interface->dev); + nfc_digital_set_drvdata(dev->nfc_digital_dev, dev); + + rc = nfc_digital_register_device(dev->nfc_digital_dev); + if (rc) { + nfc_err(&interface->dev, + "Could not register digital device.\n"); + goto free_nfc_dev; + } + + return 0; + +free_nfc_dev: + nfc_digital_free_device(dev->nfc_digital_dev); + +error: + usb_free_urb(dev->in_urb); + usb_free_urb(dev->out_urb); + usb_put_dev(dev->udev); + + return rc; +} + +static void port100_disconnect(struct usb_interface *interface) +{ + struct port100 *dev; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + nfc_digital_unregister_device(dev->nfc_digital_dev); + nfc_digital_free_device(dev->nfc_digital_dev); + + usb_kill_urb(dev->in_urb); + usb_kill_urb(dev->out_urb); + + usb_free_urb(dev->in_urb); + usb_free_urb(dev->out_urb); + + kfree(dev->cmd); + + nfc_info(&interface->dev, "Sony Port-100 NFC device disconnected"); +} + +static struct usb_driver port100_driver = { + .name = "port100", + .probe = port100_probe, + .disconnect = port100_disconnect, + .id_table = port100_table, +}; + +module_usb_driver(port100_driver); + +MODULE_DESCRIPTION("NFC Port-100 series usb driver ver " VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL"); |