diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2012-05-30 18:09:11 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-06-04 15:34:31 -0400 |
commit | dadb06f270ad7cd9572b82995f6261f8ca4620ac (patch) | |
tree | 63c71b84c55eba95aa71fa6f1551957270a36b12 /drivers/nfc | |
parent | 103b34cf5fe2bb72c38afa8523dd206e6ef3b5fe (diff) |
NFC: Implement the pn533 target mode Tx op
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r-- | drivers/nfc/pn533.c | 82 |
1 files changed, 73 insertions, 9 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 6a506e267d20..db4078765ac9 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -76,6 +76,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
76 | 76 | ||
77 | #define PN533_CMD_TG_INIT_AS_TARGET 0x8c | 77 | #define PN533_CMD_TG_INIT_AS_TARGET 0x8c |
78 | #define PN533_CMD_TG_GET_DATA 0x86 | 78 | #define PN533_CMD_TG_GET_DATA 0x86 |
79 | #define PN533_CMD_TG_SET_DATA 0x8e | ||
79 | 80 | ||
80 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) | 81 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) |
81 | 82 | ||
@@ -1630,7 +1631,8 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) | |||
1630 | return 0; | 1631 | return 0; |
1631 | } | 1632 | } |
1632 | 1633 | ||
1633 | static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) | 1634 | static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb, |
1635 | bool target) | ||
1634 | { | 1636 | { |
1635 | int payload_len = skb->len; | 1637 | int payload_len = skb->len; |
1636 | struct pn533_frame *out_frame; | 1638 | struct pn533_frame *out_frame; |
@@ -1647,14 +1649,20 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) | |||
1647 | return -ENOSYS; | 1649 | return -ENOSYS; |
1648 | } | 1650 | } |
1649 | 1651 | ||
1650 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); | 1652 | if (target == true) { |
1651 | out_frame = (struct pn533_frame *) skb->data; | 1653 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); |
1654 | out_frame = (struct pn533_frame *) skb->data; | ||
1652 | 1655 | ||
1653 | pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE); | 1656 | pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE); |
1657 | tg = 1; | ||
1658 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8)); | ||
1659 | out_frame->datalen += sizeof(u8); | ||
1660 | } else { | ||
1661 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); | ||
1662 | out_frame = (struct pn533_frame *) skb->data; | ||
1663 | pn533_tx_frame_init(out_frame, PN533_CMD_TG_SET_DATA); | ||
1664 | } | ||
1654 | 1665 | ||
1655 | tg = 1; | ||
1656 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8)); | ||
1657 | out_frame->datalen += sizeof(u8); | ||
1658 | 1666 | ||
1659 | /* The data is already in the out_frame, just update the datalen */ | 1667 | /* The data is already in the out_frame, just update the datalen */ |
1660 | out_frame->datalen += payload_len; | 1668 | out_frame->datalen += payload_len; |
@@ -1785,7 +1793,7 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, | |||
1785 | goto error; | 1793 | goto error; |
1786 | } | 1794 | } |
1787 | 1795 | ||
1788 | rc = pn533_data_exchange_tx_frame(dev, skb); | 1796 | rc = pn533_build_tx_frame(dev, skb, true); |
1789 | if (rc) | 1797 | if (rc) |
1790 | goto error; | 1798 | goto error; |
1791 | 1799 | ||
@@ -1833,6 +1841,61 @@ error: | |||
1833 | return rc; | 1841 | return rc; |
1834 | } | 1842 | } |
1835 | 1843 | ||
1844 | static int pn533_tm_send_complete(struct pn533 *dev, void *arg, | ||
1845 | u8 *params, int params_len) | ||
1846 | { | ||
1847 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1848 | |||
1849 | if (params_len < 0) { | ||
1850 | nfc_dev_err(&dev->interface->dev, | ||
1851 | "Error %d when sending data", | ||
1852 | params_len); | ||
1853 | |||
1854 | return params_len; | ||
1855 | } | ||
1856 | |||
1857 | if (params_len > 0 && params[0] != 0) { | ||
1858 | nfc_tm_deactivated(dev->nfc_dev); | ||
1859 | |||
1860 | return 0; | ||
1861 | } | ||
1862 | |||
1863 | queue_work(dev->wq, &dev->tg_work); | ||
1864 | |||
1865 | return 0; | ||
1866 | } | ||
1867 | |||
1868 | static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | ||
1869 | { | ||
1870 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | ||
1871 | struct pn533_frame *out_frame; | ||
1872 | int rc; | ||
1873 | |||
1874 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1875 | |||
1876 | rc = pn533_build_tx_frame(dev, skb, false); | ||
1877 | if (rc) | ||
1878 | goto error; | ||
1879 | |||
1880 | out_frame = (struct pn533_frame *) skb->data; | ||
1881 | |||
1882 | rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, | ||
1883 | dev->in_maxlen, pn533_tm_send_complete, | ||
1884 | NULL, GFP_KERNEL); | ||
1885 | if (rc) { | ||
1886 | nfc_dev_err(&dev->interface->dev, | ||
1887 | "Error %d when trying to send data", rc); | ||
1888 | goto error; | ||
1889 | } | ||
1890 | |||
1891 | return 0; | ||
1892 | |||
1893 | error: | ||
1894 | kfree_skb(skb); | ||
1895 | |||
1896 | return rc; | ||
1897 | } | ||
1898 | |||
1836 | static void pn533_wq_mi_recv(struct work_struct *work) | 1899 | static void pn533_wq_mi_recv(struct work_struct *work) |
1837 | { | 1900 | { |
1838 | struct pn533 *dev = container_of(work, struct pn533, mi_work); | 1901 | struct pn533 *dev = container_of(work, struct pn533, mi_work); |
@@ -1853,7 +1916,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) | |||
1853 | 1916 | ||
1854 | skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); | 1917 | skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); |
1855 | 1918 | ||
1856 | rc = pn533_data_exchange_tx_frame(dev, skb_cmd); | 1919 | rc = pn533_build_tx_frame(dev, skb_cmd, true); |
1857 | if (rc) | 1920 | if (rc) |
1858 | goto error_frame; | 1921 | goto error_frame; |
1859 | 1922 | ||
@@ -1928,6 +1991,7 @@ struct nfc_ops pn533_nfc_ops = { | |||
1928 | .activate_target = pn533_activate_target, | 1991 | .activate_target = pn533_activate_target, |
1929 | .deactivate_target = pn533_deactivate_target, | 1992 | .deactivate_target = pn533_deactivate_target, |
1930 | .im_transceive = pn533_transceive, | 1993 | .im_transceive = pn533_transceive, |
1994 | .tm_send = pn533_tm_send, | ||
1931 | }; | 1995 | }; |
1932 | 1996 | ||
1933 | static int pn533_probe(struct usb_interface *interface, | 1997 | static int pn533_probe(struct usb_interface *interface, |