]>
Commit | Line | Data |
---|---|---|
7d0911c0 TE |
1 | /* |
2 | * NFC Digital Protocol stack | |
3 | * Copyright (c) 2013, Intel Corporation. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms and conditions of the GNU General Public License, | |
7 | * version 2, as published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
14 | */ | |
15 | ||
c5da0e4a SO |
16 | #define pr_fmt(fmt) "digital: %s: " fmt, __func__ |
17 | ||
7d0911c0 TE |
18 | #include "digital.h" |
19 | ||
a80509c7 | 20 | #define DIGITAL_NFC_DEP_N_RETRY_NACK 2 |
384ab1d1 | 21 | #define DIGITAL_NFC_DEP_N_RETRY_ATN 2 |
a80509c7 | 22 | |
7d0911c0 TE |
23 | #define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4 |
24 | #define DIGITAL_NFC_DEP_FRAME_DIR_IN 0xD5 | |
25 | ||
26 | #define DIGITAL_NFC_DEP_NFCA_SOD_SB 0xF0 | |
27 | ||
28 | #define DIGITAL_CMD_ATR_REQ 0x00 | |
29 | #define DIGITAL_CMD_ATR_RES 0x01 | |
30 | #define DIGITAL_CMD_PSL_REQ 0x04 | |
31 | #define DIGITAL_CMD_PSL_RES 0x05 | |
32 | #define DIGITAL_CMD_DEP_REQ 0x06 | |
33 | #define DIGITAL_CMD_DEP_RES 0x07 | |
34 | ||
35 | #define DIGITAL_ATR_REQ_MIN_SIZE 16 | |
36 | #define DIGITAL_ATR_REQ_MAX_SIZE 64 | |
37 | ||
1a09c56f TE |
38 | #define DIGITAL_ATR_RES_TO_WT(s) ((s) & 0xF) |
39 | ||
05afedcb MG |
40 | #define DIGITAL_DID_MAX 14 |
41 | ||
b08147cb MG |
42 | #define DIGITAL_PAYLOAD_SIZE_MAX 254 |
43 | #define DIGITAL_PAYLOAD_BITS_TO_PP(s) (((s) & 0x3) << 4) | |
44 | #define DIGITAL_PAYLOAD_PP_TO_BITS(s) (((s) >> 4) & 0x3) | |
45 | #define DIGITAL_PAYLOAD_BITS_TO_FSL(s) ((s) & 0x3) | |
46 | #define DIGITAL_PAYLOAD_FSL_TO_BITS(s) ((s) & 0x3) | |
47 | ||
7d0911c0 TE |
48 | #define DIGITAL_GB_BIT 0x02 |
49 | ||
3bd2a5bc MG |
50 | #define DIGITAL_NFC_DEP_REQ_RES_HEADROOM 2 /* SoD: [SB (NFC-A)] + LEN */ |
51 | #define DIGITAL_NFC_DEP_REQ_RES_TAILROOM 2 /* EoD: 2-byte CRC */ | |
52 | ||
7d0911c0 TE |
53 | #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) |
54 | ||
55 | #define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10 | |
3bd2a5bc MG |
56 | #define DIGITAL_NFC_DEP_PFB_MI_BIT 0x10 |
57 | #define DIGITAL_NFC_DEP_PFB_NACK_BIT 0x10 | |
05afedcb | 58 | #define DIGITAL_NFC_DEP_PFB_DID_BIT 0x04 |
7d0911c0 TE |
59 | |
60 | #define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ | |
61 | ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT) | |
3bd2a5bc MG |
62 | #define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_MI_BIT) |
63 | #define DIGITAL_NFC_DEP_NACK_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_NACK_BIT) | |
7d0911c0 | 64 | #define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08) |
05afedcb | 65 | #define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT) |
7d0911c0 TE |
66 | #define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03) |
67 | ||
d85a301c TE |
68 | #define DIGITAL_NFC_DEP_RTOX_VALUE(data) ((data) & 0x3F) |
69 | #define DIGITAL_NFC_DEP_RTOX_MAX 59 | |
70 | ||
7d0911c0 TE |
71 | #define DIGITAL_NFC_DEP_PFB_I_PDU 0x00 |
72 | #define DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU 0x40 | |
73 | #define DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU 0x80 | |
74 | ||
75 | struct digital_atr_req { | |
76 | u8 dir; | |
77 | u8 cmd; | |
78 | u8 nfcid3[10]; | |
79 | u8 did; | |
80 | u8 bs; | |
81 | u8 br; | |
82 | u8 pp; | |
83 | u8 gb[0]; | |
84 | } __packed; | |
85 | ||
86 | struct digital_atr_res { | |
87 | u8 dir; | |
88 | u8 cmd; | |
89 | u8 nfcid3[10]; | |
90 | u8 did; | |
91 | u8 bs; | |
92 | u8 br; | |
93 | u8 to; | |
94 | u8 pp; | |
95 | u8 gb[0]; | |
96 | } __packed; | |
97 | ||
98 | struct digital_psl_req { | |
99 | u8 dir; | |
100 | u8 cmd; | |
101 | u8 did; | |
102 | u8 brs; | |
103 | u8 fsl; | |
104 | } __packed; | |
105 | ||
106 | struct digital_psl_res { | |
107 | u8 dir; | |
108 | u8 cmd; | |
109 | u8 did; | |
110 | } __packed; | |
111 | ||
112 | struct digital_dep_req_res { | |
113 | u8 dir; | |
114 | u8 cmd; | |
115 | u8 pfb; | |
116 | } __packed; | |
117 | ||
118 | static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, | |
119 | struct sk_buff *resp); | |
c12715ab MG |
120 | static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg, |
121 | struct sk_buff *resp); | |
7d0911c0 | 122 | |
b08147cb MG |
123 | static const u8 digital_payload_bits_map[4] = { |
124 | [0] = 64, | |
125 | [1] = 128, | |
126 | [2] = 192, | |
127 | [3] = 254 | |
128 | }; | |
129 | ||
1a09c56f TE |
130 | /* Response Waiting Time for ATR_RES PDU in ms |
131 | * | |
132 | * RWT(ATR_RES) = RWT(nfcdep,activation) + dRWT(nfcdep) + dT(nfcdep,initiator) | |
133 | * | |
134 | * with: | |
135 | * RWT(nfcdep,activation) = 4096 * 2^12 / f(c) s | |
136 | * dRWT(nfcdep) = 16 / f(c) s | |
137 | * dT(nfcdep,initiator) = 100 ms | |
138 | * f(c) = 13560000 Hz | |
139 | */ | |
140 | #define DIGITAL_ATR_RES_RWT 1337 | |
141 | ||
142 | /* Response Waiting Time for other DEP PDUs in ms | |
143 | * | |
144 | * max_rwt = rwt + dRWT(nfcdep) + dT(nfcdep,initiator) | |
145 | * | |
146 | * with: | |
147 | * rwt = (256 * 16 / f(c)) * 2^wt s | |
148 | * dRWT(nfcdep) = 16 / f(c) s | |
149 | * dT(nfcdep,initiator) = 100 ms | |
150 | * f(c) = 13560000 Hz | |
151 | * 0 <= wt <= 14 (given by the target by the TO field of ATR_RES response) | |
152 | */ | |
153 | #define DIGITAL_NFC_DEP_IN_MAX_WT 14 | |
154 | #define DIGITAL_NFC_DEP_TG_MAX_WT 8 | |
155 | static const u16 digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT + 1] = { | |
156 | 100, 101, 101, 102, 105, | |
157 | 110, 119, 139, 177, 255, | |
158 | 409, 719, 1337, 2575, 5049, | |
159 | }; | |
160 | ||
b08147cb MG |
161 | static u8 digital_payload_bits_to_size(u8 payload_bits) |
162 | { | |
163 | if (payload_bits >= ARRAY_SIZE(digital_payload_bits_map)) | |
164 | return 0; | |
165 | ||
166 | return digital_payload_bits_map[payload_bits]; | |
167 | } | |
168 | ||
169 | static u8 digital_payload_size_to_bits(u8 payload_size) | |
170 | { | |
171 | int i; | |
172 | ||
173 | for (i = 0; i < ARRAY_SIZE(digital_payload_bits_map); i++) | |
174 | if (digital_payload_bits_map[i] == payload_size) | |
175 | return i; | |
176 | ||
177 | return 0xff; | |
178 | } | |
179 | ||
7d0911c0 TE |
180 | static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev, |
181 | struct sk_buff *skb) | |
182 | { | |
183 | skb_push(skb, sizeof(u8)); | |
184 | ||
185 | skb->data[0] = skb->len; | |
186 | ||
187 | if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A) | |
188 | *skb_push(skb, sizeof(u8)) = DIGITAL_NFC_DEP_NFCA_SOD_SB; | |
189 | } | |
190 | ||
191 | static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev, | |
192 | struct sk_buff *skb) | |
193 | { | |
194 | u8 size; | |
195 | ||
196 | if (skb->len < 2) | |
197 | return -EIO; | |
198 | ||
199 | if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A) | |
200 | skb_pull(skb, sizeof(u8)); | |
201 | ||
202 | size = skb->data[0]; | |
203 | if (size != skb->len) | |
204 | return -EIO; | |
205 | ||
206 | skb_pull(skb, sizeof(u8)); | |
207 | ||
208 | return 0; | |
209 | } | |
210 | ||
3bd2a5bc MG |
211 | static struct sk_buff * |
212 | digital_send_dep_data_prep(struct nfc_digital_dev *ddev, struct sk_buff *skb, | |
213 | struct digital_dep_req_res *dep_req_res, | |
214 | struct digital_data_exch *data_exch) | |
215 | { | |
216 | struct sk_buff *new_skb; | |
217 | ||
218 | if (skb->len > ddev->remote_payload_max) { | |
219 | dep_req_res->pfb |= DIGITAL_NFC_DEP_PFB_MI_BIT; | |
220 | ||
221 | new_skb = digital_skb_alloc(ddev, ddev->remote_payload_max); | |
222 | if (!new_skb) { | |
223 | kfree_skb(ddev->chaining_skb); | |
224 | ddev->chaining_skb = NULL; | |
225 | ||
226 | return ERR_PTR(-ENOMEM); | |
227 | } | |
228 | ||
59ae1d12 | 229 | skb_put_data(new_skb, skb->data, ddev->remote_payload_max); |
3bd2a5bc MG |
230 | skb_pull(skb, ddev->remote_payload_max); |
231 | ||
232 | ddev->chaining_skb = skb; | |
233 | ddev->data_exch = data_exch; | |
234 | } else { | |
235 | ddev->chaining_skb = NULL; | |
236 | new_skb = skb; | |
237 | } | |
238 | ||
239 | return new_skb; | |
240 | } | |
241 | ||
c12715ab MG |
242 | static struct sk_buff * |
243 | digital_recv_dep_data_gather(struct nfc_digital_dev *ddev, u8 pfb, | |
244 | struct sk_buff *resp, | |
245 | int (*send_ack)(struct nfc_digital_dev *ddev, | |
246 | struct digital_data_exch | |
247 | *data_exch), | |
248 | struct digital_data_exch *data_exch) | |
249 | { | |
250 | struct sk_buff *new_skb; | |
251 | int rc; | |
252 | ||
253 | if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb) && (!ddev->chaining_skb)) { | |
254 | ddev->chaining_skb = | |
255 | nfc_alloc_recv_skb(8 * ddev->local_payload_max, | |
256 | GFP_KERNEL); | |
257 | if (!ddev->chaining_skb) { | |
258 | rc = -ENOMEM; | |
259 | goto error; | |
260 | } | |
261 | } | |
262 | ||
263 | if (ddev->chaining_skb) { | |
264 | if (resp->len > skb_tailroom(ddev->chaining_skb)) { | |
265 | new_skb = skb_copy_expand(ddev->chaining_skb, | |
266 | skb_headroom( | |
267 | ddev->chaining_skb), | |
268 | 8 * ddev->local_payload_max, | |
269 | GFP_KERNEL); | |
270 | if (!new_skb) { | |
271 | rc = -ENOMEM; | |
272 | goto error; | |
273 | } | |
274 | ||
275 | kfree_skb(ddev->chaining_skb); | |
276 | ddev->chaining_skb = new_skb; | |
277 | } | |
278 | ||
59ae1d12 | 279 | skb_put_data(ddev->chaining_skb, resp->data, resp->len); |
c12715ab MG |
280 | |
281 | kfree_skb(resp); | |
282 | resp = NULL; | |
283 | ||
284 | if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) { | |
285 | rc = send_ack(ddev, data_exch); | |
286 | if (rc) | |
287 | goto error; | |
288 | ||
289 | return NULL; | |
290 | } | |
291 | ||
292 | resp = ddev->chaining_skb; | |
293 | ddev->chaining_skb = NULL; | |
294 | } | |
295 | ||
296 | return resp; | |
297 | ||
298 | error: | |
299 | kfree_skb(resp); | |
300 | ||
301 | kfree_skb(ddev->chaining_skb); | |
302 | ddev->chaining_skb = NULL; | |
303 | ||
304 | return ERR_PTR(rc); | |
305 | } | |
306 | ||
dddb3da0 MG |
307 | static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg, |
308 | struct sk_buff *resp) | |
309 | { | |
310 | struct nfc_target *target = arg; | |
311 | struct digital_psl_res *psl_res; | |
312 | int rc; | |
313 | ||
314 | if (IS_ERR(resp)) { | |
315 | rc = PTR_ERR(resp); | |
316 | resp = NULL; | |
317 | goto exit; | |
318 | } | |
319 | ||
320 | rc = ddev->skb_check_crc(resp); | |
321 | if (rc) { | |
322 | PROTOCOL_ERR("14.4.1.6"); | |
323 | goto exit; | |
324 | } | |
325 | ||
326 | rc = digital_skb_pull_dep_sod(ddev, resp); | |
327 | if (rc) { | |
328 | PROTOCOL_ERR("14.4.1.2"); | |
329 | goto exit; | |
330 | } | |
331 | ||
332 | psl_res = (struct digital_psl_res *)resp->data; | |
333 | ||
334 | if ((resp->len != sizeof(*psl_res)) || | |
335 | (psl_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN) || | |
336 | (psl_res->cmd != DIGITAL_CMD_PSL_RES)) { | |
337 | rc = -EIO; | |
338 | goto exit; | |
339 | } | |
340 | ||
341 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, | |
342 | NFC_DIGITAL_RF_TECH_424F); | |
343 | if (rc) | |
344 | goto exit; | |
345 | ||
346 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | |
347 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP); | |
348 | if (rc) | |
349 | goto exit; | |
350 | ||
351 | if (!DIGITAL_DRV_CAPS_IN_CRC(ddev) && | |
352 | (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)) { | |
353 | ddev->skb_add_crc = digital_skb_add_crc_f; | |
354 | ddev->skb_check_crc = digital_skb_check_crc_f; | |
355 | } | |
356 | ||
357 | ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_424F; | |
358 | ||
359 | nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE, | |
360 | NFC_RF_INITIATOR); | |
361 | ||
362 | ddev->curr_nfc_dep_pni = 0; | |
363 | ||
364 | exit: | |
365 | dev_kfree_skb(resp); | |
366 | ||
367 | if (rc) | |
368 | ddev->curr_protocol = 0; | |
369 | } | |
370 | ||
371 | static int digital_in_send_psl_req(struct nfc_digital_dev *ddev, | |
372 | struct nfc_target *target) | |
373 | { | |
374 | struct sk_buff *skb; | |
375 | struct digital_psl_req *psl_req; | |
b15829ba | 376 | int rc; |
b08147cb | 377 | u8 payload_size, payload_bits; |
dddb3da0 MG |
378 | |
379 | skb = digital_skb_alloc(ddev, sizeof(*psl_req)); | |
380 | if (!skb) | |
381 | return -ENOMEM; | |
382 | ||
383 | skb_put(skb, sizeof(*psl_req)); | |
384 | ||
385 | psl_req = (struct digital_psl_req *)skb->data; | |
386 | ||
387 | psl_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | |
388 | psl_req->cmd = DIGITAL_CMD_PSL_REQ; | |
389 | psl_req->did = 0; | |
390 | psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */ | |
b08147cb MG |
391 | |
392 | payload_size = min(ddev->local_payload_max, ddev->remote_payload_max); | |
393 | payload_bits = digital_payload_size_to_bits(payload_size); | |
394 | psl_req->fsl = DIGITAL_PAYLOAD_BITS_TO_FSL(payload_bits); | |
395 | ||
396 | ddev->local_payload_max = payload_size; | |
397 | ddev->remote_payload_max = payload_size; | |
dddb3da0 MG |
398 | |
399 | digital_skb_push_dep_sod(ddev, skb); | |
400 | ||
401 | ddev->skb_add_crc(skb); | |
402 | ||
1a09c56f TE |
403 | rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt, |
404 | digital_in_recv_psl_res, target); | |
b15829ba MG |
405 | if (rc) |
406 | kfree_skb(skb); | |
407 | ||
408 | return rc; | |
dddb3da0 MG |
409 | } |
410 | ||
7d0911c0 TE |
411 | static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg, |
412 | struct sk_buff *resp) | |
413 | { | |
414 | struct nfc_target *target = arg; | |
415 | struct digital_atr_res *atr_res; | |
b08147cb | 416 | u8 gb_len, payload_bits; |
1a09c56f | 417 | u8 wt; |
7d0911c0 TE |
418 | int rc; |
419 | ||
420 | if (IS_ERR(resp)) { | |
421 | rc = PTR_ERR(resp); | |
422 | resp = NULL; | |
423 | goto exit; | |
424 | } | |
425 | ||
426 | rc = ddev->skb_check_crc(resp); | |
427 | if (rc) { | |
428 | PROTOCOL_ERR("14.4.1.6"); | |
429 | goto exit; | |
430 | } | |
431 | ||
432 | rc = digital_skb_pull_dep_sod(ddev, resp); | |
433 | if (rc) { | |
434 | PROTOCOL_ERR("14.4.1.2"); | |
435 | goto exit; | |
436 | } | |
437 | ||
438 | if (resp->len < sizeof(struct digital_atr_res)) { | |
439 | rc = -EIO; | |
440 | goto exit; | |
441 | } | |
442 | ||
443 | gb_len = resp->len - sizeof(struct digital_atr_res); | |
444 | ||
445 | atr_res = (struct digital_atr_res *)resp->data; | |
446 | ||
1a09c56f TE |
447 | wt = DIGITAL_ATR_RES_TO_WT(atr_res->to); |
448 | if (wt > DIGITAL_NFC_DEP_IN_MAX_WT) | |
449 | wt = DIGITAL_NFC_DEP_IN_MAX_WT; | |
450 | ddev->dep_rwt = digital_rwt_map[wt]; | |
451 | ||
b08147cb MG |
452 | payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_res->pp); |
453 | ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits); | |
454 | ||
455 | if (!ddev->remote_payload_max) { | |
456 | rc = -EINVAL; | |
457 | goto exit; | |
458 | } | |
459 | ||
7d0911c0 TE |
460 | rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len); |
461 | if (rc) | |
462 | goto exit; | |
463 | ||
dddb3da0 MG |
464 | if ((ddev->protocols & NFC_PROTO_FELICA_MASK) && |
465 | (ddev->curr_rf_tech != NFC_DIGITAL_RF_TECH_424F)) { | |
466 | rc = digital_in_send_psl_req(ddev, target); | |
467 | if (!rc) | |
468 | goto exit; | |
469 | } | |
470 | ||
7d0911c0 TE |
471 | rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE, |
472 | NFC_RF_INITIATOR); | |
473 | ||
474 | ddev->curr_nfc_dep_pni = 0; | |
475 | ||
476 | exit: | |
477 | dev_kfree_skb(resp); | |
478 | ||
479 | if (rc) | |
480 | ddev->curr_protocol = 0; | |
481 | } | |
482 | ||
483 | int digital_in_send_atr_req(struct nfc_digital_dev *ddev, | |
484 | struct nfc_target *target, __u8 comm_mode, __u8 *gb, | |
485 | size_t gb_len) | |
486 | { | |
487 | struct sk_buff *skb; | |
488 | struct digital_atr_req *atr_req; | |
489 | uint size; | |
b15829ba | 490 | int rc; |
b08147cb | 491 | u8 payload_bits; |
7d0911c0 TE |
492 | |
493 | size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len; | |
494 | ||
495 | if (size > DIGITAL_ATR_REQ_MAX_SIZE) { | |
496 | PROTOCOL_ERR("14.6.1.1"); | |
497 | return -EINVAL; | |
498 | } | |
499 | ||
500 | skb = digital_skb_alloc(ddev, size); | |
501 | if (!skb) | |
502 | return -ENOMEM; | |
503 | ||
504 | skb_put(skb, sizeof(struct digital_atr_req)); | |
505 | ||
506 | atr_req = (struct digital_atr_req *)skb->data; | |
507 | memset(atr_req, 0, sizeof(struct digital_atr_req)); | |
508 | ||
509 | atr_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | |
510 | atr_req->cmd = DIGITAL_CMD_ATR_REQ; | |
511 | if (target->nfcid2_len) | |
4f319e32 | 512 | memcpy(atr_req->nfcid3, target->nfcid2, NFC_NFCID2_MAXSIZE); |
7d0911c0 | 513 | else |
4f319e32 | 514 | get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE); |
7d0911c0 TE |
515 | |
516 | atr_req->did = 0; | |
517 | atr_req->bs = 0; | |
518 | atr_req->br = 0; | |
519 | ||
b08147cb MG |
520 | ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX; |
521 | payload_bits = digital_payload_size_to_bits(ddev->local_payload_max); | |
522 | atr_req->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits); | |
7d0911c0 TE |
523 | |
524 | if (gb_len) { | |
525 | atr_req->pp |= DIGITAL_GB_BIT; | |
59ae1d12 | 526 | skb_put_data(skb, gb, gb_len); |
7d0911c0 TE |
527 | } |
528 | ||
529 | digital_skb_push_dep_sod(ddev, skb); | |
530 | ||
531 | ddev->skb_add_crc(skb); | |
532 | ||
1a09c56f TE |
533 | rc = digital_in_send_cmd(ddev, skb, DIGITAL_ATR_RES_RWT, |
534 | digital_in_recv_atr_res, target); | |
b15829ba MG |
535 | if (rc) |
536 | kfree_skb(skb); | |
537 | ||
538 | return rc; | |
7d0911c0 TE |
539 | } |
540 | ||
c12715ab MG |
541 | static int digital_in_send_ack(struct nfc_digital_dev *ddev, |
542 | struct digital_data_exch *data_exch) | |
543 | { | |
544 | struct digital_dep_req_res *dep_req; | |
545 | struct sk_buff *skb; | |
546 | int rc; | |
547 | ||
548 | skb = digital_skb_alloc(ddev, 1); | |
549 | if (!skb) | |
550 | return -ENOMEM; | |
551 | ||
552 | skb_push(skb, sizeof(struct digital_dep_req_res)); | |
553 | ||
554 | dep_req = (struct digital_dep_req_res *)skb->data; | |
555 | ||
556 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | |
557 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; | |
558 | dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU | | |
559 | ddev->curr_nfc_dep_pni; | |
560 | ||
561 | digital_skb_push_dep_sod(ddev, skb); | |
562 | ||
563 | ddev->skb_add_crc(skb); | |
564 | ||
1d984c2e | 565 | ddev->saved_skb = pskb_copy(skb, GFP_KERNEL); |
384ab1d1 | 566 | |
1a09c56f TE |
567 | rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt, |
568 | digital_in_recv_dep_res, data_exch); | |
384ab1d1 | 569 | if (rc) { |
c12715ab | 570 | kfree_skb(skb); |
384ab1d1 MG |
571 | kfree_skb(ddev->saved_skb); |
572 | ddev->saved_skb = NULL; | |
573 | } | |
c12715ab MG |
574 | |
575 | return rc; | |
576 | } | |
577 | ||
a80509c7 MG |
578 | static int digital_in_send_nack(struct nfc_digital_dev *ddev, |
579 | struct digital_data_exch *data_exch) | |
580 | { | |
581 | struct digital_dep_req_res *dep_req; | |
582 | struct sk_buff *skb; | |
583 | int rc; | |
584 | ||
585 | skb = digital_skb_alloc(ddev, 1); | |
586 | if (!skb) | |
587 | return -ENOMEM; | |
588 | ||
589 | skb_push(skb, sizeof(struct digital_dep_req_res)); | |
590 | ||
591 | dep_req = (struct digital_dep_req_res *)skb->data; | |
592 | ||
593 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | |
594 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; | |
595 | dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU | | |
596 | DIGITAL_NFC_DEP_PFB_NACK_BIT | ddev->curr_nfc_dep_pni; | |
597 | ||
598 | digital_skb_push_dep_sod(ddev, skb); | |
599 | ||
600 | ddev->skb_add_crc(skb); | |
601 | ||
1a09c56f TE |
602 | rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt, |
603 | digital_in_recv_dep_res, data_exch); | |
a80509c7 MG |
604 | if (rc) |
605 | kfree_skb(skb); | |
606 | ||
607 | return rc; | |
608 | } | |
609 | ||
384ab1d1 MG |
610 | static int digital_in_send_atn(struct nfc_digital_dev *ddev, |
611 | struct digital_data_exch *data_exch) | |
612 | { | |
613 | struct digital_dep_req_res *dep_req; | |
614 | struct sk_buff *skb; | |
615 | int rc; | |
616 | ||
617 | skb = digital_skb_alloc(ddev, 1); | |
618 | if (!skb) | |
619 | return -ENOMEM; | |
620 | ||
621 | skb_push(skb, sizeof(struct digital_dep_req_res)); | |
622 | ||
623 | dep_req = (struct digital_dep_req_res *)skb->data; | |
624 | ||
625 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | |
626 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; | |
627 | dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU; | |
628 | ||
629 | digital_skb_push_dep_sod(ddev, skb); | |
630 | ||
631 | ddev->skb_add_crc(skb); | |
632 | ||
1a09c56f TE |
633 | rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt, |
634 | digital_in_recv_dep_res, data_exch); | |
384ab1d1 MG |
635 | if (rc) |
636 | kfree_skb(skb); | |
637 | ||
638 | return rc; | |
639 | } | |
640 | ||
7d0911c0 TE |
641 | static int digital_in_send_rtox(struct nfc_digital_dev *ddev, |
642 | struct digital_data_exch *data_exch, u8 rtox) | |
643 | { | |
644 | struct digital_dep_req_res *dep_req; | |
645 | struct sk_buff *skb; | |
646 | int rc; | |
d85a301c TE |
647 | u16 rwt_int; |
648 | ||
649 | rwt_int = ddev->dep_rwt * rtox; | |
650 | if (rwt_int > digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT]) | |
651 | rwt_int = digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT]; | |
7d0911c0 TE |
652 | |
653 | skb = digital_skb_alloc(ddev, 1); | |
654 | if (!skb) | |
655 | return -ENOMEM; | |
656 | ||
657 | *skb_put(skb, 1) = rtox; | |
658 | ||
659 | skb_push(skb, sizeof(struct digital_dep_req_res)); | |
660 | ||
661 | dep_req = (struct digital_dep_req_res *)skb->data; | |
662 | ||
663 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | |
664 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; | |
665 | dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU | | |
666 | DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT; | |
667 | ||
668 | digital_skb_push_dep_sod(ddev, skb); | |
669 | ||
670 | ddev->skb_add_crc(skb); | |
671 | ||
d85a301c | 672 | rc = digital_in_send_cmd(ddev, skb, rwt_int, |
1a09c56f | 673 | digital_in_recv_dep_res, data_exch); |
1d984c2e | 674 | if (rc) |
b15829ba | 675 | kfree_skb(skb); |
7d0911c0 TE |
676 | |
677 | return rc; | |
678 | } | |
679 | ||
384ab1d1 MG |
680 | static int digital_in_send_saved_skb(struct nfc_digital_dev *ddev, |
681 | struct digital_data_exch *data_exch) | |
682 | { | |
1d984c2e TE |
683 | int rc; |
684 | ||
685 | if (!ddev->saved_skb) | |
686 | return -EINVAL; | |
687 | ||
384ab1d1 | 688 | skb_get(ddev->saved_skb); |
384ab1d1 | 689 | |
1a09c56f | 690 | rc = digital_in_send_cmd(ddev, ddev->saved_skb, ddev->dep_rwt, |
1d984c2e TE |
691 | digital_in_recv_dep_res, data_exch); |
692 | if (rc) | |
693 | kfree_skb(ddev->saved_skb); | |
694 | ||
695 | return rc; | |
384ab1d1 MG |
696 | } |
697 | ||
7d0911c0 TE |
698 | static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, |
699 | struct sk_buff *resp) | |
700 | { | |
701 | struct digital_data_exch *data_exch = arg; | |
702 | struct digital_dep_req_res *dep_res; | |
703 | u8 pfb; | |
704 | uint size; | |
705 | int rc; | |
d85a301c | 706 | u8 rtox; |
7d0911c0 TE |
707 | |
708 | if (IS_ERR(resp)) { | |
709 | rc = PTR_ERR(resp); | |
710 | resp = NULL; | |
a80509c7 | 711 | |
3f89fea3 | 712 | if ((rc == -EIO || (rc == -ETIMEDOUT && ddev->nack_count)) && |
a80509c7 | 713 | (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) { |
384ab1d1 MG |
714 | ddev->atn_count = 0; |
715 | ||
a80509c7 MG |
716 | rc = digital_in_send_nack(ddev, data_exch); |
717 | if (rc) | |
718 | goto error; | |
719 | ||
384ab1d1 MG |
720 | return; |
721 | } else if ((rc == -ETIMEDOUT) && | |
722 | (ddev->atn_count++ < DIGITAL_NFC_DEP_N_RETRY_ATN)) { | |
723 | ddev->nack_count = 0; | |
724 | ||
725 | rc = digital_in_send_atn(ddev, data_exch); | |
726 | if (rc) | |
727 | goto error; | |
728 | ||
a80509c7 MG |
729 | return; |
730 | } | |
731 | ||
732 | goto exit; | |
733 | } | |
734 | ||
735 | rc = digital_skb_pull_dep_sod(ddev, resp); | |
736 | if (rc) { | |
737 | PROTOCOL_ERR("14.4.1.2"); | |
7d0911c0 TE |
738 | goto exit; |
739 | } | |
740 | ||
741 | rc = ddev->skb_check_crc(resp); | |
742 | if (rc) { | |
a80509c7 MG |
743 | if ((resp->len >= 4) && |
744 | (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) { | |
384ab1d1 MG |
745 | ddev->atn_count = 0; |
746 | ||
a80509c7 MG |
747 | rc = digital_in_send_nack(ddev, data_exch); |
748 | if (rc) | |
749 | goto error; | |
750 | ||
751 | kfree_skb(resp); | |
752 | ||
753 | return; | |
754 | } | |
755 | ||
7d0911c0 TE |
756 | PROTOCOL_ERR("14.4.1.6"); |
757 | goto error; | |
758 | } | |
759 | ||
384ab1d1 | 760 | ddev->atn_count = 0; |
a80509c7 | 761 | ddev->nack_count = 0; |
7d0911c0 | 762 | |
b08147cb MG |
763 | if (resp->len > ddev->local_payload_max) { |
764 | rc = -EMSGSIZE; | |
765 | goto exit; | |
766 | } | |
767 | ||
6ce30668 | 768 | size = sizeof(struct digital_dep_req_res); |
7d0911c0 TE |
769 | dep_res = (struct digital_dep_req_res *)resp->data; |
770 | ||
6ce30668 | 771 | if (resp->len < size || dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN || |
7d0911c0 TE |
772 | dep_res->cmd != DIGITAL_CMD_DEP_RES) { |
773 | rc = -EIO; | |
774 | goto error; | |
775 | } | |
776 | ||
777 | pfb = dep_res->pfb; | |
778 | ||
3bc3f88a MG |
779 | if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) { |
780 | PROTOCOL_ERR("14.8.2.1"); | |
781 | rc = -EIO; | |
782 | goto error; | |
783 | } | |
6ce30668 | 784 | |
3e6b0de8 MG |
785 | if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) { |
786 | rc = -EIO; | |
787 | goto exit; | |
788 | } | |
789 | ||
6ce30668 MG |
790 | if (size > resp->len) { |
791 | rc = -EIO; | |
792 | goto error; | |
793 | } | |
794 | ||
795 | skb_pull(resp, size); | |
796 | ||
7d0911c0 TE |
797 | switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) { |
798 | case DIGITAL_NFC_DEP_PFB_I_PDU: | |
799 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) { | |
800 | PROTOCOL_ERR("14.12.3.3"); | |
801 | rc = -EIO; | |
802 | goto error; | |
803 | } | |
804 | ||
805 | ddev->curr_nfc_dep_pni = | |
806 | DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); | |
c12715ab | 807 | |
384ab1d1 MG |
808 | kfree_skb(ddev->saved_skb); |
809 | ddev->saved_skb = NULL; | |
810 | ||
c12715ab MG |
811 | resp = digital_recv_dep_data_gather(ddev, pfb, resp, |
812 | digital_in_send_ack, | |
813 | data_exch); | |
814 | if (IS_ERR(resp)) { | |
815 | rc = PTR_ERR(resp); | |
816 | resp = NULL; | |
817 | goto error; | |
818 | } | |
819 | ||
820 | /* If resp is NULL then we're still chaining so return and | |
821 | * wait for the next part of the PDU. Else, the PDU is | |
822 | * complete so pass it up. | |
823 | */ | |
824 | if (!resp) | |
825 | return; | |
826 | ||
7d0911c0 TE |
827 | rc = 0; |
828 | break; | |
829 | ||
830 | case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: | |
e073eb67 TE |
831 | if (DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) { |
832 | PROTOCOL_ERR("14.12.4.5"); | |
833 | rc = -EIO; | |
834 | goto exit; | |
835 | } | |
836 | ||
485fdc9b MG |
837 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) { |
838 | PROTOCOL_ERR("14.12.3.3"); | |
839 | rc = -EIO; | |
840 | goto exit; | |
841 | } | |
842 | ||
843 | ddev->curr_nfc_dep_pni = | |
844 | DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); | |
845 | ||
e073eb67 TE |
846 | if (!ddev->chaining_skb) { |
847 | PROTOCOL_ERR("14.12.4.3"); | |
848 | rc = -EIO; | |
849 | goto exit; | |
850 | } | |
384ab1d1 | 851 | |
e073eb67 TE |
852 | /* The initiator has received a valid ACK. Free the last sent |
853 | * PDU and keep on sending chained skb. | |
854 | */ | |
855 | kfree_skb(ddev->saved_skb); | |
856 | ddev->saved_skb = NULL; | |
3bd2a5bc | 857 | |
e073eb67 TE |
858 | rc = digital_in_send_dep_req(ddev, NULL, |
859 | ddev->chaining_skb, | |
860 | ddev->data_exch); | |
861 | if (rc) | |
862 | goto error; | |
3bd2a5bc | 863 | |
e073eb67 | 864 | goto free_resp; |
7d0911c0 TE |
865 | |
866 | case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: | |
384ab1d1 MG |
867 | if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { /* ATN */ |
868 | rc = digital_in_send_saved_skb(ddev, data_exch); | |
1d984c2e | 869 | if (rc) |
384ab1d1 | 870 | goto error; |
384ab1d1 | 871 | |
e200f008 | 872 | goto free_resp; |
7d0911c0 TE |
873 | } |
874 | ||
d85a301c TE |
875 | if (ddev->atn_count || ddev->nack_count) { |
876 | PROTOCOL_ERR("14.12.4.4"); | |
877 | rc = -EIO; | |
878 | goto error; | |
879 | } | |
880 | ||
881 | rtox = DIGITAL_NFC_DEP_RTOX_VALUE(resp->data[0]); | |
882 | if (!rtox || rtox > DIGITAL_NFC_DEP_RTOX_MAX) { | |
883 | PROTOCOL_ERR("14.8.4.1"); | |
884 | rc = -EIO; | |
885 | goto error; | |
886 | } | |
887 | ||
888 | rc = digital_in_send_rtox(ddev, data_exch, rtox); | |
7d0911c0 TE |
889 | if (rc) |
890 | goto error; | |
891 | ||
e200f008 | 892 | goto free_resp; |
7d0911c0 TE |
893 | } |
894 | ||
7d0911c0 TE |
895 | exit: |
896 | data_exch->cb(data_exch->cb_context, resp, rc); | |
897 | ||
898 | error: | |
899 | kfree(data_exch); | |
900 | ||
3bd2a5bc MG |
901 | kfree_skb(ddev->chaining_skb); |
902 | ddev->chaining_skb = NULL; | |
903 | ||
384ab1d1 MG |
904 | kfree_skb(ddev->saved_skb); |
905 | ddev->saved_skb = NULL; | |
906 | ||
7d0911c0 TE |
907 | if (rc) |
908 | kfree_skb(resp); | |
e073eb67 TE |
909 | |
910 | return; | |
911 | ||
912 | free_resp: | |
913 | dev_kfree_skb(resp); | |
7d0911c0 TE |
914 | } |
915 | ||
916 | int digital_in_send_dep_req(struct nfc_digital_dev *ddev, | |
917 | struct nfc_target *target, struct sk_buff *skb, | |
918 | struct digital_data_exch *data_exch) | |
919 | { | |
920 | struct digital_dep_req_res *dep_req; | |
3bd2a5bc MG |
921 | struct sk_buff *chaining_skb, *tmp_skb; |
922 | int rc; | |
7d0911c0 TE |
923 | |
924 | skb_push(skb, sizeof(struct digital_dep_req_res)); | |
925 | ||
926 | dep_req = (struct digital_dep_req_res *)skb->data; | |
3bd2a5bc | 927 | |
7d0911c0 TE |
928 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; |
929 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; | |
930 | dep_req->pfb = ddev->curr_nfc_dep_pni; | |
931 | ||
384ab1d1 | 932 | ddev->atn_count = 0; |
a80509c7 MG |
933 | ddev->nack_count = 0; |
934 | ||
3bd2a5bc | 935 | chaining_skb = ddev->chaining_skb; |
7d0911c0 | 936 | |
3bd2a5bc MG |
937 | tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_req, data_exch); |
938 | if (IS_ERR(tmp_skb)) | |
939 | return PTR_ERR(tmp_skb); | |
7d0911c0 | 940 | |
3bd2a5bc MG |
941 | digital_skb_push_dep_sod(ddev, tmp_skb); |
942 | ||
943 | ddev->skb_add_crc(tmp_skb); | |
944 | ||
1d984c2e | 945 | ddev->saved_skb = pskb_copy(tmp_skb, GFP_KERNEL); |
384ab1d1 | 946 | |
1a09c56f TE |
947 | rc = digital_in_send_cmd(ddev, tmp_skb, ddev->dep_rwt, |
948 | digital_in_recv_dep_res, data_exch); | |
3bd2a5bc MG |
949 | if (rc) { |
950 | if (tmp_skb != skb) | |
951 | kfree_skb(tmp_skb); | |
952 | ||
953 | kfree_skb(chaining_skb); | |
954 | ddev->chaining_skb = NULL; | |
384ab1d1 MG |
955 | |
956 | kfree_skb(ddev->saved_skb); | |
957 | ddev->saved_skb = NULL; | |
3bd2a5bc MG |
958 | } |
959 | ||
960 | return rc; | |
7d0911c0 | 961 | } |
1c7a4c24 | 962 | |
b711ad52 TE |
963 | static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech) |
964 | { | |
965 | ddev->curr_rf_tech = rf_tech; | |
966 | ||
967 | ddev->skb_add_crc = digital_skb_add_crc_none; | |
968 | ddev->skb_check_crc = digital_skb_check_crc_none; | |
969 | ||
970 | if (DIGITAL_DRV_CAPS_TG_CRC(ddev)) | |
971 | return; | |
972 | ||
973 | switch (ddev->curr_rf_tech) { | |
974 | case NFC_DIGITAL_RF_TECH_106A: | |
975 | ddev->skb_add_crc = digital_skb_add_crc_a; | |
976 | ddev->skb_check_crc = digital_skb_check_crc_a; | |
977 | break; | |
978 | ||
979 | case NFC_DIGITAL_RF_TECH_212F: | |
980 | case NFC_DIGITAL_RF_TECH_424F: | |
981 | ddev->skb_add_crc = digital_skb_add_crc_f; | |
982 | ddev->skb_check_crc = digital_skb_check_crc_f; | |
983 | break; | |
984 | ||
985 | default: | |
986 | break; | |
987 | } | |
988 | } | |
989 | ||
c12715ab MG |
990 | static int digital_tg_send_ack(struct nfc_digital_dev *ddev, |
991 | struct digital_data_exch *data_exch) | |
992 | { | |
993 | struct digital_dep_req_res *dep_res; | |
994 | struct sk_buff *skb; | |
995 | int rc; | |
996 | ||
997 | skb = digital_skb_alloc(ddev, 1); | |
998 | if (!skb) | |
999 | return -ENOMEM; | |
1000 | ||
1001 | skb_push(skb, sizeof(struct digital_dep_req_res)); | |
1002 | ||
1003 | dep_res = (struct digital_dep_req_res *)skb->data; | |
1004 | ||
1005 | dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | |
1006 | dep_res->cmd = DIGITAL_CMD_DEP_RES; | |
1007 | dep_res->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU | | |
1008 | ddev->curr_nfc_dep_pni; | |
1009 | ||
1010 | if (ddev->did) { | |
1011 | dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT; | |
1012 | ||
59ae1d12 | 1013 | skb_put_data(skb, &ddev->did, sizeof(ddev->did)); |
c12715ab MG |
1014 | } |
1015 | ||
1016 | ddev->curr_nfc_dep_pni = | |
1017 | DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); | |
1018 | ||
1019 | digital_skb_push_dep_sod(ddev, skb); | |
1020 | ||
1021 | ddev->skb_add_crc(skb); | |
1022 | ||
1d984c2e | 1023 | ddev->saved_skb = pskb_copy(skb, GFP_KERNEL); |
49dbb14e | 1024 | |
c12715ab MG |
1025 | rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req, |
1026 | data_exch); | |
49dbb14e | 1027 | if (rc) { |
c12715ab | 1028 | kfree_skb(skb); |
49dbb14e MG |
1029 | kfree_skb(ddev->saved_skb); |
1030 | ddev->saved_skb = NULL; | |
1031 | } | |
c12715ab MG |
1032 | |
1033 | return rc; | |
1034 | } | |
1035 | ||
9b5ec0fd MG |
1036 | static int digital_tg_send_atn(struct nfc_digital_dev *ddev) |
1037 | { | |
1038 | struct digital_dep_req_res *dep_res; | |
1039 | struct sk_buff *skb; | |
1040 | int rc; | |
1041 | ||
1042 | skb = digital_skb_alloc(ddev, 1); | |
1043 | if (!skb) | |
1044 | return -ENOMEM; | |
1045 | ||
1046 | skb_push(skb, sizeof(struct digital_dep_req_res)); | |
1047 | ||
1048 | dep_res = (struct digital_dep_req_res *)skb->data; | |
1049 | ||
1050 | dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | |
1051 | dep_res->cmd = DIGITAL_CMD_DEP_RES; | |
1052 | dep_res->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU; | |
1053 | ||
1054 | if (ddev->did) { | |
1055 | dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT; | |
1056 | ||
59ae1d12 | 1057 | skb_put_data(skb, &ddev->did, sizeof(ddev->did)); |
9b5ec0fd MG |
1058 | } |
1059 | ||
1060 | digital_skb_push_dep_sod(ddev, skb); | |
1061 | ||
1062 | ddev->skb_add_crc(skb); | |
1063 | ||
1064 | rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req, | |
1065 | NULL); | |
1066 | if (rc) | |
1067 | kfree_skb(skb); | |
1068 | ||
1069 | return rc; | |
1070 | } | |
1071 | ||
49dbb14e MG |
1072 | static int digital_tg_send_saved_skb(struct nfc_digital_dev *ddev) |
1073 | { | |
1d984c2e TE |
1074 | int rc; |
1075 | ||
1076 | if (!ddev->saved_skb) | |
1077 | return -EINVAL; | |
1078 | ||
49dbb14e | 1079 | skb_get(ddev->saved_skb); |
49dbb14e | 1080 | |
1d984c2e TE |
1081 | rc = digital_tg_send_cmd(ddev, ddev->saved_skb, 1500, |
1082 | digital_tg_recv_dep_req, NULL); | |
1083 | if (rc) | |
1084 | kfree_skb(ddev->saved_skb); | |
1085 | ||
1086 | return rc; | |
49dbb14e MG |
1087 | } |
1088 | ||
1c7a4c24 TE |
1089 | static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg, |
1090 | struct sk_buff *resp) | |
1091 | { | |
1092 | int rc; | |
1093 | struct digital_dep_req_res *dep_req; | |
6ce30668 | 1094 | u8 pfb; |
1c7a4c24 TE |
1095 | size_t size; |
1096 | ||
1097 | if (IS_ERR(resp)) { | |
1098 | rc = PTR_ERR(resp); | |
1099 | resp = NULL; | |
1100 | goto exit; | |
1101 | } | |
1102 | ||
1103 | rc = ddev->skb_check_crc(resp); | |
1104 | if (rc) { | |
1105 | PROTOCOL_ERR("14.4.1.6"); | |
1106 | goto exit; | |
1107 | } | |
1108 | ||
1109 | rc = digital_skb_pull_dep_sod(ddev, resp); | |
1110 | if (rc) { | |
1111 | PROTOCOL_ERR("14.4.1.2"); | |
1112 | goto exit; | |
1113 | } | |
1114 | ||
b08147cb MG |
1115 | if (resp->len > ddev->local_payload_max) { |
1116 | rc = -EMSGSIZE; | |
1117 | goto exit; | |
1118 | } | |
1119 | ||
1c7a4c24 TE |
1120 | size = sizeof(struct digital_dep_req_res); |
1121 | dep_req = (struct digital_dep_req_res *)resp->data; | |
1122 | ||
1123 | if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT || | |
1124 | dep_req->cmd != DIGITAL_CMD_DEP_REQ) { | |
1125 | rc = -EIO; | |
1126 | goto exit; | |
1127 | } | |
1128 | ||
6ce30668 MG |
1129 | pfb = dep_req->pfb; |
1130 | ||
05afedcb MG |
1131 | if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) { |
1132 | if (ddev->did && (ddev->did == resp->data[3])) { | |
1133 | size++; | |
1134 | } else { | |
1135 | rc = -EIO; | |
1136 | goto exit; | |
1137 | } | |
1138 | } else if (ddev->did) { | |
1139 | rc = -EIO; | |
1140 | goto exit; | |
1141 | } | |
1c7a4c24 | 1142 | |
3e6b0de8 MG |
1143 | if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) { |
1144 | rc = -EIO; | |
1145 | goto exit; | |
1146 | } | |
1147 | ||
6ce30668 | 1148 | if (size > resp->len) { |
1c7a4c24 TE |
1149 | rc = -EIO; |
1150 | goto exit; | |
1151 | } | |
1152 | ||
6ce30668 MG |
1153 | skb_pull(resp, size); |
1154 | ||
1155 | switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) { | |
1c7a4c24 | 1156 | case DIGITAL_NFC_DEP_PFB_I_PDU: |
26042530 | 1157 | pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n"); |
485fdc9b | 1158 | |
9b5ec0fd | 1159 | if (ddev->atn_count) { |
f23a9868 TE |
1160 | /* The target has received (and replied to) at least one |
1161 | * ATN DEP_REQ. | |
1162 | */ | |
9b5ec0fd MG |
1163 | ddev->atn_count = 0; |
1164 | ||
f23a9868 TE |
1165 | /* pni of resp PDU equal to the target current pni - 1 |
1166 | * means resp is the previous DEP_REQ PDU received from | |
1167 | * the initiator so the target replies with saved_skb | |
1168 | * which is the previous DEP_RES saved in | |
1169 | * digital_tg_send_dep_res(). | |
1170 | */ | |
1171 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb) == | |
1172 | DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni - 1)) { | |
1173 | rc = digital_tg_send_saved_skb(ddev); | |
1174 | if (rc) | |
1175 | goto exit; | |
9b5ec0fd | 1176 | |
f23a9868 TE |
1177 | goto free_resp; |
1178 | } | |
1179 | ||
1180 | /* atn_count > 0 and PDU pni != curr_nfc_dep_pni - 1 | |
1181 | * means the target probably did not received the last | |
1182 | * DEP_REQ PDU sent by the initiator. The target | |
1183 | * fallbacks to normal processing then. | |
1184 | */ | |
1185 | } | |
1186 | ||
1187 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) { | |
1188 | PROTOCOL_ERR("14.12.3.4"); | |
1189 | rc = -EIO; | |
1190 | goto exit; | |
9b5ec0fd MG |
1191 | } |
1192 | ||
49dbb14e MG |
1193 | kfree_skb(ddev->saved_skb); |
1194 | ddev->saved_skb = NULL; | |
1195 | ||
c12715ab MG |
1196 | resp = digital_recv_dep_data_gather(ddev, pfb, resp, |
1197 | digital_tg_send_ack, NULL); | |
1198 | if (IS_ERR(resp)) { | |
1199 | rc = PTR_ERR(resp); | |
1200 | resp = NULL; | |
1201 | goto exit; | |
1202 | } | |
1203 | ||
1204 | /* If resp is NULL then we're still chaining so return and | |
1205 | * wait for the next part of the PDU. Else, the PDU is | |
1206 | * complete so pass it up. | |
1207 | */ | |
1208 | if (!resp) | |
1209 | return; | |
1210 | ||
485fdc9b | 1211 | rc = 0; |
1c7a4c24 TE |
1212 | break; |
1213 | case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: | |
482333b2 TE |
1214 | if (DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) { /* NACK */ |
1215 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb + 1) != | |
1216 | ddev->curr_nfc_dep_pni) { | |
49dbb14e MG |
1217 | rc = -EIO; |
1218 | goto exit; | |
1219 | } | |
1220 | ||
482333b2 TE |
1221 | ddev->atn_count = 0; |
1222 | ||
1223 | rc = digital_tg_send_saved_skb(ddev); | |
1224 | if (rc) | |
1225 | goto exit; | |
1226 | ||
1227 | goto free_resp; | |
1228 | } | |
1229 | ||
1230 | /* ACK */ | |
1231 | if (ddev->atn_count) { | |
1232 | /* The target has previously recevied one or more ATN | |
1233 | * PDUs. | |
1234 | */ | |
1235 | ddev->atn_count = 0; | |
9b5ec0fd | 1236 | |
482333b2 TE |
1237 | /* If the ACK PNI is equal to the target PNI - 1 means |
1238 | * that the initiator did not receive the previous PDU | |
1239 | * sent by the target so re-send it. | |
1240 | */ | |
1241 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb + 1) == | |
1242 | ddev->curr_nfc_dep_pni) { | |
9b5ec0fd MG |
1243 | rc = digital_tg_send_saved_skb(ddev); |
1244 | if (rc) | |
1245 | goto exit; | |
1246 | ||
482333b2 | 1247 | goto free_resp; |
9b5ec0fd MG |
1248 | } |
1249 | ||
482333b2 TE |
1250 | /* Otherwise, the target did not receive the previous |
1251 | * ACK PDU from the initiator. Fallback to normal | |
1252 | * processing of chained PDU then. | |
1253 | */ | |
1254 | } | |
485fdc9b | 1255 | |
482333b2 TE |
1256 | /* Keep on sending chained PDU */ |
1257 | if (!ddev->chaining_skb || | |
1258 | DIGITAL_NFC_DEP_PFB_PNI(pfb) != | |
1259 | ddev->curr_nfc_dep_pni) { | |
1260 | rc = -EIO; | |
1261 | goto exit; | |
1262 | } | |
3bd2a5bc | 1263 | |
482333b2 TE |
1264 | kfree_skb(ddev->saved_skb); |
1265 | ddev->saved_skb = NULL; | |
9b5ec0fd | 1266 | |
482333b2 TE |
1267 | rc = digital_tg_send_dep_res(ddev, ddev->chaining_skb); |
1268 | if (rc) | |
1269 | goto exit; | |
3bd2a5bc | 1270 | |
482333b2 | 1271 | goto free_resp; |
1c7a4c24 | 1272 | case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: |
9b5ec0fd MG |
1273 | if (DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { |
1274 | rc = -EINVAL; | |
1275 | goto exit; | |
1276 | } | |
1277 | ||
1278 | rc = digital_tg_send_atn(ddev); | |
1279 | if (rc) | |
1280 | goto exit; | |
1281 | ||
1282 | ddev->atn_count++; | |
1283 | ||
e200f008 | 1284 | goto free_resp; |
1c7a4c24 TE |
1285 | } |
1286 | ||
1c7a4c24 TE |
1287 | rc = nfc_tm_data_received(ddev->nfc_dev, resp); |
1288 | ||
1289 | exit: | |
3bd2a5bc MG |
1290 | kfree_skb(ddev->chaining_skb); |
1291 | ddev->chaining_skb = NULL; | |
1292 | ||
9b5ec0fd MG |
1293 | ddev->atn_count = 0; |
1294 | ||
49dbb14e MG |
1295 | kfree_skb(ddev->saved_skb); |
1296 | ddev->saved_skb = NULL; | |
1297 | ||
1c7a4c24 TE |
1298 | if (rc) |
1299 | kfree_skb(resp); | |
f23a9868 TE |
1300 | |
1301 | return; | |
1302 | ||
1303 | free_resp: | |
1304 | dev_kfree_skb(resp); | |
1c7a4c24 TE |
1305 | } |
1306 | ||
1307 | int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb) | |
1308 | { | |
1309 | struct digital_dep_req_res *dep_res; | |
3bd2a5bc MG |
1310 | struct sk_buff *chaining_skb, *tmp_skb; |
1311 | int rc; | |
1c7a4c24 TE |
1312 | |
1313 | skb_push(skb, sizeof(struct digital_dep_req_res)); | |
b08147cb | 1314 | |
1c7a4c24 TE |
1315 | dep_res = (struct digital_dep_req_res *)skb->data; |
1316 | ||
1317 | dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | |
1318 | dep_res->cmd = DIGITAL_CMD_DEP_RES; | |
1319 | dep_res->pfb = ddev->curr_nfc_dep_pni; | |
1320 | ||
05afedcb MG |
1321 | if (ddev->did) { |
1322 | dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT; | |
1323 | ||
59ae1d12 | 1324 | skb_put_data(skb, &ddev->did, sizeof(ddev->did)); |
05afedcb MG |
1325 | } |
1326 | ||
485fdc9b MG |
1327 | ddev->curr_nfc_dep_pni = |
1328 | DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); | |
1329 | ||
3bd2a5bc | 1330 | chaining_skb = ddev->chaining_skb; |
1c7a4c24 | 1331 | |
3bd2a5bc MG |
1332 | tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_res, NULL); |
1333 | if (IS_ERR(tmp_skb)) | |
1334 | return PTR_ERR(tmp_skb); | |
1335 | ||
1336 | digital_skb_push_dep_sod(ddev, tmp_skb); | |
1337 | ||
1338 | ddev->skb_add_crc(tmp_skb); | |
1c7a4c24 | 1339 | |
1d984c2e | 1340 | ddev->saved_skb = pskb_copy(tmp_skb, GFP_KERNEL); |
49dbb14e | 1341 | |
3bd2a5bc MG |
1342 | rc = digital_tg_send_cmd(ddev, tmp_skb, 1500, digital_tg_recv_dep_req, |
1343 | NULL); | |
1344 | if (rc) { | |
1345 | if (tmp_skb != skb) | |
1346 | kfree_skb(tmp_skb); | |
1347 | ||
1348 | kfree_skb(chaining_skb); | |
1349 | ddev->chaining_skb = NULL; | |
49dbb14e MG |
1350 | |
1351 | kfree_skb(ddev->saved_skb); | |
1352 | ddev->saved_skb = NULL; | |
3bd2a5bc MG |
1353 | } |
1354 | ||
1355 | return rc; | |
1c7a4c24 TE |
1356 | } |
1357 | ||
1358 | static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev, | |
1359 | void *arg, struct sk_buff *resp) | |
1360 | { | |
67af1d7a | 1361 | u8 rf_tech = (unsigned long)arg; |
1c7a4c24 TE |
1362 | |
1363 | if (IS_ERR(resp)) | |
1364 | return; | |
1365 | ||
b711ad52 TE |
1366 | digital_tg_set_rf_tech(ddev, rf_tech); |
1367 | ||
1c7a4c24 TE |
1368 | digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); |
1369 | ||
1370 | digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL); | |
1371 | ||
1372 | dev_kfree_skb(resp); | |
1373 | } | |
1374 | ||
1375 | static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did, | |
1376 | u8 rf_tech) | |
1377 | { | |
1378 | struct digital_psl_res *psl_res; | |
1379 | struct sk_buff *skb; | |
1380 | int rc; | |
1381 | ||
1382 | skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res)); | |
1383 | if (!skb) | |
1384 | return -ENOMEM; | |
1385 | ||
1386 | skb_put(skb, sizeof(struct digital_psl_res)); | |
1387 | ||
1388 | psl_res = (struct digital_psl_res *)skb->data; | |
1389 | ||
1390 | psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | |
1391 | psl_res->cmd = DIGITAL_CMD_PSL_RES; | |
1392 | psl_res->did = did; | |
1393 | ||
1394 | digital_skb_push_dep_sod(ddev, skb); | |
1395 | ||
1396 | ddev->skb_add_crc(skb); | |
1397 | ||
485fdc9b MG |
1398 | ddev->curr_nfc_dep_pni = 0; |
1399 | ||
1c7a4c24 | 1400 | rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete, |
67af1d7a | 1401 | (void *)(unsigned long)rf_tech); |
1c7a4c24 TE |
1402 | if (rc) |
1403 | kfree_skb(skb); | |
1404 | ||
1405 | return rc; | |
1406 | } | |
1407 | ||
1408 | static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg, | |
1409 | struct sk_buff *resp) | |
1410 | { | |
1411 | int rc; | |
1412 | struct digital_psl_req *psl_req; | |
1413 | u8 rf_tech; | |
b08147cb | 1414 | u8 dsi, payload_size, payload_bits; |
1c7a4c24 TE |
1415 | |
1416 | if (IS_ERR(resp)) { | |
1417 | rc = PTR_ERR(resp); | |
1418 | resp = NULL; | |
1419 | goto exit; | |
1420 | } | |
1421 | ||
1422 | rc = ddev->skb_check_crc(resp); | |
1423 | if (rc) { | |
1424 | PROTOCOL_ERR("14.4.1.6"); | |
1425 | goto exit; | |
1426 | } | |
1427 | ||
1428 | rc = digital_skb_pull_dep_sod(ddev, resp); | |
1429 | if (rc) { | |
1430 | PROTOCOL_ERR("14.4.1.2"); | |
1431 | goto exit; | |
1432 | } | |
1433 | ||
1434 | psl_req = (struct digital_psl_req *)resp->data; | |
1435 | ||
1436 | if (resp->len != sizeof(struct digital_psl_req) || | |
1437 | psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT || | |
1438 | psl_req->cmd != DIGITAL_CMD_PSL_REQ) { | |
1439 | rc = -EIO; | |
1440 | goto exit; | |
1441 | } | |
1442 | ||
1443 | dsi = (psl_req->brs >> 3) & 0x07; | |
1444 | switch (dsi) { | |
1445 | case 0: | |
1446 | rf_tech = NFC_DIGITAL_RF_TECH_106A; | |
1447 | break; | |
1448 | case 1: | |
1449 | rf_tech = NFC_DIGITAL_RF_TECH_212F; | |
1450 | break; | |
1451 | case 2: | |
1452 | rf_tech = NFC_DIGITAL_RF_TECH_424F; | |
1453 | break; | |
1454 | default: | |
77d84ff8 | 1455 | pr_err("Unsupported dsi value %d\n", dsi); |
1c7a4c24 TE |
1456 | goto exit; |
1457 | } | |
1458 | ||
b08147cb MG |
1459 | payload_bits = DIGITAL_PAYLOAD_FSL_TO_BITS(psl_req->fsl); |
1460 | payload_size = digital_payload_bits_to_size(payload_bits); | |
1461 | ||
1462 | if (!payload_size || (payload_size > min(ddev->local_payload_max, | |
1463 | ddev->remote_payload_max))) { | |
1464 | rc = -EINVAL; | |
1465 | goto exit; | |
1466 | } | |
1467 | ||
1468 | ddev->local_payload_max = payload_size; | |
1469 | ddev->remote_payload_max = payload_size; | |
1470 | ||
1c7a4c24 TE |
1471 | rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech); |
1472 | ||
1473 | exit: | |
1474 | kfree_skb(resp); | |
1475 | } | |
1476 | ||
1477 | static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev, | |
1478 | void *arg, struct sk_buff *resp) | |
1479 | { | |
1480 | int offset; | |
1481 | ||
1482 | if (IS_ERR(resp)) { | |
1483 | digital_poll_next_tech(ddev); | |
1484 | return; | |
1485 | } | |
1486 | ||
1487 | offset = 2; | |
1488 | if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) | |
1489 | offset++; | |
1490 | ||
9b5ec0fd MG |
1491 | ddev->atn_count = 0; |
1492 | ||
1c7a4c24 TE |
1493 | if (resp->data[offset] == DIGITAL_CMD_PSL_REQ) |
1494 | digital_tg_recv_psl_req(ddev, arg, resp); | |
1495 | else | |
1496 | digital_tg_recv_dep_req(ddev, arg, resp); | |
1497 | } | |
1498 | ||
1499 | static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev, | |
1500 | struct digital_atr_req *atr_req) | |
1501 | { | |
1502 | struct digital_atr_res *atr_res; | |
1503 | struct sk_buff *skb; | |
b08147cb | 1504 | u8 *gb, payload_bits; |
1c7a4c24 TE |
1505 | size_t gb_len; |
1506 | int rc; | |
1507 | ||
1508 | gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len); | |
1509 | if (!gb) | |
1510 | gb_len = 0; | |
1511 | ||
1512 | skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len); | |
1513 | if (!skb) | |
1514 | return -ENOMEM; | |
1515 | ||
1516 | skb_put(skb, sizeof(struct digital_atr_res)); | |
1517 | atr_res = (struct digital_atr_res *)skb->data; | |
1518 | ||
1519 | memset(atr_res, 0, sizeof(struct digital_atr_res)); | |
1520 | ||
1521 | atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | |
1522 | atr_res->cmd = DIGITAL_CMD_ATR_RES; | |
1523 | memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3)); | |
1a09c56f | 1524 | atr_res->to = DIGITAL_NFC_DEP_TG_MAX_WT; |
b08147cb MG |
1525 | |
1526 | ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX; | |
1527 | payload_bits = digital_payload_size_to_bits(ddev->local_payload_max); | |
1528 | atr_res->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits); | |
1529 | ||
1c7a4c24 TE |
1530 | if (gb_len) { |
1531 | skb_put(skb, gb_len); | |
1532 | ||
1533 | atr_res->pp |= DIGITAL_GB_BIT; | |
1534 | memcpy(atr_res->gb, gb, gb_len); | |
1535 | } | |
1536 | ||
1537 | digital_skb_push_dep_sod(ddev, skb); | |
1538 | ||
1539 | ddev->skb_add_crc(skb); | |
1540 | ||
485fdc9b MG |
1541 | ddev->curr_nfc_dep_pni = 0; |
1542 | ||
1c7a4c24 TE |
1543 | rc = digital_tg_send_cmd(ddev, skb, 999, |
1544 | digital_tg_send_atr_res_complete, NULL); | |
b15829ba | 1545 | if (rc) |
1c7a4c24 | 1546 | kfree_skb(skb); |
1c7a4c24 TE |
1547 | |
1548 | return rc; | |
1549 | } | |
1550 | ||
1551 | void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | |
1552 | struct sk_buff *resp) | |
1553 | { | |
1554 | int rc; | |
1555 | struct digital_atr_req *atr_req; | |
1556 | size_t gb_len, min_size; | |
b08147cb | 1557 | u8 poll_tech_count, payload_bits; |
1c7a4c24 TE |
1558 | |
1559 | if (IS_ERR(resp)) { | |
1560 | rc = PTR_ERR(resp); | |
1561 | resp = NULL; | |
1562 | goto exit; | |
1563 | } | |
1564 | ||
1565 | if (!resp->len) { | |
1566 | rc = -EIO; | |
1567 | goto exit; | |
1568 | } | |
1569 | ||
1570 | if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) { | |
1571 | min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2; | |
b711ad52 | 1572 | digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_106A); |
1c7a4c24 TE |
1573 | } else { |
1574 | min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1; | |
b711ad52 | 1575 | digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_212F); |
1c7a4c24 TE |
1576 | } |
1577 | ||
1578 | if (resp->len < min_size) { | |
1579 | rc = -EIO; | |
1580 | goto exit; | |
1581 | } | |
1582 | ||
48e10445 | 1583 | ddev->curr_protocol = NFC_PROTO_NFC_DEP_MASK; |
1c7a4c24 TE |
1584 | |
1585 | rc = ddev->skb_check_crc(resp); | |
1586 | if (rc) { | |
1587 | PROTOCOL_ERR("14.4.1.6"); | |
1588 | goto exit; | |
1589 | } | |
1590 | ||
1591 | rc = digital_skb_pull_dep_sod(ddev, resp); | |
1592 | if (rc) { | |
1593 | PROTOCOL_ERR("14.4.1.2"); | |
1594 | goto exit; | |
1595 | } | |
1596 | ||
1597 | atr_req = (struct digital_atr_req *)resp->data; | |
1598 | ||
1599 | if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT || | |
05afedcb MG |
1600 | atr_req->cmd != DIGITAL_CMD_ATR_REQ || |
1601 | atr_req->did > DIGITAL_DID_MAX) { | |
1c7a4c24 TE |
1602 | rc = -EINVAL; |
1603 | goto exit; | |
1604 | } | |
1605 | ||
b08147cb MG |
1606 | payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_req->pp); |
1607 | ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits); | |
1608 | ||
1609 | if (!ddev->remote_payload_max) { | |
1610 | rc = -EINVAL; | |
1611 | goto exit; | |
1612 | } | |
1613 | ||
05afedcb MG |
1614 | ddev->did = atr_req->did; |
1615 | ||
1c7a4c24 TE |
1616 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, |
1617 | NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED); | |
1618 | if (rc) | |
1619 | goto exit; | |
1620 | ||
1621 | rc = digital_tg_send_atr_res(ddev, atr_req); | |
1622 | if (rc) | |
1623 | goto exit; | |
1624 | ||
1625 | gb_len = resp->len - sizeof(struct digital_atr_req); | |
0529a7ad MG |
1626 | |
1627 | poll_tech_count = ddev->poll_tech_count; | |
1628 | ddev->poll_tech_count = 0; | |
1629 | ||
1c7a4c24 TE |
1630 | rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, |
1631 | NFC_COMM_PASSIVE, atr_req->gb, gb_len); | |
0529a7ad MG |
1632 | if (rc) { |
1633 | ddev->poll_tech_count = poll_tech_count; | |
1c7a4c24 | 1634 | goto exit; |
0529a7ad | 1635 | } |
1c7a4c24 TE |
1636 | |
1637 | rc = 0; | |
1638 | exit: | |
1639 | if (rc) | |
1640 | digital_poll_next_tech(ddev); | |
1641 | ||
1642 | dev_kfree_skb(resp); | |
1643 | } |