blob: 95a69898d5f507920d781cf1b574b6bbc271512f [file] [log] [blame]
Thierry Escande7d0911c2013-09-19 17:55:29 +02001/*
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
Samuel Ortizc5da0e42013-09-20 09:05:48 +020016#define pr_fmt(fmt) "digital: %s: " fmt, __func__
17
Thierry Escande7d0911c2013-09-19 17:55:29 +020018#include "digital.h"
19
20#define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4
21#define DIGITAL_NFC_DEP_FRAME_DIR_IN 0xD5
22
23#define DIGITAL_NFC_DEP_NFCA_SOD_SB 0xF0
24
25#define DIGITAL_CMD_ATR_REQ 0x00
26#define DIGITAL_CMD_ATR_RES 0x01
27#define DIGITAL_CMD_PSL_REQ 0x04
28#define DIGITAL_CMD_PSL_RES 0x05
29#define DIGITAL_CMD_DEP_REQ 0x06
30#define DIGITAL_CMD_DEP_RES 0x07
31
32#define DIGITAL_ATR_REQ_MIN_SIZE 16
33#define DIGITAL_ATR_REQ_MAX_SIZE 64
34
Mark A. Greer05afedc2014-09-23 16:38:05 -070035#define DIGITAL_DID_MAX 14
36
Thierry Escande7d0911c2013-09-19 17:55:29 +020037#define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30
Mark A. Greerdddb3da2014-07-22 20:18:01 -070038#define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \
39 (DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4)
Thierry Escande7d0911c2013-09-19 17:55:29 +020040#define DIGITAL_GB_BIT 0x02
41
42#define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
43
44#define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10
Mark A. Greer05afedc2014-09-23 16:38:05 -070045#define DIGITAL_NFC_DEP_PFB_DID_BIT 0x04
Thierry Escande7d0911c2013-09-19 17:55:29 +020046
47#define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
48 ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT)
49#define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & 0x10)
50#define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
Mark A. Greer05afedc2014-09-23 16:38:05 -070051#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT)
Thierry Escande7d0911c2013-09-19 17:55:29 +020052#define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03)
53
54#define DIGITAL_NFC_DEP_PFB_I_PDU 0x00
55#define DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU 0x40
56#define DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU 0x80
57
58struct digital_atr_req {
59 u8 dir;
60 u8 cmd;
61 u8 nfcid3[10];
62 u8 did;
63 u8 bs;
64 u8 br;
65 u8 pp;
66 u8 gb[0];
67} __packed;
68
69struct digital_atr_res {
70 u8 dir;
71 u8 cmd;
72 u8 nfcid3[10];
73 u8 did;
74 u8 bs;
75 u8 br;
76 u8 to;
77 u8 pp;
78 u8 gb[0];
79} __packed;
80
81struct digital_psl_req {
82 u8 dir;
83 u8 cmd;
84 u8 did;
85 u8 brs;
86 u8 fsl;
87} __packed;
88
89struct digital_psl_res {
90 u8 dir;
91 u8 cmd;
92 u8 did;
93} __packed;
94
95struct digital_dep_req_res {
96 u8 dir;
97 u8 cmd;
98 u8 pfb;
99} __packed;
100
101static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
102 struct sk_buff *resp);
103
104static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev,
105 struct sk_buff *skb)
106{
107 skb_push(skb, sizeof(u8));
108
109 skb->data[0] = skb->len;
110
111 if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
112 *skb_push(skb, sizeof(u8)) = DIGITAL_NFC_DEP_NFCA_SOD_SB;
113}
114
115static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev,
116 struct sk_buff *skb)
117{
118 u8 size;
119
120 if (skb->len < 2)
121 return -EIO;
122
123 if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
124 skb_pull(skb, sizeof(u8));
125
126 size = skb->data[0];
127 if (size != skb->len)
128 return -EIO;
129
130 skb_pull(skb, sizeof(u8));
131
132 return 0;
133}
134
Mark A. Greerdddb3da2014-07-22 20:18:01 -0700135static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg,
136 struct sk_buff *resp)
137{
138 struct nfc_target *target = arg;
139 struct digital_psl_res *psl_res;
140 int rc;
141
142 if (IS_ERR(resp)) {
143 rc = PTR_ERR(resp);
144 resp = NULL;
145 goto exit;
146 }
147
148 rc = ddev->skb_check_crc(resp);
149 if (rc) {
150 PROTOCOL_ERR("14.4.1.6");
151 goto exit;
152 }
153
154 rc = digital_skb_pull_dep_sod(ddev, resp);
155 if (rc) {
156 PROTOCOL_ERR("14.4.1.2");
157 goto exit;
158 }
159
160 psl_res = (struct digital_psl_res *)resp->data;
161
162 if ((resp->len != sizeof(*psl_res)) ||
163 (psl_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN) ||
164 (psl_res->cmd != DIGITAL_CMD_PSL_RES)) {
165 rc = -EIO;
166 goto exit;
167 }
168
169 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
170 NFC_DIGITAL_RF_TECH_424F);
171 if (rc)
172 goto exit;
173
174 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
175 NFC_DIGITAL_FRAMING_NFCF_NFC_DEP);
176 if (rc)
177 goto exit;
178
179 if (!DIGITAL_DRV_CAPS_IN_CRC(ddev) &&
180 (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)) {
181 ddev->skb_add_crc = digital_skb_add_crc_f;
182 ddev->skb_check_crc = digital_skb_check_crc_f;
183 }
184
185 ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_424F;
186
187 nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
188 NFC_RF_INITIATOR);
189
190 ddev->curr_nfc_dep_pni = 0;
191
192exit:
193 dev_kfree_skb(resp);
194
195 if (rc)
196 ddev->curr_protocol = 0;
197}
198
199static int digital_in_send_psl_req(struct nfc_digital_dev *ddev,
200 struct nfc_target *target)
201{
202 struct sk_buff *skb;
203 struct digital_psl_req *psl_req;
Mark A. Greerb15829b2014-09-23 16:38:02 -0700204 int rc;
Mark A. Greerdddb3da2014-07-22 20:18:01 -0700205
206 skb = digital_skb_alloc(ddev, sizeof(*psl_req));
207 if (!skb)
208 return -ENOMEM;
209
210 skb_put(skb, sizeof(*psl_req));
211
212 psl_req = (struct digital_psl_req *)skb->data;
213
214 psl_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
215 psl_req->cmd = DIGITAL_CMD_PSL_REQ;
216 psl_req->did = 0;
217 psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */
218 psl_req->fsl = DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B;
219
220 digital_skb_push_dep_sod(ddev, skb);
221
222 ddev->skb_add_crc(skb);
223
Mark A. Greerb15829b2014-09-23 16:38:02 -0700224 rc = digital_in_send_cmd(ddev, skb, 500, digital_in_recv_psl_res,
225 target);
226 if (rc)
227 kfree_skb(skb);
228
229 return rc;
Mark A. Greerdddb3da2014-07-22 20:18:01 -0700230}
231
Thierry Escande7d0911c2013-09-19 17:55:29 +0200232static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
233 struct sk_buff *resp)
234{
235 struct nfc_target *target = arg;
236 struct digital_atr_res *atr_res;
237 u8 gb_len;
238 int rc;
239
240 if (IS_ERR(resp)) {
241 rc = PTR_ERR(resp);
242 resp = NULL;
243 goto exit;
244 }
245
246 rc = ddev->skb_check_crc(resp);
247 if (rc) {
248 PROTOCOL_ERR("14.4.1.6");
249 goto exit;
250 }
251
252 rc = digital_skb_pull_dep_sod(ddev, resp);
253 if (rc) {
254 PROTOCOL_ERR("14.4.1.2");
255 goto exit;
256 }
257
258 if (resp->len < sizeof(struct digital_atr_res)) {
259 rc = -EIO;
260 goto exit;
261 }
262
263 gb_len = resp->len - sizeof(struct digital_atr_res);
264
265 atr_res = (struct digital_atr_res *)resp->data;
266
267 rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len);
268 if (rc)
269 goto exit;
270
Mark A. Greerdddb3da2014-07-22 20:18:01 -0700271 if ((ddev->protocols & NFC_PROTO_FELICA_MASK) &&
272 (ddev->curr_rf_tech != NFC_DIGITAL_RF_TECH_424F)) {
273 rc = digital_in_send_psl_req(ddev, target);
274 if (!rc)
275 goto exit;
276 }
277
Thierry Escande7d0911c2013-09-19 17:55:29 +0200278 rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
279 NFC_RF_INITIATOR);
280
281 ddev->curr_nfc_dep_pni = 0;
282
283exit:
284 dev_kfree_skb(resp);
285
286 if (rc)
287 ddev->curr_protocol = 0;
288}
289
290int digital_in_send_atr_req(struct nfc_digital_dev *ddev,
291 struct nfc_target *target, __u8 comm_mode, __u8 *gb,
292 size_t gb_len)
293{
294 struct sk_buff *skb;
295 struct digital_atr_req *atr_req;
296 uint size;
Mark A. Greerb15829b2014-09-23 16:38:02 -0700297 int rc;
Thierry Escande7d0911c2013-09-19 17:55:29 +0200298
299 size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len;
300
301 if (size > DIGITAL_ATR_REQ_MAX_SIZE) {
302 PROTOCOL_ERR("14.6.1.1");
303 return -EINVAL;
304 }
305
306 skb = digital_skb_alloc(ddev, size);
307 if (!skb)
308 return -ENOMEM;
309
310 skb_put(skb, sizeof(struct digital_atr_req));
311
312 atr_req = (struct digital_atr_req *)skb->data;
313 memset(atr_req, 0, sizeof(struct digital_atr_req));
314
315 atr_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
316 atr_req->cmd = DIGITAL_CMD_ATR_REQ;
317 if (target->nfcid2_len)
Thierry Escande4f319e32014-01-02 11:58:14 +0100318 memcpy(atr_req->nfcid3, target->nfcid2, NFC_NFCID2_MAXSIZE);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200319 else
Thierry Escande4f319e32014-01-02 11:58:14 +0100320 get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200321
322 atr_req->did = 0;
323 atr_req->bs = 0;
324 atr_req->br = 0;
325
326 atr_req->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
327
328 if (gb_len) {
329 atr_req->pp |= DIGITAL_GB_BIT;
330 memcpy(skb_put(skb, gb_len), gb, gb_len);
331 }
332
333 digital_skb_push_dep_sod(ddev, skb);
334
335 ddev->skb_add_crc(skb);
336
Mark A. Greerb15829b2014-09-23 16:38:02 -0700337 rc = digital_in_send_cmd(ddev, skb, 500, digital_in_recv_atr_res,
338 target);
339 if (rc)
340 kfree_skb(skb);
341
342 return rc;
Thierry Escande7d0911c2013-09-19 17:55:29 +0200343}
344
345static int digital_in_send_rtox(struct nfc_digital_dev *ddev,
346 struct digital_data_exch *data_exch, u8 rtox)
347{
348 struct digital_dep_req_res *dep_req;
349 struct sk_buff *skb;
350 int rc;
351
352 skb = digital_skb_alloc(ddev, 1);
353 if (!skb)
354 return -ENOMEM;
355
356 *skb_put(skb, 1) = rtox;
357
358 skb_push(skb, sizeof(struct digital_dep_req_res));
359
360 dep_req = (struct digital_dep_req_res *)skb->data;
361
362 dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
363 dep_req->cmd = DIGITAL_CMD_DEP_REQ;
364 dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU |
365 DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT;
366
367 digital_skb_push_dep_sod(ddev, skb);
368
369 ddev->skb_add_crc(skb);
370
371 rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
372 data_exch);
Mark A. Greerb15829b2014-09-23 16:38:02 -0700373 if (rc)
374 kfree_skb(skb);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200375
376 return rc;
377}
378
379static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
380 struct sk_buff *resp)
381{
382 struct digital_data_exch *data_exch = arg;
383 struct digital_dep_req_res *dep_res;
384 u8 pfb;
385 uint size;
386 int rc;
387
388 if (IS_ERR(resp)) {
389 rc = PTR_ERR(resp);
390 resp = NULL;
391 goto exit;
392 }
393
394 rc = ddev->skb_check_crc(resp);
395 if (rc) {
396 PROTOCOL_ERR("14.4.1.6");
397 goto error;
398 }
399
400 rc = digital_skb_pull_dep_sod(ddev, resp);
401 if (rc) {
402 PROTOCOL_ERR("14.4.1.2");
403 goto exit;
404 }
405
Mark A. Greer6ce30662014-09-23 16:38:03 -0700406 size = sizeof(struct digital_dep_req_res);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200407 dep_res = (struct digital_dep_req_res *)resp->data;
408
Mark A. Greer6ce30662014-09-23 16:38:03 -0700409 if (resp->len < size || dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN ||
Thierry Escande7d0911c2013-09-19 17:55:29 +0200410 dep_res->cmd != DIGITAL_CMD_DEP_RES) {
411 rc = -EIO;
412 goto error;
413 }
414
415 pfb = dep_res->pfb;
416
Mark A. Greer3bc3f882014-09-23 16:38:04 -0700417 if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
418 PROTOCOL_ERR("14.8.2.1");
419 rc = -EIO;
420 goto error;
421 }
Mark A. Greer6ce30662014-09-23 16:38:03 -0700422
Mark A. Greer3e6b0de2014-09-23 16:38:06 -0700423 if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
424 rc = -EIO;
425 goto exit;
426 }
427
Mark A. Greer6ce30662014-09-23 16:38:03 -0700428 if (size > resp->len) {
429 rc = -EIO;
430 goto error;
431 }
432
433 skb_pull(resp, size);
434
Thierry Escande7d0911c2013-09-19 17:55:29 +0200435 switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
436 case DIGITAL_NFC_DEP_PFB_I_PDU:
437 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
438 PROTOCOL_ERR("14.12.3.3");
439 rc = -EIO;
440 goto error;
441 }
442
443 ddev->curr_nfc_dep_pni =
444 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
445 rc = 0;
446 break;
447
448 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200449 pr_err("Received a ACK/NACK PDU\n");
Mark A. Greer485fdc92014-09-23 16:38:07 -0700450
451 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
452 PROTOCOL_ERR("14.12.3.3");
453 rc = -EIO;
454 goto exit;
455 }
456
457 ddev->curr_nfc_dep_pni =
458 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
459
460 rc = -EINVAL;
461 goto exit;
Thierry Escande7d0911c2013-09-19 17:55:29 +0200462
463 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
464 if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
465 rc = -EINVAL;
466 goto error;
467 }
468
Mark A. Greer6ce30662014-09-23 16:38:03 -0700469 rc = digital_in_send_rtox(ddev, data_exch, resp->data[0]);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200470 if (rc)
471 goto error;
472
473 kfree_skb(resp);
474 return;
475 }
476
477 if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
Samuel Ortiz26042532013-09-20 16:56:40 +0200478 pr_err("MI bit set. Chained PDU not supported\n");
Thierry Escande7d0911c2013-09-19 17:55:29 +0200479 rc = -EIO;
480 goto error;
481 }
482
Thierry Escande7d0911c2013-09-19 17:55:29 +0200483exit:
484 data_exch->cb(data_exch->cb_context, resp, rc);
485
486error:
487 kfree(data_exch);
488
489 if (rc)
490 kfree_skb(resp);
491}
492
493int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
494 struct nfc_target *target, struct sk_buff *skb,
495 struct digital_data_exch *data_exch)
496{
497 struct digital_dep_req_res *dep_req;
498
499 skb_push(skb, sizeof(struct digital_dep_req_res));
500
501 dep_req = (struct digital_dep_req_res *)skb->data;
502 dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
503 dep_req->cmd = DIGITAL_CMD_DEP_REQ;
504 dep_req->pfb = ddev->curr_nfc_dep_pni;
505
506 digital_skb_push_dep_sod(ddev, skb);
507
508 ddev->skb_add_crc(skb);
509
510 return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
511 data_exch);
512}
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200513
Thierry Escandeb711ad52014-01-06 23:34:48 +0100514static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech)
515{
516 ddev->curr_rf_tech = rf_tech;
517
518 ddev->skb_add_crc = digital_skb_add_crc_none;
519 ddev->skb_check_crc = digital_skb_check_crc_none;
520
521 if (DIGITAL_DRV_CAPS_TG_CRC(ddev))
522 return;
523
524 switch (ddev->curr_rf_tech) {
525 case NFC_DIGITAL_RF_TECH_106A:
526 ddev->skb_add_crc = digital_skb_add_crc_a;
527 ddev->skb_check_crc = digital_skb_check_crc_a;
528 break;
529
530 case NFC_DIGITAL_RF_TECH_212F:
531 case NFC_DIGITAL_RF_TECH_424F:
532 ddev->skb_add_crc = digital_skb_add_crc_f;
533 ddev->skb_check_crc = digital_skb_check_crc_f;
534 break;
535
536 default:
537 break;
538 }
539}
540
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200541static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
542 struct sk_buff *resp)
543{
544 int rc;
545 struct digital_dep_req_res *dep_req;
Mark A. Greer6ce30662014-09-23 16:38:03 -0700546 u8 pfb;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200547 size_t size;
548
549 if (IS_ERR(resp)) {
550 rc = PTR_ERR(resp);
551 resp = NULL;
552 goto exit;
553 }
554
555 rc = ddev->skb_check_crc(resp);
556 if (rc) {
557 PROTOCOL_ERR("14.4.1.6");
558 goto exit;
559 }
560
561 rc = digital_skb_pull_dep_sod(ddev, resp);
562 if (rc) {
563 PROTOCOL_ERR("14.4.1.2");
564 goto exit;
565 }
566
567 size = sizeof(struct digital_dep_req_res);
568 dep_req = (struct digital_dep_req_res *)resp->data;
569
570 if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
571 dep_req->cmd != DIGITAL_CMD_DEP_REQ) {
572 rc = -EIO;
573 goto exit;
574 }
575
Mark A. Greer6ce30662014-09-23 16:38:03 -0700576 pfb = dep_req->pfb;
577
Mark A. Greer05afedc2014-09-23 16:38:05 -0700578 if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
579 if (ddev->did && (ddev->did == resp->data[3])) {
580 size++;
581 } else {
582 rc = -EIO;
583 goto exit;
584 }
585 } else if (ddev->did) {
586 rc = -EIO;
587 goto exit;
588 }
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200589
Mark A. Greer3e6b0de2014-09-23 16:38:06 -0700590 if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
591 rc = -EIO;
592 goto exit;
593 }
594
Mark A. Greer6ce30662014-09-23 16:38:03 -0700595 if (size > resp->len) {
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200596 rc = -EIO;
597 goto exit;
598 }
599
Mark A. Greer6ce30662014-09-23 16:38:03 -0700600 skb_pull(resp, size);
601
602 switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200603 case DIGITAL_NFC_DEP_PFB_I_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200604 pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
Mark A. Greer485fdc92014-09-23 16:38:07 -0700605
606 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
607 PROTOCOL_ERR("14.12.3.4");
608 rc = -EIO;
609 goto exit;
610 }
611
612 rc = 0;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200613 break;
614 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
Mark A. Greer485fdc92014-09-23 16:38:07 -0700615 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
616 PROTOCOL_ERR("14.12.3.4");
617 rc = -EIO;
618 goto exit;
619 }
620
Samuel Ortiz26042532013-09-20 16:56:40 +0200621 pr_err("Received a ACK/NACK PDU\n");
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200622 rc = -EINVAL;
623 goto exit;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200624 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200625 pr_err("Received a SUPERVISOR PDU\n");
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200626 rc = -EINVAL;
627 goto exit;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200628 }
629
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200630 rc = nfc_tm_data_received(ddev->nfc_dev, resp);
631
632exit:
633 if (rc)
634 kfree_skb(resp);
635}
636
637int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
638{
639 struct digital_dep_req_res *dep_res;
640
641 skb_push(skb, sizeof(struct digital_dep_req_res));
642 dep_res = (struct digital_dep_req_res *)skb->data;
643
644 dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
645 dep_res->cmd = DIGITAL_CMD_DEP_RES;
646 dep_res->pfb = ddev->curr_nfc_dep_pni;
647
Mark A. Greer05afedc2014-09-23 16:38:05 -0700648 if (ddev->did) {
649 dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
650
651 memcpy(skb_put(skb, sizeof(ddev->did)), &ddev->did,
652 sizeof(ddev->did));
653 }
654
Mark A. Greer485fdc92014-09-23 16:38:07 -0700655 ddev->curr_nfc_dep_pni =
656 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
657
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200658 digital_skb_push_dep_sod(ddev, skb);
659
660 ddev->skb_add_crc(skb);
661
662 return digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
663 NULL);
664}
665
666static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,
667 void *arg, struct sk_buff *resp)
668{
Thierry Escande67af1d72014-01-02 11:58:13 +0100669 u8 rf_tech = (unsigned long)arg;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200670
671 if (IS_ERR(resp))
672 return;
673
Thierry Escandeb711ad52014-01-06 23:34:48 +0100674 digital_tg_set_rf_tech(ddev, rf_tech);
675
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200676 digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
677
678 digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL);
679
680 dev_kfree_skb(resp);
681}
682
683static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did,
684 u8 rf_tech)
685{
686 struct digital_psl_res *psl_res;
687 struct sk_buff *skb;
688 int rc;
689
690 skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res));
691 if (!skb)
692 return -ENOMEM;
693
694 skb_put(skb, sizeof(struct digital_psl_res));
695
696 psl_res = (struct digital_psl_res *)skb->data;
697
698 psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
699 psl_res->cmd = DIGITAL_CMD_PSL_RES;
700 psl_res->did = did;
701
702 digital_skb_push_dep_sod(ddev, skb);
703
704 ddev->skb_add_crc(skb);
705
Mark A. Greer485fdc92014-09-23 16:38:07 -0700706 ddev->curr_nfc_dep_pni = 0;
707
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200708 rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
Thierry Escande67af1d72014-01-02 11:58:13 +0100709 (void *)(unsigned long)rf_tech);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200710 if (rc)
711 kfree_skb(skb);
712
713 return rc;
714}
715
716static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg,
717 struct sk_buff *resp)
718{
719 int rc;
720 struct digital_psl_req *psl_req;
721 u8 rf_tech;
722 u8 dsi;
723
724 if (IS_ERR(resp)) {
725 rc = PTR_ERR(resp);
726 resp = NULL;
727 goto exit;
728 }
729
730 rc = ddev->skb_check_crc(resp);
731 if (rc) {
732 PROTOCOL_ERR("14.4.1.6");
733 goto exit;
734 }
735
736 rc = digital_skb_pull_dep_sod(ddev, resp);
737 if (rc) {
738 PROTOCOL_ERR("14.4.1.2");
739 goto exit;
740 }
741
742 psl_req = (struct digital_psl_req *)resp->data;
743
744 if (resp->len != sizeof(struct digital_psl_req) ||
745 psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
746 psl_req->cmd != DIGITAL_CMD_PSL_REQ) {
747 rc = -EIO;
748 goto exit;
749 }
750
751 dsi = (psl_req->brs >> 3) & 0x07;
752 switch (dsi) {
753 case 0:
754 rf_tech = NFC_DIGITAL_RF_TECH_106A;
755 break;
756 case 1:
757 rf_tech = NFC_DIGITAL_RF_TECH_212F;
758 break;
759 case 2:
760 rf_tech = NFC_DIGITAL_RF_TECH_424F;
761 break;
762 default:
Masanari Iida77d84ff2013-12-09 00:22:53 +0900763 pr_err("Unsupported dsi value %d\n", dsi);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200764 goto exit;
765 }
766
767 rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
768
769exit:
770 kfree_skb(resp);
771}
772
773static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev,
774 void *arg, struct sk_buff *resp)
775{
776 int offset;
777
778 if (IS_ERR(resp)) {
779 digital_poll_next_tech(ddev);
780 return;
781 }
782
783 offset = 2;
784 if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
785 offset++;
786
787 if (resp->data[offset] == DIGITAL_CMD_PSL_REQ)
788 digital_tg_recv_psl_req(ddev, arg, resp);
789 else
790 digital_tg_recv_dep_req(ddev, arg, resp);
791}
792
793static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,
794 struct digital_atr_req *atr_req)
795{
796 struct digital_atr_res *atr_res;
797 struct sk_buff *skb;
798 u8 *gb;
799 size_t gb_len;
800 int rc;
801
802 gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len);
803 if (!gb)
804 gb_len = 0;
805
806 skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len);
807 if (!skb)
808 return -ENOMEM;
809
810 skb_put(skb, sizeof(struct digital_atr_res));
811 atr_res = (struct digital_atr_res *)skb->data;
812
813 memset(atr_res, 0, sizeof(struct digital_atr_res));
814
815 atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
816 atr_res->cmd = DIGITAL_CMD_ATR_RES;
817 memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
818 atr_res->to = 8;
819 atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
820 if (gb_len) {
821 skb_put(skb, gb_len);
822
823 atr_res->pp |= DIGITAL_GB_BIT;
824 memcpy(atr_res->gb, gb, gb_len);
825 }
826
827 digital_skb_push_dep_sod(ddev, skb);
828
829 ddev->skb_add_crc(skb);
830
Mark A. Greer485fdc92014-09-23 16:38:07 -0700831 ddev->curr_nfc_dep_pni = 0;
832
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200833 rc = digital_tg_send_cmd(ddev, skb, 999,
834 digital_tg_send_atr_res_complete, NULL);
Mark A. Greerb15829b2014-09-23 16:38:02 -0700835 if (rc)
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200836 kfree_skb(skb);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200837
838 return rc;
839}
840
841void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg,
842 struct sk_buff *resp)
843{
844 int rc;
845 struct digital_atr_req *atr_req;
846 size_t gb_len, min_size;
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700847 u8 poll_tech_count;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200848
849 if (IS_ERR(resp)) {
850 rc = PTR_ERR(resp);
851 resp = NULL;
852 goto exit;
853 }
854
855 if (!resp->len) {
856 rc = -EIO;
857 goto exit;
858 }
859
860 if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) {
861 min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2;
Thierry Escandeb711ad52014-01-06 23:34:48 +0100862 digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_106A);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200863 } else {
864 min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1;
Thierry Escandeb711ad52014-01-06 23:34:48 +0100865 digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_212F);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200866 }
867
868 if (resp->len < min_size) {
869 rc = -EIO;
870 goto exit;
871 }
872
Thierry Escande48e10442014-01-06 23:34:37 +0100873 ddev->curr_protocol = NFC_PROTO_NFC_DEP_MASK;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200874
875 rc = ddev->skb_check_crc(resp);
876 if (rc) {
877 PROTOCOL_ERR("14.4.1.6");
878 goto exit;
879 }
880
881 rc = digital_skb_pull_dep_sod(ddev, resp);
882 if (rc) {
883 PROTOCOL_ERR("14.4.1.2");
884 goto exit;
885 }
886
887 atr_req = (struct digital_atr_req *)resp->data;
888
889 if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
Mark A. Greer05afedc2014-09-23 16:38:05 -0700890 atr_req->cmd != DIGITAL_CMD_ATR_REQ ||
891 atr_req->did > DIGITAL_DID_MAX) {
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200892 rc = -EINVAL;
893 goto exit;
894 }
895
Mark A. Greer05afedc2014-09-23 16:38:05 -0700896 ddev->did = atr_req->did;
897
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200898 rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
899 NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
900 if (rc)
901 goto exit;
902
903 rc = digital_tg_send_atr_res(ddev, atr_req);
904 if (rc)
905 goto exit;
906
907 gb_len = resp->len - sizeof(struct digital_atr_req);
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700908
909 poll_tech_count = ddev->poll_tech_count;
910 ddev->poll_tech_count = 0;
911
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200912 rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
913 NFC_COMM_PASSIVE, atr_req->gb, gb_len);
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700914 if (rc) {
915 ddev->poll_tech_count = poll_tech_count;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200916 goto exit;
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700917 }
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200918
919 rc = 0;
920exit:
921 if (rc)
922 digital_poll_next_tech(ddev);
923
924 dev_kfree_skb(resp);
925}