diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2012-07-02 14:04:01 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-07-09 16:42:22 -0400 |
commit | 5c7b0531299dad4255ff5c5106d060150cda75a4 (patch) | |
tree | 68a9a807e1a07b30cafca5a6793c5aa80ae743d1 /drivers/nfc | |
parent | c66433dc5dda15861dcbac63a97645771d14feb6 (diff) |
NFC: Add initial Sony RC-S360 support to pn533
Sony RC-S360 is also known as the Sony PaSoRi contactless reader.
Only type 2, 3 and 4 tag reading is supported at the moment.
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r-- | drivers/nfc/pn533.c | 219 |
1 files changed, 181 insertions, 38 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 9ac829e22e73..37786ff18c36 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -38,9 +38,42 @@ | |||
38 | #define SCM_VENDOR_ID 0x4E6 | 38 | #define SCM_VENDOR_ID 0x4E6 |
39 | #define SCL3711_PRODUCT_ID 0x5591 | 39 | #define SCL3711_PRODUCT_ID 0x5591 |
40 | 40 | ||
41 | #define SONY_VENDOR_ID 0x054c | ||
42 | #define PASORI_PRODUCT_ID 0x02e1 | ||
43 | |||
44 | #define PN533_QUIRKS_TYPE_A BIT(0) | ||
45 | #define PN533_QUIRKS_TYPE_F BIT(1) | ||
46 | #define PN533_QUIRKS_DEP BIT(2) | ||
47 | #define PN533_QUIRKS_RAW_EXCHANGE BIT(3) | ||
48 | |||
49 | #define PN533_DEVICE_STD 0x1 | ||
50 | #define PN533_DEVICE_PASORI 0x2 | ||
51 | |||
52 | #define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK \ | ||
53 | | NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK \ | ||
54 | | NFC_PROTO_NFC_DEP_MASK) | ||
55 | |||
56 | #define PN533_NO_TYPE_B_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ | ||
57 | NFC_PROTO_MIFARE_MASK | \ | ||
58 | NFC_PROTO_FELICA_MASK | \ | ||
59 | NFC_PROTO_NFC_DEP_MASK) | ||
60 | |||
41 | static const struct usb_device_id pn533_table[] = { | 61 | static const struct usb_device_id pn533_table[] = { |
42 | { USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID) }, | 62 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, |
43 | { USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID) }, | 63 | .idVendor = PN533_VENDOR_ID, |
64 | .idProduct = PN533_PRODUCT_ID, | ||
65 | .driver_info = PN533_DEVICE_STD, | ||
66 | }, | ||
67 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
68 | .idVendor = SCM_VENDOR_ID, | ||
69 | .idProduct = SCL3711_PRODUCT_ID, | ||
70 | .driver_info = PN533_DEVICE_STD, | ||
71 | }, | ||
72 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
73 | .idVendor = SONY_VENDOR_ID, | ||
74 | .idProduct = PASORI_PRODUCT_ID, | ||
75 | .driver_info = PN533_DEVICE_PASORI, | ||
76 | }, | ||
44 | { } | 77 | { } |
45 | }; | 78 | }; |
46 | MODULE_DEVICE_TABLE(usb, pn533_table); | 79 | MODULE_DEVICE_TABLE(usb, pn533_table); |
@@ -72,6 +105,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
72 | #define PN533_CMD_GET_FIRMWARE_VERSION 0x02 | 105 | #define PN533_CMD_GET_FIRMWARE_VERSION 0x02 |
73 | #define PN533_CMD_RF_CONFIGURATION 0x32 | 106 | #define PN533_CMD_RF_CONFIGURATION 0x32 |
74 | #define PN533_CMD_IN_DATA_EXCHANGE 0x40 | 107 | #define PN533_CMD_IN_DATA_EXCHANGE 0x40 |
108 | #define PN533_CMD_IN_COMM_THRU 0x42 | ||
75 | #define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A | 109 | #define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A |
76 | #define PN533_CMD_IN_ATR 0x50 | 110 | #define PN533_CMD_IN_ATR 0x50 |
77 | #define PN533_CMD_IN_RELEASE 0x52 | 111 | #define PN533_CMD_IN_RELEASE 0x52 |
@@ -109,6 +143,7 @@ struct pn533_fw_version { | |||
109 | /* PN533_CMD_RF_CONFIGURATION */ | 143 | /* PN533_CMD_RF_CONFIGURATION */ |
110 | #define PN533_CFGITEM_TIMING 0x02 | 144 | #define PN533_CFGITEM_TIMING 0x02 |
111 | #define PN533_CFGITEM_MAX_RETRIES 0x05 | 145 | #define PN533_CFGITEM_MAX_RETRIES 0x05 |
146 | #define PN533_CFGITEM_PASORI 0x82 | ||
112 | 147 | ||
113 | #define PN533_CONFIG_TIMING_102 0xb | 148 | #define PN533_CONFIG_TIMING_102 0xb |
114 | #define PN533_CONFIG_TIMING_204 0xc | 149 | #define PN533_CONFIG_TIMING_204 0xc |
@@ -344,6 +379,8 @@ struct pn533 { | |||
344 | u8 tgt_available_prots; | 379 | u8 tgt_available_prots; |
345 | u8 tgt_active_prot; | 380 | u8 tgt_active_prot; |
346 | u8 tgt_mode; | 381 | u8 tgt_mode; |
382 | |||
383 | u32 device_type; | ||
347 | }; | 384 | }; |
348 | 385 | ||
349 | struct pn533_frame { | 386 | struct pn533_frame { |
@@ -1768,13 +1805,31 @@ static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb, | |||
1768 | } | 1805 | } |
1769 | 1806 | ||
1770 | if (target == true) { | 1807 | if (target == true) { |
1771 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); | 1808 | switch (dev->device_type) { |
1772 | out_frame = (struct pn533_frame *) skb->data; | 1809 | case PN533_DEVICE_STD: |
1810 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); | ||
1811 | out_frame = (struct pn533_frame *) skb->data; | ||
1812 | pn533_tx_frame_init(out_frame, | ||
1813 | PN533_CMD_IN_DATA_EXCHANGE); | ||
1814 | tg = 1; | ||
1815 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), | ||
1816 | &tg, sizeof(u8)); | ||
1817 | out_frame->datalen += sizeof(u8); | ||
1818 | break; | ||
1819 | |||
1820 | case PN533_DEVICE_PASORI: | ||
1821 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); | ||
1822 | out_frame = (struct pn533_frame *) skb->data; | ||
1823 | pn533_tx_frame_init(out_frame, PN533_CMD_IN_COMM_THRU); | ||
1824 | |||
1825 | break; | ||
1826 | |||
1827 | default: | ||
1828 | nfc_dev_err(&dev->interface->dev, | ||
1829 | "Unknown device type %d", dev->device_type); | ||
1830 | return -EINVAL; | ||
1831 | } | ||
1773 | 1832 | ||
1774 | pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE); | ||
1775 | tg = 1; | ||
1776 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8)); | ||
1777 | out_frame->datalen += sizeof(u8); | ||
1778 | } else { | 1833 | } else { |
1779 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); | 1834 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); |
1780 | out_frame = (struct pn533_frame *) skb->data; | 1835 | out_frame = (struct pn533_frame *) skb->data; |
@@ -2101,7 +2156,28 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, | |||
2101 | return rc; | 2156 | return rc; |
2102 | } | 2157 | } |
2103 | 2158 | ||
2104 | struct nfc_ops pn533_nfc_ops = { | 2159 | static int pn533_fw_reset(struct pn533 *dev) |
2160 | { | ||
2161 | int rc; | ||
2162 | u8 *params; | ||
2163 | |||
2164 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
2165 | |||
2166 | pn533_tx_frame_init(dev->out_frame, 0x18); | ||
2167 | |||
2168 | params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame); | ||
2169 | params[0] = 0x1; | ||
2170 | dev->out_frame->datalen += 1; | ||
2171 | |||
2172 | pn533_tx_frame_finish(dev->out_frame); | ||
2173 | |||
2174 | rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, | ||
2175 | dev->in_maxlen); | ||
2176 | |||
2177 | return rc; | ||
2178 | } | ||
2179 | |||
2180 | static struct nfc_ops pn533_nfc_ops = { | ||
2105 | .dev_up = NULL, | 2181 | .dev_up = NULL, |
2106 | .dev_down = NULL, | 2182 | .dev_down = NULL, |
2107 | .dep_link_up = pn533_dep_link_up, | 2183 | .dep_link_up = pn533_dep_link_up, |
@@ -2114,6 +2190,84 @@ struct nfc_ops pn533_nfc_ops = { | |||
2114 | .tm_send = pn533_tm_send, | 2190 | .tm_send = pn533_tm_send, |
2115 | }; | 2191 | }; |
2116 | 2192 | ||
2193 | static int pn533_setup(struct pn533 *dev) | ||
2194 | { | ||
2195 | struct pn533_config_max_retries max_retries; | ||
2196 | struct pn533_config_timing timing; | ||
2197 | u8 pasori_cfg[3] = {0x08, 0x01, 0x08}; | ||
2198 | int rc; | ||
2199 | |||
2200 | switch (dev->device_type) { | ||
2201 | case PN533_DEVICE_STD: | ||
2202 | max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS; | ||
2203 | max_retries.mx_rty_psl = 2; | ||
2204 | max_retries.mx_rty_passive_act = | ||
2205 | PN533_CONFIG_MAX_RETRIES_NO_RETRY; | ||
2206 | |||
2207 | timing.rfu = PN533_CONFIG_TIMING_102; | ||
2208 | timing.atr_res_timeout = PN533_CONFIG_TIMING_204; | ||
2209 | timing.dep_timeout = PN533_CONFIG_TIMING_409; | ||
2210 | |||
2211 | break; | ||
2212 | |||
2213 | case PN533_DEVICE_PASORI: | ||
2214 | max_retries.mx_rty_atr = 0x2; | ||
2215 | max_retries.mx_rty_psl = 0x1; | ||
2216 | max_retries.mx_rty_passive_act = | ||
2217 | PN533_CONFIG_MAX_RETRIES_NO_RETRY; | ||
2218 | |||
2219 | timing.rfu = PN533_CONFIG_TIMING_102; | ||
2220 | timing.atr_res_timeout = PN533_CONFIG_TIMING_102; | ||
2221 | timing.dep_timeout = PN533_CONFIG_TIMING_204; | ||
2222 | |||
2223 | break; | ||
2224 | |||
2225 | default: | ||
2226 | nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n", | ||
2227 | dev->device_type); | ||
2228 | return -EINVAL; | ||
2229 | } | ||
2230 | |||
2231 | rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES, | ||
2232 | (u8 *)&max_retries, sizeof(max_retries)); | ||
2233 | if (rc) { | ||
2234 | nfc_dev_err(&dev->interface->dev, | ||
2235 | "Error on setting MAX_RETRIES config"); | ||
2236 | return rc; | ||
2237 | } | ||
2238 | |||
2239 | |||
2240 | rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, | ||
2241 | (u8 *)&timing, sizeof(timing)); | ||
2242 | if (rc) { | ||
2243 | nfc_dev_err(&dev->interface->dev, | ||
2244 | "Error on setting RF timings"); | ||
2245 | return rc; | ||
2246 | } | ||
2247 | |||
2248 | switch (dev->device_type) { | ||
2249 | case PN533_DEVICE_STD: | ||
2250 | break; | ||
2251 | |||
2252 | case PN533_DEVICE_PASORI: | ||
2253 | pn533_fw_reset(dev); | ||
2254 | |||
2255 | rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI, | ||
2256 | pasori_cfg, 3); | ||
2257 | if (rc) { | ||
2258 | nfc_dev_err(&dev->interface->dev, | ||
2259 | "Error while settings PASORI config"); | ||
2260 | return rc; | ||
2261 | } | ||
2262 | |||
2263 | pn533_fw_reset(dev); | ||
2264 | |||
2265 | break; | ||
2266 | } | ||
2267 | |||
2268 | return 0; | ||
2269 | } | ||
2270 | |||
2117 | static int pn533_probe(struct usb_interface *interface, | 2271 | static int pn533_probe(struct usb_interface *interface, |
2118 | const struct usb_device_id *id) | 2272 | const struct usb_device_id *id) |
2119 | { | 2273 | { |
@@ -2121,8 +2275,6 @@ static int pn533_probe(struct usb_interface *interface, | |||
2121 | struct pn533 *dev; | 2275 | struct pn533 *dev; |
2122 | struct usb_host_interface *iface_desc; | 2276 | struct usb_host_interface *iface_desc; |
2123 | struct usb_endpoint_descriptor *endpoint; | 2277 | struct usb_endpoint_descriptor *endpoint; |
2124 | struct pn533_config_max_retries max_retries; | ||
2125 | struct pn533_config_timing timing; | ||
2126 | int in_endpoint = 0; | 2278 | int in_endpoint = 0; |
2127 | int out_endpoint = 0; | 2279 | int out_endpoint = 0; |
2128 | int rc = -ENOMEM; | 2280 | int rc = -ENOMEM; |
@@ -2208,10 +2360,22 @@ static int pn533_probe(struct usb_interface *interface, | |||
2208 | nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now" | 2360 | nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now" |
2209 | " attached", fw_ver->ver, fw_ver->rev); | 2361 | " attached", fw_ver->ver, fw_ver->rev); |
2210 | 2362 | ||
2211 | protocols = NFC_PROTO_JEWEL_MASK | 2363 | dev->device_type = id->driver_info; |
2212 | | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK | 2364 | switch (dev->device_type) { |
2213 | | NFC_PROTO_ISO14443_MASK | 2365 | case PN533_DEVICE_STD: |
2214 | | NFC_PROTO_NFC_DEP_MASK; | 2366 | protocols = PN533_ALL_PROTOCOLS; |
2367 | break; | ||
2368 | |||
2369 | case PN533_DEVICE_PASORI: | ||
2370 | protocols = PN533_NO_TYPE_B_PROTOCOLS; | ||
2371 | break; | ||
2372 | |||
2373 | default: | ||
2374 | nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n", | ||
2375 | dev->device_type); | ||
2376 | rc = -EINVAL; | ||
2377 | goto destroy_wq; | ||
2378 | } | ||
2215 | 2379 | ||
2216 | dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, | 2380 | dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, |
2217 | PN533_CMD_DATAEXCH_HEAD_LEN, | 2381 | PN533_CMD_DATAEXCH_HEAD_LEN, |
@@ -2226,30 +2390,9 @@ static int pn533_probe(struct usb_interface *interface, | |||
2226 | if (rc) | 2390 | if (rc) |
2227 | goto free_nfc_dev; | 2391 | goto free_nfc_dev; |
2228 | 2392 | ||
2229 | max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS; | 2393 | rc = pn533_setup(dev); |
2230 | max_retries.mx_rty_psl = 2; | 2394 | if (rc) |
2231 | max_retries.mx_rty_passive_act = PN533_CONFIG_MAX_RETRIES_NO_RETRY; | ||
2232 | |||
2233 | rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES, | ||
2234 | (u8 *) &max_retries, sizeof(max_retries)); | ||
2235 | |||
2236 | if (rc) { | ||
2237 | nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES" | ||
2238 | " config"); | ||
2239 | goto unregister_nfc_dev; | ||
2240 | } | ||
2241 | |||
2242 | timing.rfu = PN533_CONFIG_TIMING_102; | ||
2243 | timing.atr_res_timeout = PN533_CONFIG_TIMING_204; | ||
2244 | timing.dep_timeout = PN533_CONFIG_TIMING_409; | ||
2245 | |||
2246 | rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, | ||
2247 | (u8 *) &timing, sizeof(timing)); | ||
2248 | if (rc) { | ||
2249 | nfc_dev_err(&dev->interface->dev, | ||
2250 | "Error on setting RF timings"); | ||
2251 | goto unregister_nfc_dev; | 2395 | goto unregister_nfc_dev; |
2252 | } | ||
2253 | 2396 | ||
2254 | return 0; | 2397 | return 0; |
2255 | 2398 | ||