]>
Commit | Line | Data |
---|---|---|
cfad1ba8 EL |
1 | /* |
2 | * HCI based Driver for Inside Secure microread NFC Chip | |
3 | * | |
4 | * Copyright (C) 2013 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/>. |
cfad1ba8 EL |
17 | */ |
18 | ||
17936b43 JP |
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
20 | ||
cfad1ba8 EL |
21 | #include <linux/module.h> |
22 | #include <linux/delay.h> | |
23 | #include <linux/slab.h> | |
24 | #include <linux/crc-ccitt.h> | |
25 | ||
26 | #include <linux/nfc.h> | |
27 | #include <net/nfc/nfc.h> | |
28 | #include <net/nfc/hci.h> | |
29 | #include <net/nfc/llc.h> | |
30 | ||
31 | #include "microread.h" | |
32 | ||
33 | /* Proprietary gates, events, commands and registers */ | |
34 | /* Admin */ | |
35 | #define MICROREAD_GATE_ID_ADM NFC_HCI_ADMIN_GATE | |
36 | #define MICROREAD_GATE_ID_MGT 0x01 | |
37 | #define MICROREAD_GATE_ID_OS 0x02 | |
38 | #define MICROREAD_GATE_ID_TESTRF 0x03 | |
39 | #define MICROREAD_GATE_ID_LOOPBACK NFC_HCI_LOOPBACK_GATE | |
40 | #define MICROREAD_GATE_ID_IDT NFC_HCI_ID_MGMT_GATE | |
41 | #define MICROREAD_GATE_ID_LMS NFC_HCI_LINK_MGMT_GATE | |
42 | ||
43 | /* Reader */ | |
44 | #define MICROREAD_GATE_ID_MREAD_GEN 0x10 | |
45 | #define MICROREAD_GATE_ID_MREAD_ISO_B NFC_HCI_RF_READER_B_GATE | |
46 | #define MICROREAD_GATE_ID_MREAD_NFC_T1 0x12 | |
47 | #define MICROREAD_GATE_ID_MREAD_ISO_A NFC_HCI_RF_READER_A_GATE | |
48 | #define MICROREAD_GATE_ID_MREAD_NFC_T3 0x14 | |
49 | #define MICROREAD_GATE_ID_MREAD_ISO_15_3 0x15 | |
50 | #define MICROREAD_GATE_ID_MREAD_ISO_15_2 0x16 | |
51 | #define MICROREAD_GATE_ID_MREAD_ISO_B_3 0x17 | |
52 | #define MICROREAD_GATE_ID_MREAD_BPRIME 0x18 | |
53 | #define MICROREAD_GATE_ID_MREAD_ISO_A_3 0x19 | |
54 | ||
55 | /* Card */ | |
56 | #define MICROREAD_GATE_ID_MCARD_GEN 0x20 | |
57 | #define MICROREAD_GATE_ID_MCARD_ISO_B 0x21 | |
58 | #define MICROREAD_GATE_ID_MCARD_BPRIME 0x22 | |
59 | #define MICROREAD_GATE_ID_MCARD_ISO_A 0x23 | |
60 | #define MICROREAD_GATE_ID_MCARD_NFC_T3 0x24 | |
61 | #define MICROREAD_GATE_ID_MCARD_ISO_15_3 0x25 | |
62 | #define MICROREAD_GATE_ID_MCARD_ISO_15_2 0x26 | |
63 | #define MICROREAD_GATE_ID_MCARD_ISO_B_2 0x27 | |
64 | #define MICROREAD_GATE_ID_MCARD_ISO_CUSTOM 0x28 | |
65 | #define MICROREAD_GATE_ID_SECURE_ELEMENT 0x2F | |
66 | ||
67 | /* P2P */ | |
68 | #define MICROREAD_GATE_ID_P2P_GEN 0x30 | |
69 | #define MICROREAD_GATE_ID_P2P_TARGET 0x31 | |
70 | #define MICROREAD_PAR_P2P_TARGET_MODE 0x01 | |
71 | #define MICROREAD_PAR_P2P_TARGET_GT 0x04 | |
72 | #define MICROREAD_GATE_ID_P2P_INITIATOR 0x32 | |
73 | #define MICROREAD_PAR_P2P_INITIATOR_GI 0x01 | |
74 | #define MICROREAD_PAR_P2P_INITIATOR_GT 0x03 | |
75 | ||
76 | /* Those pipes are created/opened by default in the chip */ | |
77 | #define MICROREAD_PIPE_ID_LMS 0x00 | |
78 | #define MICROREAD_PIPE_ID_ADMIN 0x01 | |
79 | #define MICROREAD_PIPE_ID_MGT 0x02 | |
80 | #define MICROREAD_PIPE_ID_OS 0x03 | |
81 | #define MICROREAD_PIPE_ID_HDS_LOOPBACK 0x04 | |
82 | #define MICROREAD_PIPE_ID_HDS_IDT 0x05 | |
83 | #define MICROREAD_PIPE_ID_HDS_MCARD_ISO_B 0x08 | |
84 | #define MICROREAD_PIPE_ID_HDS_MCARD_ISO_BPRIME 0x09 | |
85 | #define MICROREAD_PIPE_ID_HDS_MCARD_ISO_A 0x0A | |
86 | #define MICROREAD_PIPE_ID_HDS_MCARD_ISO_15_3 0x0B | |
87 | #define MICROREAD_PIPE_ID_HDS_MCARD_ISO_15_2 0x0C | |
88 | #define MICROREAD_PIPE_ID_HDS_MCARD_NFC_T3 0x0D | |
89 | #define MICROREAD_PIPE_ID_HDS_MCARD_ISO_B_2 0x0E | |
90 | #define MICROREAD_PIPE_ID_HDS_MCARD_CUSTOM 0x0F | |
91 | #define MICROREAD_PIPE_ID_HDS_MREAD_ISO_B 0x10 | |
92 | #define MICROREAD_PIPE_ID_HDS_MREAD_NFC_T1 0x11 | |
93 | #define MICROREAD_PIPE_ID_HDS_MREAD_ISO_A 0x12 | |
94 | #define MICROREAD_PIPE_ID_HDS_MREAD_ISO_15_3 0x13 | |
95 | #define MICROREAD_PIPE_ID_HDS_MREAD_ISO_15_2 0x14 | |
96 | #define MICROREAD_PIPE_ID_HDS_MREAD_NFC_T3 0x15 | |
97 | #define MICROREAD_PIPE_ID_HDS_MREAD_ISO_B_3 0x16 | |
98 | #define MICROREAD_PIPE_ID_HDS_MREAD_BPRIME 0x17 | |
99 | #define MICROREAD_PIPE_ID_HDS_MREAD_ISO_A_3 0x18 | |
100 | #define MICROREAD_PIPE_ID_HDS_MREAD_GEN 0x1B | |
101 | #define MICROREAD_PIPE_ID_HDS_STACKED_ELEMENT 0x1C | |
102 | #define MICROREAD_PIPE_ID_HDS_INSTANCES 0x1D | |
103 | #define MICROREAD_PIPE_ID_HDS_TESTRF 0x1E | |
104 | #define MICROREAD_PIPE_ID_HDS_P2P_TARGET 0x1F | |
105 | #define MICROREAD_PIPE_ID_HDS_P2P_INITIATOR 0x20 | |
106 | ||
107 | /* Events */ | |
108 | #define MICROREAD_EVT_MREAD_DISCOVERY_OCCURED NFC_HCI_EVT_TARGET_DISCOVERED | |
109 | #define MICROREAD_EVT_MREAD_CARD_FOUND 0x3D | |
110 | #define MICROREAD_EMCF_A_ATQA 0 | |
111 | #define MICROREAD_EMCF_A_SAK 2 | |
112 | #define MICROREAD_EMCF_A_LEN 3 | |
113 | #define MICROREAD_EMCF_A_UID 4 | |
114 | #define MICROREAD_EMCF_A3_ATQA 0 | |
115 | #define MICROREAD_EMCF_A3_SAK 2 | |
116 | #define MICROREAD_EMCF_A3_LEN 3 | |
117 | #define MICROREAD_EMCF_A3_UID 4 | |
118 | #define MICROREAD_EMCF_B_UID 0 | |
119 | #define MICROREAD_EMCF_T1_ATQA 0 | |
120 | #define MICROREAD_EMCF_T1_UID 4 | |
121 | #define MICROREAD_EMCF_T3_UID 0 | |
122 | #define MICROREAD_EVT_MREAD_DISCOVERY_START NFC_HCI_EVT_READER_REQUESTED | |
123 | #define MICROREAD_EVT_MREAD_DISCOVERY_START_SOME 0x3E | |
124 | #define MICROREAD_EVT_MREAD_DISCOVERY_STOP NFC_HCI_EVT_END_OPERATION | |
125 | #define MICROREAD_EVT_MREAD_SIM_REQUESTS 0x3F | |
126 | #define MICROREAD_EVT_MCARD_EXCHANGE NFC_HCI_EVT_TARGET_DISCOVERED | |
127 | #define MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_TO_RF 0x20 | |
128 | #define MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_FROM_RF 0x21 | |
129 | #define MICROREAD_EVT_MCARD_FIELD_ON 0x11 | |
130 | #define MICROREAD_EVT_P2P_TARGET_ACTIVATED 0x13 | |
131 | #define MICROREAD_EVT_P2P_TARGET_DEACTIVATED 0x12 | |
132 | #define MICROREAD_EVT_MCARD_FIELD_OFF 0x14 | |
133 | ||
134 | /* Commands */ | |
135 | #define MICROREAD_CMD_MREAD_EXCHANGE 0x10 | |
136 | #define MICROREAD_CMD_MREAD_SUBSCRIBE 0x3F | |
137 | ||
138 | /* Hosts IDs */ | |
139 | #define MICROREAD_ELT_ID_HDS NFC_HCI_TERMINAL_HOST_ID | |
140 | #define MICROREAD_ELT_ID_SIM NFC_HCI_UICC_HOST_ID | |
141 | #define MICROREAD_ELT_ID_SE1 0x03 | |
142 | #define MICROREAD_ELT_ID_SE2 0x04 | |
143 | #define MICROREAD_ELT_ID_SE3 0x05 | |
144 | ||
145 | static struct nfc_hci_gate microread_gates[] = { | |
146 | {MICROREAD_GATE_ID_ADM, MICROREAD_PIPE_ID_ADMIN}, | |
147 | {MICROREAD_GATE_ID_LOOPBACK, MICROREAD_PIPE_ID_HDS_LOOPBACK}, | |
148 | {MICROREAD_GATE_ID_IDT, MICROREAD_PIPE_ID_HDS_IDT}, | |
149 | {MICROREAD_GATE_ID_LMS, MICROREAD_PIPE_ID_LMS}, | |
150 | {MICROREAD_GATE_ID_MREAD_ISO_B, MICROREAD_PIPE_ID_HDS_MREAD_ISO_B}, | |
151 | {MICROREAD_GATE_ID_MREAD_ISO_A, MICROREAD_PIPE_ID_HDS_MREAD_ISO_A}, | |
152 | {MICROREAD_GATE_ID_MREAD_ISO_A_3, MICROREAD_PIPE_ID_HDS_MREAD_ISO_A_3}, | |
153 | {MICROREAD_GATE_ID_MGT, MICROREAD_PIPE_ID_MGT}, | |
154 | {MICROREAD_GATE_ID_OS, MICROREAD_PIPE_ID_OS}, | |
155 | {MICROREAD_GATE_ID_MREAD_NFC_T1, MICROREAD_PIPE_ID_HDS_MREAD_NFC_T1}, | |
156 | {MICROREAD_GATE_ID_MREAD_NFC_T3, MICROREAD_PIPE_ID_HDS_MREAD_NFC_T3}, | |
157 | {MICROREAD_GATE_ID_P2P_TARGET, MICROREAD_PIPE_ID_HDS_P2P_TARGET}, | |
158 | {MICROREAD_GATE_ID_P2P_INITIATOR, MICROREAD_PIPE_ID_HDS_P2P_INITIATOR} | |
159 | }; | |
160 | ||
161 | /* Largest headroom needed for outgoing custom commands */ | |
162 | #define MICROREAD_CMDS_HEADROOM 2 | |
163 | #define MICROREAD_CMD_TAILROOM 2 | |
164 | ||
165 | struct microread_info { | |
166 | struct nfc_phy_ops *phy_ops; | |
167 | void *phy_id; | |
168 | ||
169 | struct nfc_hci_dev *hdev; | |
170 | ||
171 | int async_cb_type; | |
172 | data_exchange_cb_t async_cb; | |
173 | void *async_cb_context; | |
174 | }; | |
175 | ||
176 | static int microread_open(struct nfc_hci_dev *hdev) | |
177 | { | |
178 | struct microread_info *info = nfc_hci_get_clientdata(hdev); | |
179 | ||
180 | return info->phy_ops->enable(info->phy_id); | |
181 | } | |
182 | ||
183 | static void microread_close(struct nfc_hci_dev *hdev) | |
184 | { | |
185 | struct microread_info *info = nfc_hci_get_clientdata(hdev); | |
186 | ||
187 | info->phy_ops->disable(info->phy_id); | |
188 | } | |
189 | ||
190 | static int microread_hci_ready(struct nfc_hci_dev *hdev) | |
191 | { | |
192 | int r; | |
193 | u8 param[4]; | |
194 | ||
195 | param[0] = 0x03; | |
196 | r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_A, | |
197 | MICROREAD_CMD_MREAD_SUBSCRIBE, param, 1, NULL); | |
198 | if (r) | |
199 | return r; | |
200 | ||
201 | r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_A_3, | |
202 | MICROREAD_CMD_MREAD_SUBSCRIBE, NULL, 0, NULL); | |
203 | if (r) | |
204 | return r; | |
205 | ||
206 | param[0] = 0x00; | |
207 | param[1] = 0x03; | |
208 | param[2] = 0x00; | |
209 | r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_B, | |
210 | MICROREAD_CMD_MREAD_SUBSCRIBE, param, 3, NULL); | |
211 | if (r) | |
212 | return r; | |
213 | ||
214 | r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_NFC_T1, | |
215 | MICROREAD_CMD_MREAD_SUBSCRIBE, NULL, 0, NULL); | |
216 | if (r) | |
217 | return r; | |
218 | ||
219 | param[0] = 0xFF; | |
220 | param[1] = 0xFF; | |
221 | param[2] = 0x00; | |
222 | param[3] = 0x00; | |
223 | r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_NFC_T3, | |
224 | MICROREAD_CMD_MREAD_SUBSCRIBE, param, 4, NULL); | |
225 | ||
226 | return r; | |
227 | } | |
228 | ||
229 | static int microread_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) | |
230 | { | |
231 | struct microread_info *info = nfc_hci_get_clientdata(hdev); | |
232 | ||
233 | return info->phy_ops->write(info->phy_id, skb); | |
234 | } | |
235 | ||
236 | static int microread_start_poll(struct nfc_hci_dev *hdev, | |
237 | u32 im_protocols, u32 tm_protocols) | |
238 | { | |
239 | int r; | |
240 | ||
241 | u8 param[2]; | |
242 | u8 mode; | |
243 | ||
244 | param[0] = 0x00; | |
245 | param[1] = 0x00; | |
246 | ||
247 | if (im_protocols & NFC_PROTO_ISO14443_MASK) | |
248 | param[0] |= (1 << 2); | |
249 | ||
250 | if (im_protocols & NFC_PROTO_ISO14443_B_MASK) | |
251 | param[0] |= 1; | |
252 | ||
253 | if (im_protocols & NFC_PROTO_MIFARE_MASK) | |
254 | param[1] |= 1; | |
255 | ||
256 | if (im_protocols & NFC_PROTO_JEWEL_MASK) | |
257 | param[0] |= (1 << 1); | |
258 | ||
259 | if (im_protocols & NFC_PROTO_FELICA_MASK) | |
260 | param[0] |= (1 << 5); | |
261 | ||
262 | if (im_protocols & NFC_PROTO_NFC_DEP_MASK) | |
263 | param[1] |= (1 << 1); | |
264 | ||
265 | if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { | |
266 | hdev->gb = nfc_get_local_general_bytes(hdev->ndev, | |
267 | &hdev->gb_len); | |
268 | if (hdev->gb == NULL || hdev->gb_len == 0) { | |
269 | im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | |
270 | tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | |
271 | } | |
272 | } | |
273 | ||
274 | r = nfc_hci_send_event(hdev, MICROREAD_GATE_ID_MREAD_ISO_A, | |
275 | MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, 0); | |
276 | if (r) | |
277 | return r; | |
278 | ||
279 | mode = 0xff; | |
280 | r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, | |
281 | MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1); | |
282 | if (r) | |
283 | return r; | |
284 | ||
285 | if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { | |
286 | r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_INITIATOR, | |
287 | MICROREAD_PAR_P2P_INITIATOR_GI, | |
288 | hdev->gb, hdev->gb_len); | |
289 | if (r) | |
290 | return r; | |
291 | } | |
292 | ||
293 | if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | |
294 | r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, | |
295 | MICROREAD_PAR_P2P_TARGET_GT, | |
296 | hdev->gb, hdev->gb_len); | |
297 | if (r) | |
298 | return r; | |
299 | ||
300 | mode = 0x02; | |
301 | r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, | |
302 | MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1); | |
303 | if (r) | |
304 | return r; | |
305 | } | |
306 | ||
307 | return nfc_hci_send_event(hdev, MICROREAD_GATE_ID_MREAD_ISO_A, | |
308 | MICROREAD_EVT_MREAD_DISCOVERY_START_SOME, | |
309 | param, 2); | |
310 | } | |
311 | ||
312 | static int microread_dep_link_up(struct nfc_hci_dev *hdev, | |
313 | struct nfc_target *target, u8 comm_mode, | |
314 | u8 *gb, size_t gb_len) | |
315 | { | |
316 | struct sk_buff *rgb_skb = NULL; | |
317 | int r; | |
318 | ||
319 | r = nfc_hci_get_param(hdev, target->hci_reader_gate, | |
320 | MICROREAD_PAR_P2P_INITIATOR_GT, &rgb_skb); | |
321 | if (r < 0) | |
322 | return r; | |
323 | ||
324 | if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) { | |
325 | r = -EPROTO; | |
326 | goto exit; | |
327 | } | |
328 | ||
329 | r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data, | |
330 | rgb_skb->len); | |
331 | if (r == 0) | |
332 | r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode, | |
333 | NFC_RF_INITIATOR); | |
334 | exit: | |
335 | kfree_skb(rgb_skb); | |
336 | ||
337 | return r; | |
338 | } | |
339 | ||
340 | static int microread_dep_link_down(struct nfc_hci_dev *hdev) | |
341 | { | |
342 | return nfc_hci_send_event(hdev, MICROREAD_GATE_ID_P2P_INITIATOR, | |
343 | MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, 0); | |
344 | } | |
345 | ||
346 | static int microread_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, | |
347 | struct nfc_target *target) | |
348 | { | |
349 | switch (gate) { | |
350 | case MICROREAD_GATE_ID_P2P_INITIATOR: | |
351 | target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; | |
352 | break; | |
353 | default: | |
354 | return -EPROTO; | |
355 | } | |
356 | ||
357 | return 0; | |
358 | } | |
359 | ||
360 | static int microread_complete_target_discovered(struct nfc_hci_dev *hdev, | |
361 | u8 gate, | |
362 | struct nfc_target *target) | |
363 | { | |
364 | return 0; | |
365 | } | |
366 | ||
367 | #define MICROREAD_CB_TYPE_READER_ALL 1 | |
368 | ||
369 | static void microread_im_transceive_cb(void *context, struct sk_buff *skb, | |
370 | int err) | |
371 | { | |
372 | struct microread_info *info = context; | |
373 | ||
374 | switch (info->async_cb_type) { | |
375 | case MICROREAD_CB_TYPE_READER_ALL: | |
376 | if (err == 0) { | |
377 | if (skb->len == 0) { | |
378 | err = -EPROTO; | |
379 | kfree_skb(skb); | |
380 | info->async_cb(info->async_cb_context, NULL, | |
381 | -EPROTO); | |
382 | return; | |
383 | } | |
384 | ||
385 | if (skb->data[skb->len - 1] != 0) { | |
386 | err = nfc_hci_result_to_errno( | |
387 | skb->data[skb->len - 1]); | |
388 | kfree_skb(skb); | |
389 | info->async_cb(info->async_cb_context, NULL, | |
390 | err); | |
391 | return; | |
392 | } | |
393 | ||
394 | skb_trim(skb, skb->len - 1); /* RF Error ind. */ | |
395 | } | |
396 | info->async_cb(info->async_cb_context, skb, err); | |
397 | break; | |
398 | default: | |
399 | if (err == 0) | |
400 | kfree_skb(skb); | |
401 | break; | |
402 | } | |
403 | } | |
404 | ||
405 | /* | |
406 | * Returns: | |
407 | * <= 0: driver handled the data exchange | |
408 | * 1: driver doesn't especially handle, please do standard processing | |
409 | */ | |
410 | static int microread_im_transceive(struct nfc_hci_dev *hdev, | |
411 | struct nfc_target *target, | |
412 | struct sk_buff *skb, data_exchange_cb_t cb, | |
413 | void *cb_context) | |
414 | { | |
415 | struct microread_info *info = nfc_hci_get_clientdata(hdev); | |
416 | u8 control_bits; | |
417 | u16 crc; | |
418 | ||
419 | pr_info("data exchange to gate 0x%x\n", target->hci_reader_gate); | |
420 | ||
421 | if (target->hci_reader_gate == MICROREAD_GATE_ID_P2P_INITIATOR) { | |
422 | *skb_push(skb, 1) = 0; | |
423 | ||
424 | return nfc_hci_send_event(hdev, target->hci_reader_gate, | |
425 | MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_TO_RF, | |
426 | skb->data, skb->len); | |
427 | } | |
428 | ||
429 | switch (target->hci_reader_gate) { | |
430 | case MICROREAD_GATE_ID_MREAD_ISO_A: | |
431 | control_bits = 0xCB; | |
432 | break; | |
433 | case MICROREAD_GATE_ID_MREAD_ISO_A_3: | |
434 | control_bits = 0xCB; | |
435 | break; | |
436 | case MICROREAD_GATE_ID_MREAD_ISO_B: | |
437 | control_bits = 0xCB; | |
438 | break; | |
439 | case MICROREAD_GATE_ID_MREAD_NFC_T1: | |
440 | control_bits = 0x1B; | |
441 | ||
442 | crc = crc_ccitt(0xffff, skb->data, skb->len); | |
443 | crc = ~crc; | |
444 | *skb_put(skb, 1) = crc & 0xff; | |
445 | *skb_put(skb, 1) = crc >> 8; | |
446 | break; | |
447 | case MICROREAD_GATE_ID_MREAD_NFC_T3: | |
448 | control_bits = 0xDB; | |
449 | break; | |
450 | default: | |
451 | pr_info("Abort im_transceive to invalid gate 0x%x\n", | |
452 | target->hci_reader_gate); | |
453 | return 1; | |
454 | } | |
455 | ||
456 | *skb_push(skb, 1) = control_bits; | |
457 | ||
458 | info->async_cb_type = MICROREAD_CB_TYPE_READER_ALL; | |
459 | info->async_cb = cb; | |
460 | info->async_cb_context = cb_context; | |
461 | ||
462 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, | |
463 | MICROREAD_CMD_MREAD_EXCHANGE, | |
464 | skb->data, skb->len, | |
465 | microread_im_transceive_cb, info); | |
466 | } | |
467 | ||
468 | static int microread_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) | |
469 | { | |
470 | int r; | |
471 | ||
472 | r = nfc_hci_send_event(hdev, MICROREAD_GATE_ID_P2P_TARGET, | |
473 | MICROREAD_EVT_MCARD_EXCHANGE, | |
474 | skb->data, skb->len); | |
475 | ||
476 | kfree_skb(skb); | |
477 | ||
478 | return r; | |
479 | } | |
480 | ||
481 | static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate, | |
482 | struct sk_buff *skb) | |
483 | { | |
484 | struct nfc_target *targets; | |
485 | int r = 0; | |
486 | ||
487 | pr_info("target discovered to gate 0x%x\n", gate); | |
488 | ||
489 | targets = kzalloc(sizeof(struct nfc_target), GFP_KERNEL); | |
490 | if (targets == NULL) { | |
491 | r = -ENOMEM; | |
492 | goto exit; | |
493 | } | |
494 | ||
495 | targets->hci_reader_gate = gate; | |
496 | ||
497 | switch (gate) { | |
498 | case MICROREAD_GATE_ID_MREAD_ISO_A: | |
499 | targets->supported_protocols = | |
500 | nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A_SAK]); | |
501 | targets->sens_res = | |
502 | be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A_ATQA]); | |
503 | targets->sel_res = skb->data[MICROREAD_EMCF_A_SAK]; | |
cfad1ba8 | 504 | targets->nfcid1_len = skb->data[MICROREAD_EMCF_A_LEN]; |
d07f1e86 DC |
505 | if (targets->nfcid1_len > sizeof(targets->nfcid1)) { |
506 | r = -EINVAL; | |
507 | goto exit_free; | |
508 | } | |
509 | memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID], | |
510 | targets->nfcid1_len); | |
cfad1ba8 EL |
511 | break; |
512 | case MICROREAD_GATE_ID_MREAD_ISO_A_3: | |
513 | targets->supported_protocols = | |
514 | nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A3_SAK]); | |
515 | targets->sens_res = | |
516 | be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A3_ATQA]); | |
517 | targets->sel_res = skb->data[MICROREAD_EMCF_A3_SAK]; | |
cfad1ba8 | 518 | targets->nfcid1_len = skb->data[MICROREAD_EMCF_A3_LEN]; |
d07f1e86 DC |
519 | if (targets->nfcid1_len > sizeof(targets->nfcid1)) { |
520 | r = -EINVAL; | |
521 | goto exit_free; | |
522 | } | |
523 | memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID], | |
524 | targets->nfcid1_len); | |
cfad1ba8 EL |
525 | break; |
526 | case MICROREAD_GATE_ID_MREAD_ISO_B: | |
527 | targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK; | |
528 | memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_B_UID], 4); | |
529 | targets->nfcid1_len = 4; | |
530 | break; | |
531 | case MICROREAD_GATE_ID_MREAD_NFC_T1: | |
532 | targets->supported_protocols = NFC_PROTO_JEWEL_MASK; | |
533 | targets->sens_res = | |
534 | le16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_T1_ATQA]); | |
535 | memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_T1_UID], 4); | |
536 | targets->nfcid1_len = 4; | |
537 | break; | |
538 | case MICROREAD_GATE_ID_MREAD_NFC_T3: | |
539 | targets->supported_protocols = NFC_PROTO_FELICA_MASK; | |
540 | memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_T3_UID], 8); | |
541 | targets->nfcid1_len = 8; | |
542 | break; | |
543 | default: | |
544 | pr_info("discard target discovered to gate 0x%x\n", gate); | |
545 | goto exit_free; | |
546 | } | |
547 | ||
548 | r = nfc_targets_found(hdev->ndev, targets, 1); | |
549 | ||
550 | exit_free: | |
551 | kfree(targets); | |
552 | ||
553 | exit: | |
554 | kfree_skb(skb); | |
555 | ||
556 | if (r) | |
17936b43 | 557 | pr_err("Failed to handle discovered target err=%d\n", r); |
cfad1ba8 EL |
558 | } |
559 | ||
d6365c01 | 560 | static int microread_event_received(struct nfc_hci_dev *hdev, u8 pipe, |
cfad1ba8 EL |
561 | u8 event, struct sk_buff *skb) |
562 | { | |
563 | int r; | |
d6365c01 | 564 | u8 gate = hdev->pipes[pipe].gate; |
cfad1ba8 EL |
565 | u8 mode; |
566 | ||
567 | pr_info("Microread received event 0x%x to gate 0x%x\n", event, gate); | |
568 | ||
569 | switch (event) { | |
570 | case MICROREAD_EVT_MREAD_CARD_FOUND: | |
571 | microread_target_discovered(hdev, gate, skb); | |
572 | return 0; | |
573 | ||
574 | case MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_FROM_RF: | |
575 | if (skb->len < 1) { | |
576 | kfree_skb(skb); | |
577 | return -EPROTO; | |
578 | } | |
579 | ||
580 | if (skb->data[skb->len - 1]) { | |
581 | kfree_skb(skb); | |
582 | return -EIO; | |
583 | } | |
584 | ||
585 | skb_trim(skb, skb->len - 1); | |
586 | ||
587 | r = nfc_tm_data_received(hdev->ndev, skb); | |
588 | break; | |
589 | ||
590 | case MICROREAD_EVT_MCARD_FIELD_ON: | |
591 | case MICROREAD_EVT_MCARD_FIELD_OFF: | |
592 | kfree_skb(skb); | |
593 | return 0; | |
594 | ||
595 | case MICROREAD_EVT_P2P_TARGET_ACTIVATED: | |
596 | r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, | |
597 | NFC_COMM_PASSIVE, skb->data, | |
598 | skb->len); | |
599 | ||
600 | kfree_skb(skb); | |
601 | break; | |
602 | ||
603 | case MICROREAD_EVT_MCARD_EXCHANGE: | |
604 | if (skb->len < 1) { | |
605 | kfree_skb(skb); | |
606 | return -EPROTO; | |
607 | } | |
608 | ||
609 | if (skb->data[skb->len-1]) { | |
610 | kfree_skb(skb); | |
611 | return -EIO; | |
612 | } | |
613 | ||
614 | skb_trim(skb, skb->len - 1); | |
615 | ||
616 | r = nfc_tm_data_received(hdev->ndev, skb); | |
617 | break; | |
618 | ||
619 | case MICROREAD_EVT_P2P_TARGET_DEACTIVATED: | |
620 | kfree_skb(skb); | |
621 | ||
622 | mode = 0xff; | |
623 | r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, | |
624 | MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1); | |
625 | if (r) | |
626 | break; | |
627 | ||
628 | r = nfc_hci_send_event(hdev, gate, | |
629 | MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, | |
630 | 0); | |
631 | break; | |
632 | ||
633 | default: | |
634 | return 1; | |
635 | } | |
636 | ||
637 | return r; | |
638 | } | |
639 | ||
640 | static struct nfc_hci_ops microread_hci_ops = { | |
641 | .open = microread_open, | |
642 | .close = microread_close, | |
643 | .hci_ready = microread_hci_ready, | |
644 | .xmit = microread_xmit, | |
645 | .start_poll = microread_start_poll, | |
646 | .dep_link_up = microread_dep_link_up, | |
647 | .dep_link_down = microread_dep_link_down, | |
648 | .target_from_gate = microread_target_from_gate, | |
649 | .complete_target_discovered = microread_complete_target_discovered, | |
650 | .im_transceive = microread_im_transceive, | |
651 | .tm_send = microread_tm_send, | |
652 | .check_presence = NULL, | |
653 | .event_received = microread_event_received, | |
654 | }; | |
655 | ||
656 | int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | |
657 | int phy_headroom, int phy_tailroom, int phy_payload, | |
658 | struct nfc_hci_dev **hdev) | |
659 | { | |
660 | struct microread_info *info; | |
661 | unsigned long quirks = 0; | |
0b456c41 | 662 | u32 protocols; |
cfad1ba8 EL |
663 | struct nfc_hci_init_data init_data; |
664 | int r; | |
665 | ||
666 | info = kzalloc(sizeof(struct microread_info), GFP_KERNEL); | |
667 | if (!info) { | |
cfad1ba8 EL |
668 | r = -ENOMEM; |
669 | goto err_info_alloc; | |
670 | } | |
671 | ||
672 | info->phy_ops = phy_ops; | |
673 | info->phy_id = phy_id; | |
674 | ||
675 | init_data.gate_count = ARRAY_SIZE(microread_gates); | |
676 | memcpy(init_data.gates, microread_gates, sizeof(microread_gates)); | |
677 | ||
678 | strcpy(init_data.session_id, "MICROREA"); | |
679 | ||
680 | set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); | |
681 | ||
682 | protocols = NFC_PROTO_JEWEL_MASK | | |
683 | NFC_PROTO_MIFARE_MASK | | |
684 | NFC_PROTO_FELICA_MASK | | |
685 | NFC_PROTO_ISO14443_MASK | | |
686 | NFC_PROTO_ISO14443_B_MASK | | |
687 | NFC_PROTO_NFC_DEP_MASK; | |
688 | ||
cfad1ba8 | 689 | info->hdev = nfc_hci_allocate_device(µread_hci_ops, &init_data, |
0b456c41 | 690 | quirks, protocols, llc_name, |
cfad1ba8 EL |
691 | phy_headroom + |
692 | MICROREAD_CMDS_HEADROOM, | |
693 | phy_tailroom + | |
694 | MICROREAD_CMD_TAILROOM, | |
695 | phy_payload); | |
696 | if (!info->hdev) { | |
17936b43 | 697 | pr_err("Cannot allocate nfc hdev\n"); |
cfad1ba8 EL |
698 | r = -ENOMEM; |
699 | goto err_alloc_hdev; | |
700 | } | |
701 | ||
702 | nfc_hci_set_clientdata(info->hdev, info); | |
703 | ||
704 | r = nfc_hci_register_device(info->hdev); | |
705 | if (r) | |
706 | goto err_regdev; | |
707 | ||
708 | *hdev = info->hdev; | |
709 | ||
710 | return 0; | |
711 | ||
712 | err_regdev: | |
713 | nfc_hci_free_device(info->hdev); | |
714 | ||
715 | err_alloc_hdev: | |
716 | kfree(info); | |
717 | ||
718 | err_info_alloc: | |
719 | return r; | |
720 | } | |
721 | EXPORT_SYMBOL(microread_probe); | |
722 | ||
723 | void microread_remove(struct nfc_hci_dev *hdev) | |
724 | { | |
725 | struct microread_info *info = nfc_hci_get_clientdata(hdev); | |
726 | ||
727 | nfc_hci_unregister_device(hdev); | |
728 | nfc_hci_free_device(hdev); | |
729 | kfree(info); | |
730 | } | |
731 | EXPORT_SYMBOL(microread_remove); | |
732 | ||
733 | MODULE_LICENSE("GPL"); | |
734 | MODULE_DESCRIPTION(DRIVER_DESC); |