aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc/pn533.c
diff options
context:
space:
mode:
authorOlivier Guiter <olivier.guiter@linux.intel.com>2013-09-23 06:24:38 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-09-25 10:01:41 -0400
commit3c13b244de968d88659b5aece0c0c4a6b97f220e (patch)
treeb4b42862ff5981ec9ccef92612e02e03361184b3 /drivers/nfc/pn533.c
parent22953f9329ebf5cc81cefe250a079600145388b3 (diff)
NFC: pn533: Add support for incoming fragmented frame in target mode
This code processes, for Target Mode, incoming fragmented frames. If the MI bit is present, we start a working queue to grab and aggregate all the parts (using TmGetData between each parts). On the last one, as there's no more MI bit, we jump on the usual behavior. Signed-off-by: Olivier Guiter <olivier.guiter@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc/pn533.c')
-rw-r--r--drivers/nfc/pn533.c72
1 files changed, 64 insertions, 8 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 0b7e928ceb3d..cd20641e7443 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -373,6 +373,7 @@ struct pn533 {
373 struct delayed_work poll_work; 373 struct delayed_work poll_work;
374 struct work_struct mi_rx_work; 374 struct work_struct mi_rx_work;
375 struct work_struct mi_tx_work; 375 struct work_struct mi_tx_work;
376 struct work_struct mi_tm_rx_work;
376 struct work_struct tg_work; 377 struct work_struct tg_work;
377 struct work_struct rf_work; 378 struct work_struct rf_work;
378 379
@@ -1624,27 +1625,81 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev)
1624 1625
1625#define PN533_CMD_DATAEXCH_HEAD_LEN 1 1626#define PN533_CMD_DATAEXCH_HEAD_LEN 1
1626#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 1627#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
1628static void pn533_wq_tm_mi_recv(struct work_struct *work);
1629static struct sk_buff *pn533_build_response(struct pn533 *dev);
1630
1627static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, 1631static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg,
1628 struct sk_buff *resp) 1632 struct sk_buff *resp)
1629{ 1633{
1630 u8 status; 1634 struct sk_buff *skb;
1635 u8 status, ret, mi;
1636 int rc;
1631 1637
1632 dev_dbg(&dev->interface->dev, "%s\n", __func__); 1638 dev_dbg(&dev->interface->dev, "%s\n", __func__);
1633 1639
1634 if (IS_ERR(resp)) 1640 if (IS_ERR(resp)) {
1641 skb_queue_purge(&dev->resp_q);
1635 return PTR_ERR(resp); 1642 return PTR_ERR(resp);
1643 }
1636 1644
1637 status = resp->data[0]; 1645 status = resp->data[0];
1646
1647 ret = status & PN533_CMD_RET_MASK;
1648 mi = status & PN533_CMD_MI_MASK;
1649
1638 skb_pull(resp, sizeof(status)); 1650 skb_pull(resp, sizeof(status));
1639 1651
1640 if (status != 0) { 1652 if (ret != PN533_CMD_RET_SUCCESS) {
1641 nfc_tm_deactivated(dev->nfc_dev); 1653 rc = -EIO;
1642 dev->tgt_mode = 0; 1654 goto error;
1643 dev_kfree_skb(resp); 1655 }
1644 return 0; 1656
1657 skb_queue_tail(&dev->resp_q, resp);
1658
1659 if (mi) {
1660 queue_work(dev->wq, &dev->mi_tm_rx_work);
1661 return -EINPROGRESS;
1662 }
1663
1664 skb = pn533_build_response(dev);
1665 if (!skb) {
1666 rc = -EIO;
1667 goto error;
1645 } 1668 }
1646 1669
1647 return nfc_tm_data_received(dev->nfc_dev, resp); 1670 return nfc_tm_data_received(dev->nfc_dev, skb);
1671
1672error:
1673 nfc_tm_deactivated(dev->nfc_dev);
1674 dev->tgt_mode = 0;
1675 skb_queue_purge(&dev->resp_q);
1676 dev_kfree_skb(resp);
1677
1678 return rc;
1679}
1680
1681static void pn533_wq_tm_mi_recv(struct work_struct *work)
1682{
1683 struct pn533 *dev = container_of(work, struct pn533, mi_tm_rx_work);
1684 struct sk_buff *skb;
1685 int rc;
1686
1687 dev_dbg(&dev->interface->dev, "%s\n", __func__);
1688
1689 skb = pn533_alloc_skb(dev, 0);
1690 if (!skb)
1691 return;
1692
1693 rc = pn533_send_cmd_direct_async(dev,
1694 PN533_CMD_TG_GET_DATA,
1695 skb,
1696 pn533_tm_get_data_complete,
1697 NULL);
1698
1699 if (rc < 0)
1700 dev_kfree_skb(skb);
1701
1702 return;
1648} 1703}
1649 1704
1650static void pn533_wq_tg_get_data(struct work_struct *work) 1705static void pn533_wq_tg_get_data(struct work_struct *work)
@@ -3055,6 +3110,7 @@ static int pn533_probe(struct usb_interface *interface,
3055 INIT_WORK(&dev->mi_rx_work, pn533_wq_mi_recv); 3110 INIT_WORK(&dev->mi_rx_work, pn533_wq_mi_recv);
3056 INIT_WORK(&dev->mi_tx_work, pn533_wq_mi_send); 3111 INIT_WORK(&dev->mi_tx_work, pn533_wq_mi_send);
3057 INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); 3112 INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data);
3113 INIT_WORK(&dev->mi_tm_rx_work, pn533_wq_tm_mi_recv);
3058 INIT_DELAYED_WORK(&dev->poll_work, pn533_wq_poll); 3114 INIT_DELAYED_WORK(&dev->poll_work, pn533_wq_poll);
3059 INIT_WORK(&dev->rf_work, pn533_wq_rf); 3115 INIT_WORK(&dev->rf_work, pn533_wq_rf);
3060 dev->wq = alloc_ordered_workqueue("pn533", 0); 3116 dev->wq = alloc_ordered_workqueue("pn533", 0);