Commit | Line | Data |
---|---|---|
bbed0dee EL |
1 | /* |
2 | * HCI based Driver for NXP PN544 NFC Chip | |
3 | * | |
4 | * Copyright (C) 2012 Intel Corporation. All rights reserved. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms and conditions of the GNU General Public License, | |
8 | * version 2, as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
98b32dec | 16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
bbed0dee EL |
17 | */ |
18 | ||
17936b43 JP |
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
20 | ||
bbed0dee EL |
21 | #include <linux/delay.h> |
22 | #include <linux/slab.h> | |
aa741030 | 23 | #include <linux/module.h> |
bbed0dee EL |
24 | |
25 | #include <linux/nfc.h> | |
26 | #include <net/nfc/hci.h> | |
412fda53 | 27 | #include <net/nfc/llc.h> |
bbed0dee | 28 | |
97f18414 | 29 | #include "pn544.h" |
bbed0dee EL |
30 | |
31 | /* Timing restrictions (ms) */ | |
32 | #define PN544_HCI_RESETVEN_TIME 30 | |
33 | ||
bbed0dee EL |
34 | enum pn544_state { |
35 | PN544_ST_COLD, | |
36 | PN544_ST_FW_READY, | |
37 | PN544_ST_READY, | |
38 | }; | |
39 | ||
40 | #define FULL_VERSION_LEN 11 | |
41 | ||
42 | /* Proprietary commands */ | |
43 | #define PN544_WRITE 0x3f | |
5faba2fd | 44 | #define PN544_TEST_SWP 0x21 |
bbed0dee EL |
45 | |
46 | /* Proprietary gates, events, commands and registers */ | |
47 | ||
48 | /* NFC_HCI_RF_READER_A_GATE additional registers and commands */ | |
49 | #define PN544_RF_READER_A_AUTO_ACTIVATION 0x10 | |
50 | #define PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION 0x12 | |
51 | #define PN544_MIFARE_CMD 0x21 | |
52 | ||
53 | /* Commands that apply to all RF readers */ | |
54 | #define PN544_RF_READER_CMD_PRESENCE_CHECK 0x30 | |
55 | #define PN544_RF_READER_CMD_ACTIVATE_NEXT 0x32 | |
56 | ||
57 | /* NFC_HCI_ID_MGMT_GATE additional registers */ | |
58 | #define PN544_ID_MGMT_FULL_VERSION_SW 0x10 | |
59 | ||
60 | #define PN544_RF_READER_ISO15693_GATE 0x12 | |
61 | ||
62 | #define PN544_RF_READER_F_GATE 0x14 | |
63 | #define PN544_FELICA_ID 0x04 | |
64 | #define PN544_FELICA_RAW 0x20 | |
65 | ||
66 | #define PN544_RF_READER_JEWEL_GATE 0x15 | |
67 | #define PN544_JEWEL_RAW_CMD 0x23 | |
68 | ||
69 | #define PN544_RF_READER_NFCIP1_INITIATOR_GATE 0x30 | |
70 | #define PN544_RF_READER_NFCIP1_TARGET_GATE 0x31 | |
71 | ||
72 | #define PN544_SYS_MGMT_GATE 0x90 | |
73 | #define PN544_SYS_MGMT_INFO_NOTIFICATION 0x02 | |
74 | ||
75 | #define PN544_POLLING_LOOP_MGMT_GATE 0x94 | |
7e2afc9d AW |
76 | #define PN544_DEP_MODE 0x01 |
77 | #define PN544_DEP_ATR_REQ 0x02 | |
78 | #define PN544_DEP_ATR_RES 0x03 | |
79 | #define PN544_DEP_MERGE 0x0D | |
bbed0dee EL |
80 | #define PN544_PL_RDPHASES 0x06 |
81 | #define PN544_PL_EMULATION 0x07 | |
82 | #define PN544_PL_NFCT_DEACTIVATED 0x09 | |
83 | ||
84 | #define PN544_SWP_MGMT_GATE 0xA0 | |
39438261 | 85 | #define PN544_SWP_DEFAULT_MODE 0x01 |
bbed0dee EL |
86 | |
87 | #define PN544_NFC_WI_MGMT_GATE 0xA1 | |
5faba2fd | 88 | #define PN544_NFC_ESE_DEFAULT_MODE 0x01 |
bbed0dee | 89 | |
f7a5f6c5 AW |
90 | #define PN544_HCI_EVT_SND_DATA 0x01 |
91 | #define PN544_HCI_EVT_ACTIVATED 0x02 | |
92 | #define PN544_HCI_EVT_DEACTIVATED 0x03 | |
93 | #define PN544_HCI_EVT_RCV_DATA 0x04 | |
94 | #define PN544_HCI_EVT_CONTINUE_MI 0x05 | |
5faba2fd | 95 | #define PN544_HCI_EVT_SWITCH_MODE 0x03 |
f7a5f6c5 | 96 | |
da052850 | 97 | #define PN544_HCI_CMD_ATTREQUEST 0x12 |
928326f2 AW |
98 | #define PN544_HCI_CMD_CONTINUE_ACTIVATION 0x13 |
99 | ||
a10d595b EL |
100 | static struct nfc_hci_gate pn544_gates[] = { |
101 | {NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE}, | |
102 | {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE}, | |
103 | {NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE}, | |
104 | {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_INVALID_PIPE}, | |
105 | {NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE}, | |
106 | {NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE}, | |
107 | {PN544_SYS_MGMT_GATE, NFC_HCI_INVALID_PIPE}, | |
108 | {PN544_SWP_MGMT_GATE, NFC_HCI_INVALID_PIPE}, | |
109 | {PN544_POLLING_LOOP_MGMT_GATE, NFC_HCI_INVALID_PIPE}, | |
110 | {PN544_NFC_WI_MGMT_GATE, NFC_HCI_INVALID_PIPE}, | |
111 | {PN544_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, | |
112 | {PN544_RF_READER_JEWEL_GATE, NFC_HCI_INVALID_PIPE}, | |
113 | {PN544_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, | |
114 | {PN544_RF_READER_NFCIP1_INITIATOR_GATE, NFC_HCI_INVALID_PIPE}, | |
115 | {PN544_RF_READER_NFCIP1_TARGET_GATE, NFC_HCI_INVALID_PIPE} | |
bbed0dee EL |
116 | }; |
117 | ||
118 | /* Largest headroom needed for outgoing custom commands */ | |
119 | #define PN544_CMDS_HEADROOM 2 | |
120 | ||
121 | struct pn544_hci_info { | |
97f18414 EL |
122 | struct nfc_phy_ops *phy_ops; |
123 | void *phy_id; | |
124 | ||
412fda53 | 125 | struct nfc_hci_dev *hdev; |
bbed0dee EL |
126 | |
127 | enum pn544_state state; | |
128 | ||
129 | struct mutex info_lock; | |
130 | ||
f3e8fb55 EL |
131 | int async_cb_type; |
132 | data_exchange_cb_t async_cb; | |
133 | void *async_cb_context; | |
8bd7fc89 EL |
134 | |
135 | fw_download_t fw_download; | |
bbed0dee EL |
136 | }; |
137 | ||
412fda53 | 138 | static int pn544_hci_open(struct nfc_hci_dev *hdev) |
bbed0dee | 139 | { |
412fda53 | 140 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); |
bbed0dee EL |
141 | int r = 0; |
142 | ||
143 | mutex_lock(&info->info_lock); | |
144 | ||
145 | if (info->state != PN544_ST_COLD) { | |
146 | r = -EBUSY; | |
147 | goto out; | |
148 | } | |
149 | ||
97f18414 | 150 | r = info->phy_ops->enable(info->phy_id); |
bbed0dee | 151 | |
eae202aa EL |
152 | if (r == 0) |
153 | info->state = PN544_ST_READY; | |
154 | ||
bbed0dee EL |
155 | out: |
156 | mutex_unlock(&info->info_lock); | |
157 | return r; | |
158 | } | |
159 | ||
412fda53 | 160 | static void pn544_hci_close(struct nfc_hci_dev *hdev) |
bbed0dee | 161 | { |
412fda53 | 162 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); |
bbed0dee EL |
163 | |
164 | mutex_lock(&info->info_lock); | |
165 | ||
166 | if (info->state == PN544_ST_COLD) | |
167 | goto out; | |
168 | ||
97f18414 | 169 | info->phy_ops->disable(info->phy_id); |
bbed0dee | 170 | |
eae202aa EL |
171 | info->state = PN544_ST_COLD; |
172 | ||
bbed0dee EL |
173 | out: |
174 | mutex_unlock(&info->info_lock); | |
175 | } | |
176 | ||
412fda53 | 177 | static int pn544_hci_ready(struct nfc_hci_dev *hdev) |
bbed0dee | 178 | { |
bbed0dee EL |
179 | struct sk_buff *skb; |
180 | static struct hw_config { | |
181 | u8 adr[2]; | |
182 | u8 value; | |
183 | } hw_config[] = { | |
184 | {{0x9f, 0x9a}, 0x00}, | |
185 | ||
186 | {{0x98, 0x10}, 0xbc}, | |
187 | ||
188 | {{0x9e, 0x71}, 0x00}, | |
189 | ||
190 | {{0x98, 0x09}, 0x00}, | |
191 | ||
192 | {{0x9e, 0xb4}, 0x00}, | |
193 | ||
bbed0dee EL |
194 | {{0x9c, 0x01}, 0x08}, |
195 | ||
196 | {{0x9e, 0xaa}, 0x01}, | |
197 | ||
34f7e57b AU |
198 | {{0x9b, 0xd1}, 0x17}, |
199 | {{0x9b, 0xd2}, 0x58}, | |
200 | {{0x9b, 0xd3}, 0x10}, | |
201 | {{0x9b, 0xd4}, 0x47}, | |
202 | {{0x9b, 0xd5}, 0x0c}, | |
203 | {{0x9b, 0xd6}, 0x37}, | |
204 | {{0x9b, 0xdd}, 0x33}, | |
205 | ||
206 | {{0x9b, 0x84}, 0x00}, | |
207 | {{0x99, 0x81}, 0x79}, | |
208 | {{0x99, 0x31}, 0x79}, | |
bbed0dee EL |
209 | |
210 | {{0x98, 0x00}, 0x3f}, | |
211 | ||
34f7e57b | 212 | {{0x9f, 0x09}, 0x02}, |
bbed0dee EL |
213 | |
214 | {{0x9f, 0x0a}, 0x05}, | |
215 | ||
216 | {{0x9e, 0xd1}, 0xa1}, | |
34f7e57b | 217 | {{0x99, 0x23}, 0x01}, |
bbed0dee | 218 | |
34f7e57b AU |
219 | {{0x9e, 0x74}, 0x00}, |
220 | {{0x9e, 0x90}, 0x00}, | |
bbed0dee EL |
221 | {{0x9f, 0x28}, 0x10}, |
222 | ||
34f7e57b | 223 | {{0x9f, 0x35}, 0x04}, |
bbed0dee | 224 | |
34f7e57b | 225 | {{0x9f, 0x36}, 0x11}, |
bbed0dee EL |
226 | |
227 | {{0x9c, 0x31}, 0x00}, | |
228 | ||
34f7e57b | 229 | {{0x9c, 0x32}, 0x00}, |
bbed0dee | 230 | |
34f7e57b | 231 | {{0x9c, 0x19}, 0x0a}, |
bbed0dee | 232 | |
34f7e57b | 233 | {{0x9c, 0x1a}, 0x0a}, |
bbed0dee EL |
234 | |
235 | {{0x9c, 0x0c}, 0x00}, | |
236 | ||
237 | {{0x9c, 0x0d}, 0x00}, | |
238 | ||
239 | {{0x9c, 0x12}, 0x00}, | |
240 | ||
241 | {{0x9c, 0x13}, 0x00}, | |
242 | ||
34f7e57b | 243 | {{0x98, 0xa2}, 0x09}, |
bbed0dee | 244 | |
34f7e57b | 245 | {{0x98, 0x93}, 0x00}, |
bbed0dee | 246 | |
34f7e57b | 247 | {{0x98, 0x7d}, 0x08}, |
bbed0dee | 248 | {{0x98, 0x7e}, 0x00}, |
34f7e57b | 249 | {{0x9f, 0xc8}, 0x00}, |
bbed0dee EL |
250 | }; |
251 | struct hw_config *p = hw_config; | |
252 | int count = ARRAY_SIZE(hw_config); | |
253 | struct sk_buff *res_skb; | |
254 | u8 param[4]; | |
255 | int r; | |
256 | ||
257 | param[0] = 0; | |
258 | while (count--) { | |
259 | param[1] = p->adr[0]; | |
260 | param[2] = p->adr[1]; | |
261 | param[3] = p->value; | |
262 | ||
263 | r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_WRITE, | |
264 | param, 4, &res_skb); | |
265 | if (r < 0) | |
266 | return r; | |
267 | ||
268 | if (res_skb->len != 1) { | |
269 | kfree_skb(res_skb); | |
270 | return -EPROTO; | |
271 | } | |
272 | ||
273 | if (res_skb->data[0] != p->value) { | |
274 | kfree_skb(res_skb); | |
275 | return -EIO; | |
276 | } | |
277 | ||
278 | kfree_skb(res_skb); | |
279 | ||
280 | p++; | |
281 | } | |
282 | ||
283 | param[0] = NFC_HCI_UICC_HOST_ID; | |
284 | r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, | |
285 | NFC_HCI_ADMIN_WHITELIST, param, 1); | |
286 | if (r < 0) | |
287 | return r; | |
288 | ||
289 | param[0] = 0x3d; | |
290 | r = nfc_hci_set_param(hdev, PN544_SYS_MGMT_GATE, | |
291 | PN544_SYS_MGMT_INFO_NOTIFICATION, param, 1); | |
292 | if (r < 0) | |
293 | return r; | |
294 | ||
295 | param[0] = 0x0; | |
296 | r = nfc_hci_set_param(hdev, NFC_HCI_RF_READER_A_GATE, | |
297 | PN544_RF_READER_A_AUTO_ACTIVATION, param, 1); | |
298 | if (r < 0) | |
299 | return r; | |
300 | ||
301 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | |
302 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | |
303 | if (r < 0) | |
304 | return r; | |
305 | ||
306 | param[0] = 0x1; | |
307 | r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, | |
308 | PN544_PL_NFCT_DEACTIVATED, param, 1); | |
309 | if (r < 0) | |
310 | return r; | |
311 | ||
312 | param[0] = 0x0; | |
313 | r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, | |
314 | PN544_PL_RDPHASES, param, 1); | |
315 | if (r < 0) | |
316 | return r; | |
317 | ||
318 | r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, | |
319 | PN544_ID_MGMT_FULL_VERSION_SW, &skb); | |
320 | if (r < 0) | |
321 | return r; | |
322 | ||
323 | if (skb->len != FULL_VERSION_LEN) { | |
324 | kfree_skb(skb); | |
325 | return -EINVAL; | |
326 | } | |
327 | ||
328 | print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ", | |
329 | DUMP_PREFIX_NONE, 16, 1, | |
330 | skb->data, FULL_VERSION_LEN, false); | |
331 | ||
332 | kfree_skb(skb); | |
333 | ||
334 | return 0; | |
335 | } | |
336 | ||
412fda53 | 337 | static int pn544_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) |
bbed0dee | 338 | { |
412fda53 | 339 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); |
ade67208 | 340 | |
97f18414 | 341 | return info->phy_ops->write(info->phy_id, skb); |
bbed0dee EL |
342 | } |
343 | ||
412fda53 | 344 | static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, |
fe7c5800 | 345 | u32 im_protocols, u32 tm_protocols) |
bbed0dee | 346 | { |
bbed0dee EL |
347 | u8 phases = 0; |
348 | int r; | |
349 | u8 duration[2]; | |
350 | u8 activated; | |
7e2afc9d AW |
351 | u8 i_mode = 0x3f; /* Enable all supported modes */ |
352 | u8 t_mode = 0x0f; | |
353 | u8 t_merge = 0x01; /* Enable merge by default */ | |
bbed0dee | 354 | |
fe7c5800 SO |
355 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", |
356 | __func__, im_protocols, tm_protocols); | |
bbed0dee EL |
357 | |
358 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | |
359 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | |
360 | if (r < 0) | |
361 | return r; | |
362 | ||
363 | duration[0] = 0x18; | |
364 | duration[1] = 0x6a; | |
365 | r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, | |
366 | PN544_PL_EMULATION, duration, 2); | |
367 | if (r < 0) | |
368 | return r; | |
369 | ||
370 | activated = 0; | |
371 | r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, | |
372 | PN544_PL_NFCT_DEACTIVATED, &activated, 1); | |
373 | if (r < 0) | |
374 | return r; | |
375 | ||
fe7c5800 | 376 | if (im_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK | |
bbed0dee EL |
377 | NFC_PROTO_JEWEL_MASK)) |
378 | phases |= 1; /* Type A */ | |
fe7c5800 | 379 | if (im_protocols & NFC_PROTO_FELICA_MASK) { |
bbed0dee EL |
380 | phases |= (1 << 2); /* Type F 212 */ |
381 | phases |= (1 << 3); /* Type F 424 */ | |
382 | } | |
383 | ||
384 | phases |= (1 << 5); /* NFC active */ | |
385 | ||
386 | r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, | |
387 | PN544_PL_RDPHASES, &phases, 1); | |
388 | if (r < 0) | |
389 | return r; | |
390 | ||
7e2afc9d AW |
391 | if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { |
392 | hdev->gb = nfc_get_local_general_bytes(hdev->ndev, | |
393 | &hdev->gb_len); | |
17936b43 | 394 | pr_debug("generate local bytes %p\n", hdev->gb); |
7e2afc9d AW |
395 | if (hdev->gb == NULL || hdev->gb_len == 0) { |
396 | im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | |
397 | tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | |
398 | } | |
399 | } | |
400 | ||
401 | if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { | |
402 | r = nfc_hci_send_event(hdev, | |
403 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
404 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | |
405 | if (r < 0) | |
406 | return r; | |
407 | ||
408 | r = nfc_hci_set_param(hdev, | |
409 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
410 | PN544_DEP_MODE, &i_mode, 1); | |
411 | if (r < 0) | |
412 | return r; | |
413 | ||
414 | r = nfc_hci_set_param(hdev, | |
415 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
416 | PN544_DEP_ATR_REQ, hdev->gb, hdev->gb_len); | |
417 | if (r < 0) | |
418 | return r; | |
419 | ||
420 | r = nfc_hci_send_event(hdev, | |
421 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
422 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | |
423 | if (r < 0) | |
424 | nfc_hci_send_event(hdev, | |
425 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
426 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | |
427 | } | |
428 | ||
429 | if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | |
430 | r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | |
431 | PN544_DEP_MODE, &t_mode, 1); | |
432 | if (r < 0) | |
433 | return r; | |
434 | ||
435 | r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | |
436 | PN544_DEP_ATR_RES, hdev->gb, hdev->gb_len); | |
437 | if (r < 0) | |
438 | return r; | |
439 | ||
440 | r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | |
441 | PN544_DEP_MERGE, &t_merge, 1); | |
442 | if (r < 0) | |
443 | return r; | |
444 | } | |
445 | ||
bbed0dee EL |
446 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
447 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | |
448 | if (r < 0) | |
449 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | |
450 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | |
451 | ||
452 | return r; | |
453 | } | |
454 | ||
c40d1740 AW |
455 | static int pn544_hci_dep_link_up(struct nfc_hci_dev *hdev, |
456 | struct nfc_target *target, u8 comm_mode, | |
457 | u8 *gb, size_t gb_len) | |
458 | { | |
459 | struct sk_buff *rgb_skb = NULL; | |
460 | int r; | |
461 | ||
462 | r = nfc_hci_get_param(hdev, target->hci_reader_gate, | |
463 | PN544_DEP_ATR_RES, &rgb_skb); | |
464 | if (r < 0) | |
465 | return r; | |
466 | ||
467 | if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) { | |
468 | r = -EPROTO; | |
469 | goto exit; | |
470 | } | |
471 | print_hex_dump(KERN_DEBUG, "remote gb: ", DUMP_PREFIX_OFFSET, | |
472 | 16, 1, rgb_skb->data, rgb_skb->len, true); | |
473 | ||
474 | r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data, | |
475 | rgb_skb->len); | |
476 | ||
477 | if (r == 0) | |
478 | r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode, | |
479 | NFC_RF_INITIATOR); | |
480 | exit: | |
481 | kfree_skb(rgb_skb); | |
482 | return r; | |
483 | } | |
484 | ||
485 | static int pn544_hci_dep_link_down(struct nfc_hci_dev *hdev) | |
486 | { | |
487 | ||
488 | return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
489 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | |
490 | } | |
491 | ||
412fda53 | 492 | static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, |
bbed0dee EL |
493 | struct nfc_target *target) |
494 | { | |
495 | switch (gate) { | |
496 | case PN544_RF_READER_F_GATE: | |
497 | target->supported_protocols = NFC_PROTO_FELICA_MASK; | |
498 | break; | |
499 | case PN544_RF_READER_JEWEL_GATE: | |
500 | target->supported_protocols = NFC_PROTO_JEWEL_MASK; | |
501 | target->sens_res = 0x0c00; | |
502 | break; | |
928326f2 AW |
503 | case PN544_RF_READER_NFCIP1_INITIATOR_GATE: |
504 | target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; | |
505 | break; | |
bbed0dee EL |
506 | default: |
507 | return -EPROTO; | |
508 | } | |
509 | ||
510 | return 0; | |
511 | } | |
512 | ||
412fda53 | 513 | static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev, |
bbed0dee EL |
514 | u8 gate, |
515 | struct nfc_target *target) | |
516 | { | |
bbed0dee EL |
517 | struct sk_buff *uid_skb; |
518 | int r = 0; | |
519 | ||
928326f2 AW |
520 | if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) |
521 | return r; | |
522 | ||
523 | if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { | |
524 | r = nfc_hci_send_cmd(hdev, | |
525 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
526 | PN544_HCI_CMD_CONTINUE_ACTIVATION, NULL, 0, NULL); | |
527 | if (r < 0) | |
528 | return r; | |
529 | ||
530 | target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE; | |
531 | } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | |
bbed0dee EL |
532 | if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && |
533 | target->nfcid1_len != 10) | |
534 | return -EPROTO; | |
535 | ||
536 | r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, | |
537 | PN544_RF_READER_CMD_ACTIVATE_NEXT, | |
538 | target->nfcid1, target->nfcid1_len, NULL); | |
539 | } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) { | |
540 | r = nfc_hci_get_param(hdev, PN544_RF_READER_F_GATE, | |
541 | PN544_FELICA_ID, &uid_skb); | |
542 | if (r < 0) | |
543 | return r; | |
544 | ||
545 | if (uid_skb->len != 8) { | |
546 | kfree_skb(uid_skb); | |
547 | return -EPROTO; | |
548 | } | |
549 | ||
9c598440 AW |
550 | /* Type F NFC-DEP IDm has prefix 0x01FE */ |
551 | if ((uid_skb->data[0] == 0x01) && (uid_skb->data[1] == 0xfe)) { | |
552 | kfree_skb(uid_skb); | |
553 | r = nfc_hci_send_cmd(hdev, | |
928326f2 AW |
554 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, |
555 | PN544_HCI_CMD_CONTINUE_ACTIVATION, | |
556 | NULL, 0, NULL); | |
9c598440 AW |
557 | if (r < 0) |
558 | return r; | |
559 | ||
560 | target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; | |
561 | target->hci_reader_gate = | |
562 | PN544_RF_READER_NFCIP1_INITIATOR_GATE; | |
563 | } else { | |
564 | r = nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, | |
565 | PN544_RF_READER_CMD_ACTIVATE_NEXT, | |
566 | uid_skb->data, uid_skb->len, NULL); | |
567 | kfree_skb(uid_skb); | |
568 | } | |
bbed0dee EL |
569 | } else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) { |
570 | /* | |
571 | * TODO: maybe other ISO 14443 require some kind of continue | |
572 | * activation, but for now we've seen only this one below. | |
573 | */ | |
574 | if (target->sens_res == 0x4403) /* Type 4 Mifare DESFire */ | |
575 | r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, | |
576 | PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION, | |
577 | NULL, 0, NULL); | |
578 | } | |
579 | ||
580 | return r; | |
581 | } | |
582 | ||
f3e8fb55 EL |
583 | #define PN544_CB_TYPE_READER_F 1 |
584 | ||
585 | static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb, | |
586 | int err) | |
587 | { | |
588 | struct pn544_hci_info *info = context; | |
589 | ||
590 | switch (info->async_cb_type) { | |
591 | case PN544_CB_TYPE_READER_F: | |
592 | if (err == 0) | |
593 | skb_pull(skb, 1); | |
594 | info->async_cb(info->async_cb_context, skb, err); | |
595 | break; | |
596 | default: | |
597 | if (err == 0) | |
598 | kfree_skb(skb); | |
599 | break; | |
600 | } | |
601 | } | |
602 | ||
bbed0dee EL |
603 | #define MIFARE_CMD_AUTH_KEY_A 0x60 |
604 | #define MIFARE_CMD_AUTH_KEY_B 0x61 | |
605 | #define MIFARE_CMD_HEADER 2 | |
606 | #define MIFARE_UID_LEN 4 | |
607 | #define MIFARE_KEY_LEN 6 | |
608 | #define MIFARE_CMD_LEN 12 | |
609 | /* | |
610 | * Returns: | |
611 | * <= 0: driver handled the data exchange | |
612 | * 1: driver doesn't especially handle, please do standard processing | |
613 | */ | |
e8107623 | 614 | static int pn544_hci_im_transceive(struct nfc_hci_dev *hdev, |
bbed0dee | 615 | struct nfc_target *target, |
f3e8fb55 EL |
616 | struct sk_buff *skb, data_exchange_cb_t cb, |
617 | void *cb_context) | |
bbed0dee | 618 | { |
412fda53 | 619 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); |
bbed0dee EL |
620 | |
621 | pr_info(DRIVER_DESC ": %s for gate=%d\n", __func__, | |
622 | target->hci_reader_gate); | |
623 | ||
624 | switch (target->hci_reader_gate) { | |
625 | case NFC_HCI_RF_READER_A_GATE: | |
626 | if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | |
627 | /* | |
628 | * It seems that pn544 is inverting key and UID for | |
629 | * MIFARE authentication commands. | |
630 | */ | |
631 | if (skb->len == MIFARE_CMD_LEN && | |
632 | (skb->data[0] == MIFARE_CMD_AUTH_KEY_A || | |
633 | skb->data[0] == MIFARE_CMD_AUTH_KEY_B)) { | |
634 | u8 uid[MIFARE_UID_LEN]; | |
635 | u8 *data = skb->data + MIFARE_CMD_HEADER; | |
636 | ||
637 | memcpy(uid, data + MIFARE_KEY_LEN, | |
638 | MIFARE_UID_LEN); | |
639 | memmove(data + MIFARE_UID_LEN, data, | |
640 | MIFARE_KEY_LEN); | |
641 | memcpy(data, uid, MIFARE_UID_LEN); | |
642 | } | |
643 | ||
f3e8fb55 EL |
644 | return nfc_hci_send_cmd_async(hdev, |
645 | target->hci_reader_gate, | |
646 | PN544_MIFARE_CMD, | |
647 | skb->data, skb->len, | |
648 | cb, cb_context); | |
bbed0dee EL |
649 | } else |
650 | return 1; | |
651 | case PN544_RF_READER_F_GATE: | |
652 | *skb_push(skb, 1) = 0; | |
653 | *skb_push(skb, 1) = 0; | |
654 | ||
f3e8fb55 EL |
655 | info->async_cb_type = PN544_CB_TYPE_READER_F; |
656 | info->async_cb = cb; | |
657 | info->async_cb_context = cb_context; | |
658 | ||
659 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, | |
660 | PN544_FELICA_RAW, skb->data, | |
661 | skb->len, | |
662 | pn544_hci_data_exchange_cb, info); | |
bbed0dee | 663 | case PN544_RF_READER_JEWEL_GATE: |
f3e8fb55 EL |
664 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, |
665 | PN544_JEWEL_RAW_CMD, skb->data, | |
666 | skb->len, cb, cb_context); | |
e8107623 AW |
667 | case PN544_RF_READER_NFCIP1_INITIATOR_GATE: |
668 | *skb_push(skb, 1) = 0; | |
669 | ||
670 | return nfc_hci_send_event(hdev, target->hci_reader_gate, | |
671 | PN544_HCI_EVT_SND_DATA, skb->data, | |
672 | skb->len); | |
bbed0dee EL |
673 | default: |
674 | return 1; | |
675 | } | |
676 | } | |
677 | ||
e8107623 AW |
678 | static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) |
679 | { | |
924d4a02 EL |
680 | int r; |
681 | ||
e8107623 AW |
682 | /* Set default false for multiple information chaining */ |
683 | *skb_push(skb, 1) = 0; | |
684 | ||
924d4a02 EL |
685 | r = nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, |
686 | PN544_HCI_EVT_SND_DATA, skb->data, skb->len); | |
687 | ||
688 | kfree_skb(skb); | |
689 | ||
690 | return r; | |
e8107623 AW |
691 | } |
692 | ||
412fda53 | 693 | static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, |
bbed0dee EL |
694 | struct nfc_target *target) |
695 | { | |
17936b43 | 696 | pr_debug("supported protocol %d\b", target->supported_protocols); |
da052850 AW |
697 | if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK | |
698 | NFC_PROTO_ISO14443_B_MASK)) { | |
699 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | |
700 | PN544_RF_READER_CMD_PRESENCE_CHECK, | |
701 | NULL, 0, NULL); | |
702 | } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | |
703 | if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && | |
704 | target->nfcid1_len != 10) | |
632c016a | 705 | return -EOPNOTSUPP; |
da052850 AW |
706 | |
707 | return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, | |
708 | PN544_RF_READER_CMD_ACTIVATE_NEXT, | |
709 | target->nfcid1, target->nfcid1_len, NULL); | |
a69bdc1e AW |
710 | } else if (target->supported_protocols & (NFC_PROTO_JEWEL_MASK | |
711 | NFC_PROTO_FELICA_MASK)) { | |
712 | return -EOPNOTSUPP; | |
da052850 AW |
713 | } else if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { |
714 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | |
715 | PN544_HCI_CMD_ATTREQUEST, | |
716 | NULL, 0, NULL); | |
717 | } | |
718 | ||
719 | return 0; | |
bbed0dee EL |
720 | } |
721 | ||
40d06d36 EL |
722 | /* |
723 | * Returns: | |
724 | * <= 0: driver handled the event, skb consumed | |
725 | * 1: driver does not handle the event, please do standard processing | |
726 | */ | |
8abe3c6a | 727 | static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, |
27c31191 | 728 | struct sk_buff *skb) |
f7a5f6c5 AW |
729 | { |
730 | struct sk_buff *rgb_skb = NULL; | |
8abe3c6a | 731 | u8 gate = hdev->pipes[pipe].gate; |
40d06d36 | 732 | int r; |
f7a5f6c5 | 733 | |
17936b43 | 734 | pr_debug("hci event %d\n", event); |
f7a5f6c5 AW |
735 | switch (event) { |
736 | case PN544_HCI_EVT_ACTIVATED: | |
40d06d36 | 737 | if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) { |
27c31191 | 738 | r = nfc_hci_target_discovered(hdev, gate); |
40d06d36 | 739 | } else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { |
f7a5f6c5 | 740 | r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ, |
27c31191 | 741 | &rgb_skb); |
f7a5f6c5 AW |
742 | if (r < 0) |
743 | goto exit; | |
744 | ||
27c31191 EL |
745 | r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, |
746 | NFC_COMM_PASSIVE, rgb_skb->data, | |
747 | rgb_skb->len); | |
f7a5f6c5 AW |
748 | |
749 | kfree_skb(rgb_skb); | |
40d06d36 EL |
750 | } else { |
751 | r = -EINVAL; | |
f7a5f6c5 | 752 | } |
f7a5f6c5 AW |
753 | break; |
754 | case PN544_HCI_EVT_DEACTIVATED: | |
27c31191 EL |
755 | r = nfc_hci_send_event(hdev, gate, NFC_HCI_EVT_END_OPERATION, |
756 | NULL, 0); | |
f7a5f6c5 | 757 | break; |
e8107623 AW |
758 | case PN544_HCI_EVT_RCV_DATA: |
759 | if (skb->len < 2) { | |
760 | r = -EPROTO; | |
761 | goto exit; | |
762 | } | |
763 | ||
764 | if (skb->data[0] != 0) { | |
17936b43 | 765 | pr_debug("data0 %d\n", skb->data[0]); |
e8107623 AW |
766 | r = -EPROTO; |
767 | goto exit; | |
768 | } | |
769 | ||
770 | skb_pull(skb, 2); | |
27c31191 | 771 | return nfc_tm_data_received(hdev->ndev, skb); |
f7a5f6c5 | 772 | default: |
40d06d36 | 773 | return 1; |
f7a5f6c5 AW |
774 | } |
775 | ||
776 | exit: | |
777 | kfree_skb(skb); | |
27c31191 EL |
778 | |
779 | return r; | |
f7a5f6c5 AW |
780 | } |
781 | ||
8bd7fc89 EL |
782 | static int pn544_hci_fw_download(struct nfc_hci_dev *hdev, |
783 | const char *firmware_name) | |
784 | { | |
785 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); | |
786 | ||
787 | if (info->fw_download == NULL) | |
788 | return -ENOTSUPP; | |
789 | ||
971d63cf | 790 | return info->fw_download(info->phy_id, firmware_name, hdev->sw_romlib); |
8bd7fc89 EL |
791 | } |
792 | ||
5faba2fd AW |
793 | static int pn544_hci_discover_se(struct nfc_hci_dev *hdev) |
794 | { | |
795 | u32 se_idx = 0; | |
796 | u8 ese_mode = 0x01; /* Default mode */ | |
797 | struct sk_buff *res_skb; | |
798 | int r; | |
799 | ||
800 | r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_TEST_SWP, | |
801 | NULL, 0, &res_skb); | |
802 | ||
803 | if (r == 0) { | |
804 | if (res_skb->len == 2 && res_skb->data[0] == 0x00) | |
805 | nfc_add_se(hdev->ndev, se_idx++, NFC_SE_UICC); | |
806 | ||
807 | kfree_skb(res_skb); | |
808 | } | |
809 | ||
810 | r = nfc_hci_send_event(hdev, PN544_NFC_WI_MGMT_GATE, | |
811 | PN544_HCI_EVT_SWITCH_MODE, | |
812 | &ese_mode, 1); | |
813 | if (r == 0) | |
814 | nfc_add_se(hdev->ndev, se_idx++, NFC_SE_EMBEDDED); | |
815 | ||
816 | return !se_idx; | |
817 | } | |
818 | ||
39438261 AW |
819 | #define PN544_SE_MODE_OFF 0x00 |
820 | #define PN544_SE_MODE_ON 0x01 | |
821 | static int pn544_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx) | |
822 | { | |
823 | struct nfc_se *se; | |
824 | u8 enable = PN544_SE_MODE_ON; | |
825 | static struct uicc_gatelist { | |
826 | u8 head; | |
827 | u8 adr[2]; | |
828 | u8 value; | |
829 | } uicc_gatelist[] = { | |
830 | {0x00, {0x9e, 0xd9}, 0x23}, | |
831 | {0x00, {0x9e, 0xda}, 0x21}, | |
832 | {0x00, {0x9e, 0xdb}, 0x22}, | |
833 | {0x00, {0x9e, 0xdc}, 0x24}, | |
834 | }; | |
835 | struct uicc_gatelist *p = uicc_gatelist; | |
836 | int count = ARRAY_SIZE(uicc_gatelist); | |
837 | struct sk_buff *res_skb; | |
838 | int r; | |
839 | ||
840 | se = nfc_find_se(hdev->ndev, se_idx); | |
841 | ||
842 | switch (se->type) { | |
843 | case NFC_SE_UICC: | |
844 | while (count--) { | |
845 | r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, | |
846 | PN544_WRITE, (u8 *)p, 4, &res_skb); | |
847 | if (r < 0) | |
848 | return r; | |
849 | ||
850 | if (res_skb->len != 1) { | |
851 | kfree_skb(res_skb); | |
852 | return -EPROTO; | |
853 | } | |
854 | ||
855 | if (res_skb->data[0] != p->value) { | |
856 | kfree_skb(res_skb); | |
857 | return -EIO; | |
858 | } | |
859 | ||
860 | kfree_skb(res_skb); | |
861 | ||
862 | p++; | |
863 | } | |
864 | ||
865 | return nfc_hci_set_param(hdev, PN544_SWP_MGMT_GATE, | |
866 | PN544_SWP_DEFAULT_MODE, &enable, 1); | |
867 | case NFC_SE_EMBEDDED: | |
868 | return nfc_hci_set_param(hdev, PN544_NFC_WI_MGMT_GATE, | |
869 | PN544_NFC_ESE_DEFAULT_MODE, &enable, 1); | |
870 | ||
871 | default: | |
872 | return -EINVAL; | |
873 | } | |
874 | } | |
875 | ||
876 | static int pn544_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx) | |
877 | { | |
878 | struct nfc_se *se; | |
879 | u8 disable = PN544_SE_MODE_OFF; | |
880 | ||
881 | se = nfc_find_se(hdev->ndev, se_idx); | |
882 | ||
883 | switch (se->type) { | |
884 | case NFC_SE_UICC: | |
885 | return nfc_hci_set_param(hdev, PN544_SWP_MGMT_GATE, | |
886 | PN544_SWP_DEFAULT_MODE, &disable, 1); | |
887 | case NFC_SE_EMBEDDED: | |
888 | return nfc_hci_set_param(hdev, PN544_NFC_WI_MGMT_GATE, | |
889 | PN544_NFC_ESE_DEFAULT_MODE, &disable, 1); | |
890 | default: | |
891 | return -EINVAL; | |
892 | } | |
893 | } | |
894 | ||
412fda53 | 895 | static struct nfc_hci_ops pn544_hci_ops = { |
bbed0dee EL |
896 | .open = pn544_hci_open, |
897 | .close = pn544_hci_close, | |
898 | .hci_ready = pn544_hci_ready, | |
899 | .xmit = pn544_hci_xmit, | |
900 | .start_poll = pn544_hci_start_poll, | |
c40d1740 AW |
901 | .dep_link_up = pn544_hci_dep_link_up, |
902 | .dep_link_down = pn544_hci_dep_link_down, | |
bbed0dee EL |
903 | .target_from_gate = pn544_hci_target_from_gate, |
904 | .complete_target_discovered = pn544_hci_complete_target_discovered, | |
e8107623 AW |
905 | .im_transceive = pn544_hci_im_transceive, |
906 | .tm_send = pn544_hci_tm_send, | |
bbed0dee | 907 | .check_presence = pn544_hci_check_presence, |
f7a5f6c5 | 908 | .event_received = pn544_hci_event_received, |
8bd7fc89 | 909 | .fw_download = pn544_hci_fw_download, |
5faba2fd | 910 | .discover_se = pn544_hci_discover_se, |
39438261 AW |
911 | .enable_se = pn544_hci_enable_se, |
912 | .disable_se = pn544_hci_disable_se, | |
bbed0dee EL |
913 | }; |
914 | ||
97f18414 EL |
915 | int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, |
916 | int phy_headroom, int phy_tailroom, int phy_payload, | |
8bd7fc89 | 917 | fw_download_t fw_download, struct nfc_hci_dev **hdev) |
bbed0dee EL |
918 | { |
919 | struct pn544_hci_info *info; | |
0b456c41 | 920 | u32 protocols; |
bbed0dee | 921 | struct nfc_hci_init_data init_data; |
97f18414 | 922 | int r; |
bbed0dee EL |
923 | |
924 | info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL); | |
925 | if (!info) { | |
bbed0dee EL |
926 | r = -ENOMEM; |
927 | goto err_info_alloc; | |
928 | } | |
929 | ||
97f18414 EL |
930 | info->phy_ops = phy_ops; |
931 | info->phy_id = phy_id; | |
8bd7fc89 | 932 | info->fw_download = fw_download; |
bbed0dee EL |
933 | info->state = PN544_ST_COLD; |
934 | mutex_init(&info->info_lock); | |
bbed0dee | 935 | |
a10d595b | 936 | init_data.gate_count = ARRAY_SIZE(pn544_gates); |
bbed0dee | 937 | |
a10d595b | 938 | memcpy(init_data.gates, pn544_gates, sizeof(pn544_gates)); |
bbed0dee EL |
939 | |
940 | /* | |
941 | * TODO: Session id must include the driver name + some bus addr | |
942 | * persistent info to discriminate 2 identical chips | |
943 | */ | |
944 | strcpy(init_data.session_id, "ID544HCI"); | |
945 | ||
946 | protocols = NFC_PROTO_JEWEL_MASK | | |
947 | NFC_PROTO_MIFARE_MASK | | |
948 | NFC_PROTO_FELICA_MASK | | |
949 | NFC_PROTO_ISO14443_MASK | | |
01d719a2 | 950 | NFC_PROTO_ISO14443_B_MASK | |
bbed0dee EL |
951 | NFC_PROTO_NFC_DEP_MASK; |
952 | ||
bf71ab8b | 953 | info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, 0, |
0b456c41 | 954 | protocols, llc_name, |
97f18414 EL |
955 | phy_headroom + PN544_CMDS_HEADROOM, |
956 | phy_tailroom, phy_payload); | |
412fda53 | 957 | if (!info->hdev) { |
17936b43 | 958 | pr_err("Cannot allocate nfc hdev\n"); |
bbed0dee | 959 | r = -ENOMEM; |
412fda53 | 960 | goto err_alloc_hdev; |
bbed0dee EL |
961 | } |
962 | ||
412fda53 EL |
963 | nfc_hci_set_clientdata(info->hdev, info); |
964 | ||
965 | r = nfc_hci_register_device(info->hdev); | |
966 | if (r) | |
967 | goto err_regdev; | |
bbed0dee | 968 | |
97f18414 EL |
969 | *hdev = info->hdev; |
970 | ||
bbed0dee EL |
971 | return 0; |
972 | ||
412fda53 EL |
973 | err_regdev: |
974 | nfc_hci_free_device(info->hdev); | |
975 | ||
976 | err_alloc_hdev: | |
bbed0dee EL |
977 | kfree(info); |
978 | ||
979 | err_info_alloc: | |
980 | return r; | |
981 | } | |
aa741030 | 982 | EXPORT_SYMBOL(pn544_hci_probe); |
bbed0dee | 983 | |
97f18414 | 984 | void pn544_hci_remove(struct nfc_hci_dev *hdev) |
bbed0dee | 985 | { |
97f18414 | 986 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); |
bbed0dee | 987 | |
97f18414 EL |
988 | nfc_hci_unregister_device(hdev); |
989 | nfc_hci_free_device(hdev); | |
bbed0dee | 990 | kfree(info); |
bbed0dee | 991 | } |
aa741030 SO |
992 | EXPORT_SYMBOL(pn544_hci_remove); |
993 | ||
994 | MODULE_LICENSE("GPL"); | |
995 | MODULE_DESCRIPTION(DRIVER_DESC); |