diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2013-08-21 09:06:55 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-09-24 19:35:41 -0400 |
commit | 673088fb42d0d6de500c4d3e22527611982dcce1 (patch) | |
tree | 2d91a6dbc4c8e0a727d113becb03e8569ef27d6c /drivers/nfc | |
parent | e29a9e2ae165620d202f3ce45abd3a219b13ffb7 (diff) |
NFC: pn533: Send ATR_REQ directly for active device detection
In order to improve active devices detection, we send an ATR_REQ between
each passive detection cycle. Without this algorithm, Android 4.3 based
devices running the Broadcom stack are hardly detected.
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r-- | drivers/nfc/pn533.c | 121 |
1 files changed, 120 insertions, 1 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index dc744eabeec1..8cffd73690b8 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -387,6 +387,7 @@ struct pn533 { | |||
387 | struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; | 387 | struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; |
388 | u8 poll_mod_count; | 388 | u8 poll_mod_count; |
389 | u8 poll_mod_curr; | 389 | u8 poll_mod_curr; |
390 | u8 poll_dep; | ||
390 | u32 poll_protocols; | 391 | u32 poll_protocols; |
391 | u32 listen_protocols; | 392 | u32 listen_protocols; |
392 | struct timer_list listen_timer; | 393 | struct timer_list listen_timer; |
@@ -1546,6 +1547,9 @@ static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) | |||
1546 | u8 nbtg, tg, *tgdata; | 1547 | u8 nbtg, tg, *tgdata; |
1547 | int rc, tgdata_len; | 1548 | int rc, tgdata_len; |
1548 | 1549 | ||
1550 | /* Toggle the DEP polling */ | ||
1551 | dev->poll_dep = 1; | ||
1552 | |||
1549 | nbtg = resp->data[0]; | 1553 | nbtg = resp->data[0]; |
1550 | tg = resp->data[1]; | 1554 | tg = resp->data[1]; |
1551 | tgdata = &resp->data[2]; | 1555 | tgdata = &resp->data[2]; |
@@ -1767,6 +1771,117 @@ static void pn533_wq_rf(struct work_struct *work) | |||
1767 | return; | 1771 | return; |
1768 | } | 1772 | } |
1769 | 1773 | ||
1774 | static int pn533_poll_dep_complete(struct pn533 *dev, void *arg, | ||
1775 | struct sk_buff *resp) | ||
1776 | { | ||
1777 | struct pn533_cmd_jump_dep_response *rsp; | ||
1778 | struct nfc_target nfc_target; | ||
1779 | u8 target_gt_len; | ||
1780 | int rc; | ||
1781 | |||
1782 | if (IS_ERR(resp)) | ||
1783 | return PTR_ERR(resp); | ||
1784 | |||
1785 | rsp = (struct pn533_cmd_jump_dep_response *)resp->data; | ||
1786 | |||
1787 | rc = rsp->status & PN533_CMD_RET_MASK; | ||
1788 | if (rc != PN533_CMD_RET_SUCCESS) { | ||
1789 | /* Not target found, turn radio off */ | ||
1790 | queue_work(dev->wq, &dev->rf_work); | ||
1791 | |||
1792 | dev_kfree_skb(resp); | ||
1793 | return 0; | ||
1794 | } | ||
1795 | |||
1796 | dev_dbg(&dev->interface->dev, "Creating new target"); | ||
1797 | |||
1798 | nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; | ||
1799 | nfc_target.nfcid1_len = 10; | ||
1800 | memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len); | ||
1801 | rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1); | ||
1802 | if (rc) | ||
1803 | goto error; | ||
1804 | |||
1805 | dev->tgt_available_prots = 0; | ||
1806 | dev->tgt_active_prot = NFC_PROTO_NFC_DEP; | ||
1807 | |||
1808 | /* ATR_RES general bytes are located at offset 17 */ | ||
1809 | target_gt_len = resp->len - 17; | ||
1810 | rc = nfc_set_remote_general_bytes(dev->nfc_dev, | ||
1811 | rsp->gt, target_gt_len); | ||
1812 | if (!rc) { | ||
1813 | rc = nfc_dep_link_is_up(dev->nfc_dev, | ||
1814 | dev->nfc_dev->targets[0].idx, | ||
1815 | 0, NFC_RF_INITIATOR); | ||
1816 | |||
1817 | if (!rc) | ||
1818 | pn533_poll_reset_mod_list(dev); | ||
1819 | } | ||
1820 | error: | ||
1821 | dev_kfree_skb(resp); | ||
1822 | return rc; | ||
1823 | } | ||
1824 | |||
1825 | #define PASSIVE_DATA_LEN 5 | ||
1826 | static int pn533_poll_dep(struct nfc_dev *nfc_dev) | ||
1827 | { | ||
1828 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | ||
1829 | struct sk_buff *skb; | ||
1830 | int rc, skb_len; | ||
1831 | u8 *next, nfcid3[NFC_NFCID3_MAXSIZE]; | ||
1832 | u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; | ||
1833 | |||
1834 | dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1835 | |||
1836 | if (!dev->gb) { | ||
1837 | dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len); | ||
1838 | |||
1839 | if (!dev->gb || !dev->gb_len) { | ||
1840 | dev->poll_dep = 0; | ||
1841 | queue_work(dev->wq, &dev->rf_work); | ||
1842 | } | ||
1843 | } | ||
1844 | |||
1845 | skb_len = 3 + dev->gb_len; /* ActPass + BR + Next */ | ||
1846 | skb_len += PASSIVE_DATA_LEN; | ||
1847 | |||
1848 | /* NFCID3 */ | ||
1849 | skb_len += NFC_NFCID3_MAXSIZE; | ||
1850 | nfcid3[0] = 0x1; | ||
1851 | nfcid3[1] = 0xfe; | ||
1852 | get_random_bytes(nfcid3 + 2, 6); | ||
1853 | |||
1854 | skb = pn533_alloc_skb(dev, skb_len); | ||
1855 | if (!skb) | ||
1856 | return -ENOMEM; | ||
1857 | |||
1858 | *skb_put(skb, 1) = 0x01; /* Active */ | ||
1859 | *skb_put(skb, 1) = 0x02; /* 424 kbps */ | ||
1860 | |||
1861 | next = skb_put(skb, 1); /* Next */ | ||
1862 | *next = 0; | ||
1863 | |||
1864 | /* Copy passive data */ | ||
1865 | memcpy(skb_put(skb, PASSIVE_DATA_LEN), passive_data, PASSIVE_DATA_LEN); | ||
1866 | *next |= 1; | ||
1867 | |||
1868 | /* Copy NFCID3 (which is NFCID2 from SENSF_RES) */ | ||
1869 | memcpy(skb_put(skb, NFC_NFCID3_MAXSIZE), nfcid3, | ||
1870 | NFC_NFCID3_MAXSIZE); | ||
1871 | *next |= 2; | ||
1872 | |||
1873 | memcpy(skb_put(skb, dev->gb_len), dev->gb, dev->gb_len); | ||
1874 | *next |= 4; /* We have some Gi */ | ||
1875 | |||
1876 | rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb, | ||
1877 | pn533_poll_dep_complete, NULL); | ||
1878 | |||
1879 | if (rc < 0) | ||
1880 | dev_kfree_skb(skb); | ||
1881 | |||
1882 | return rc; | ||
1883 | } | ||
1884 | |||
1770 | static int pn533_poll_complete(struct pn533 *dev, void *arg, | 1885 | static int pn533_poll_complete(struct pn533 *dev, void *arg, |
1771 | struct sk_buff *resp) | 1886 | struct sk_buff *resp) |
1772 | { | 1887 | { |
@@ -1853,6 +1968,11 @@ static int pn533_send_poll_frame(struct pn533 *dev) | |||
1853 | dev_dbg(&dev->interface->dev, "%s mod len %d\n", | 1968 | dev_dbg(&dev->interface->dev, "%s mod len %d\n", |
1854 | __func__, mod->len); | 1969 | __func__, mod->len); |
1855 | 1970 | ||
1971 | if (dev->poll_dep) { | ||
1972 | dev->poll_dep = 0; | ||
1973 | return pn533_poll_dep(dev->nfc_dev); | ||
1974 | } | ||
1975 | |||
1856 | if (mod->len == 0) { /* Listen mode */ | 1976 | if (mod->len == 0) { /* Listen mode */ |
1857 | cmd_code = PN533_CMD_TG_INIT_AS_TARGET; | 1977 | cmd_code = PN533_CMD_TG_INIT_AS_TARGET; |
1858 | skb = pn533_alloc_poll_tg_frame(dev); | 1978 | skb = pn533_alloc_poll_tg_frame(dev); |
@@ -2146,7 +2266,6 @@ error: | |||
2146 | } | 2266 | } |
2147 | 2267 | ||
2148 | static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf); | 2268 | static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf); |
2149 | #define PASSIVE_DATA_LEN 5 | ||
2150 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | 2269 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
2151 | u8 comm_mode, u8 *gb, size_t gb_len) | 2270 | u8 comm_mode, u8 *gb, size_t gb_len) |
2152 | { | 2271 | { |