blob: 70fcce03e8a9e58019959bb68923af32d7abf898 [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
Thierry Escande7d0911c2013-09-19 17:55:29 +020035#define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30
Mark A. Greerdddb3da2014-07-22 20:18:01 -070036#define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \
37 (DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4)
Thierry Escande7d0911c2013-09-19 17:55:29 +020038#define DIGITAL_GB_BIT 0x02
39
40#define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
41
42#define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10
43
44#define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
45 ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT)
46#define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & 0x10)
47#define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
48#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04)
49#define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03)
50
51#define DIGITAL_NFC_DEP_PFB_I_PDU 0x00
52#define DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU 0x40
53#define DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU 0x80
54
55struct digital_atr_req {
56 u8 dir;
57 u8 cmd;
58 u8 nfcid3[10];
59 u8 did;
60 u8 bs;
61 u8 br;
62 u8 pp;
63 u8 gb[0];
64} __packed;
65
66struct digital_atr_res {
67 u8 dir;
68 u8 cmd;
69 u8 nfcid3[10];
70 u8 did;
71 u8 bs;
72 u8 br;
73 u8 to;
74 u8 pp;
75 u8 gb[0];
76} __packed;
77
78struct digital_psl_req {
79 u8 dir;
80 u8 cmd;
81 u8 did;
82 u8 brs;
83 u8 fsl;
84} __packed;
85
86struct digital_psl_res {
87 u8 dir;
88 u8 cmd;
89 u8 did;
90} __packed;
91
92struct digital_dep_req_res {
93 u8 dir;
94 u8 cmd;
95 u8 pfb;
96} __packed;
97
98static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
99 struct sk_buff *resp);
100
101static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev,
102 struct sk_buff *skb)
103{
104 skb_push(skb, sizeof(u8));
105
106 skb->data[0] = skb->len;
107
108 if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
109 *skb_push(skb, sizeof(u8)) = DIGITAL_NFC_DEP_NFCA_SOD_SB;
110}
111
112static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev,
113 struct sk_buff *skb)
114{
115 u8 size;
116
117 if (skb->len < 2)
118 return -EIO;
119
120 if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
121 skb_pull(skb, sizeof(u8));
122
123 size = skb->data[0];
124 if (size != skb->len)
125 return -EIO;
126
127 skb_pull(skb, sizeof(u8));
128
129 return 0;
130}
131
Mark A. Greerdddb3da2014-07-22 20:18:01 -0700132static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg,
133 struct sk_buff *resp)
134{
135 struct nfc_target *target = arg;
136 struct digital_psl_res *psl_res;
137 int rc;
138
139 if (IS_ERR(resp)) {
140 rc = PTR_ERR(resp);
141 resp = NULL;
142 goto exit;
143 }
144
145 rc = ddev->skb_check_crc(resp);
146 if (rc) {
147 PROTOCOL_ERR("14.4.1.6");
148 goto exit;
149 }
150
151 rc = digital_skb_pull_dep_sod(ddev, resp);
152 if (rc) {
153 PROTOCOL_ERR("14.4.1.2");
154 goto exit;
155 }
156
157 psl_res = (struct digital_psl_res *)resp->data;
158
159 if ((resp->len != sizeof(*psl_res)) ||
160 (psl_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN) ||
161 (psl_res->cmd != DIGITAL_CMD_PSL_RES)) {
162 rc = -EIO;
163 goto exit;
164 }
165
166 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
167 NFC_DIGITAL_RF_TECH_424F);
168 if (rc)
169 goto exit;
170
171 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
172 NFC_DIGITAL_FRAMING_NFCF_NFC_DEP);
173 if (rc)
174 goto exit;
175
176 if (!DIGITAL_DRV_CAPS_IN_CRC(ddev) &&
177 (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)) {
178 ddev->skb_add_crc = digital_skb_add_crc_f;
179 ddev->skb_check_crc = digital_skb_check_crc_f;
180 }
181
182 ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_424F;
183
184 nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
185 NFC_RF_INITIATOR);
186
187 ddev->curr_nfc_dep_pni = 0;
188
189exit:
190 dev_kfree_skb(resp);
191
192 if (rc)
193 ddev->curr_protocol = 0;
194}
195
196static int digital_in_send_psl_req(struct nfc_digital_dev *ddev,
197 struct nfc_target *target)
198{
199 struct sk_buff *skb;
200 struct digital_psl_req *psl_req;
Mark A. Greerb15829b2014-09-23 16:38:02 -0700201 int rc;
Mark A. Greerdddb3da2014-07-22 20:18:01 -0700202
203 skb = digital_skb_alloc(ddev, sizeof(*psl_req));
204 if (!skb)
205 return -ENOMEM;
206
207 skb_put(skb, sizeof(*psl_req));
208
209 psl_req = (struct digital_psl_req *)skb->data;
210
211 psl_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
212 psl_req->cmd = DIGITAL_CMD_PSL_REQ;
213 psl_req->did = 0;
214 psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */
215 psl_req->fsl = DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B;
216
217 digital_skb_push_dep_sod(ddev, skb);
218
219 ddev->skb_add_crc(skb);
220
Mark A. Greerb15829b2014-09-23 16:38:02 -0700221 rc = digital_in_send_cmd(ddev, skb, 500, digital_in_recv_psl_res,
222 target);
223 if (rc)
224 kfree_skb(skb);
225
226 return rc;
Mark A. Greerdddb3da2014-07-22 20:18:01 -0700227}
228
Thierry Escande7d0911c2013-09-19 17:55:29 +0200229static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
230 struct sk_buff *resp)
231{
232 struct nfc_target *target = arg;
233 struct digital_atr_res *atr_res;
234 u8 gb_len;
235 int rc;
236
237 if (IS_ERR(resp)) {
238 rc = PTR_ERR(resp);
239 resp = NULL;
240 goto exit;
241 }
242
243 rc = ddev->skb_check_crc(resp);
244 if (rc) {
245 PROTOCOL_ERR("14.4.1.6");
246 goto exit;
247 }
248
249 rc = digital_skb_pull_dep_sod(ddev, resp);
250 if (rc) {
251 PROTOCOL_ERR("14.4.1.2");
252 goto exit;
253 }
254
255 if (resp->len < sizeof(struct digital_atr_res)) {
256 rc = -EIO;
257 goto exit;
258 }
259
260 gb_len = resp->len - sizeof(struct digital_atr_res);
261
262 atr_res = (struct digital_atr_res *)resp->data;
263
264 rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len);
265 if (rc)
266 goto exit;
267
Mark A. Greerdddb3da2014-07-22 20:18:01 -0700268 if ((ddev->protocols & NFC_PROTO_FELICA_MASK) &&
269 (ddev->curr_rf_tech != NFC_DIGITAL_RF_TECH_424F)) {
270 rc = digital_in_send_psl_req(ddev, target);
271 if (!rc)
272 goto exit;
273 }
274
Thierry Escande7d0911c2013-09-19 17:55:29 +0200275 rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
276 NFC_RF_INITIATOR);
277
278 ddev->curr_nfc_dep_pni = 0;
279
280exit:
281 dev_kfree_skb(resp);
282
283 if (rc)
284 ddev->curr_protocol = 0;
285}
286
287int digital_in_send_atr_req(struct nfc_digital_dev *ddev,
288 struct nfc_target *target, __u8 comm_mode, __u8 *gb,
289 size_t gb_len)
290{
291 struct sk_buff *skb;
292 struct digital_atr_req *atr_req;
293 uint size;
Mark A. Greerb15829b2014-09-23 16:38:02 -0700294 int rc;
Thierry Escande7d0911c2013-09-19 17:55:29 +0200295
296 size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len;
297
298 if (size > DIGITAL_ATR_REQ_MAX_SIZE) {
299 PROTOCOL_ERR("14.6.1.1");
300 return -EINVAL;
301 }
302
303 skb = digital_skb_alloc(ddev, size);
304 if (!skb)
305 return -ENOMEM;
306
307 skb_put(skb, sizeof(struct digital_atr_req));
308
309 atr_req = (struct digital_atr_req *)skb->data;
310 memset(atr_req, 0, sizeof(struct digital_atr_req));
311
312 atr_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
313 atr_req->cmd = DIGITAL_CMD_ATR_REQ;
314 if (target->nfcid2_len)
Thierry Escande4f319e32014-01-02 11:58:14 +0100315 memcpy(atr_req->nfcid3, target->nfcid2, NFC_NFCID2_MAXSIZE);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200316 else
Thierry Escande4f319e32014-01-02 11:58:14 +0100317 get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200318
319 atr_req->did = 0;
320 atr_req->bs = 0;
321 atr_req->br = 0;
322
323 atr_req->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
324
325 if (gb_len) {
326 atr_req->pp |= DIGITAL_GB_BIT;
327 memcpy(skb_put(skb, gb_len), gb, gb_len);
328 }
329
330 digital_skb_push_dep_sod(ddev, skb);
331
332 ddev->skb_add_crc(skb);
333
Mark A. Greerb15829b2014-09-23 16:38:02 -0700334 rc = digital_in_send_cmd(ddev, skb, 500, digital_in_recv_atr_res,
335 target);
336 if (rc)
337 kfree_skb(skb);
338
339 return rc;
Thierry Escande7d0911c2013-09-19 17:55:29 +0200340}
341
342static int digital_in_send_rtox(struct nfc_digital_dev *ddev,
343 struct digital_data_exch *data_exch, u8 rtox)
344{
345 struct digital_dep_req_res *dep_req;
346 struct sk_buff *skb;
347 int rc;
348
349 skb = digital_skb_alloc(ddev, 1);
350 if (!skb)
351 return -ENOMEM;
352
353 *skb_put(skb, 1) = rtox;
354
355 skb_push(skb, sizeof(struct digital_dep_req_res));
356
357 dep_req = (struct digital_dep_req_res *)skb->data;
358
359 dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
360 dep_req->cmd = DIGITAL_CMD_DEP_REQ;
361 dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU |
362 DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT;
363
364 digital_skb_push_dep_sod(ddev, skb);
365
366 ddev->skb_add_crc(skb);
367
368 rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
369 data_exch);
Mark A. Greerb15829b2014-09-23 16:38:02 -0700370 if (rc)
371 kfree_skb(skb);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200372
373 return rc;
374}
375
376static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
377 struct sk_buff *resp)
378{
379 struct digital_data_exch *data_exch = arg;
380 struct digital_dep_req_res *dep_res;
381 u8 pfb;
382 uint size;
383 int rc;
384
385 if (IS_ERR(resp)) {
386 rc = PTR_ERR(resp);
387 resp = NULL;
388 goto exit;
389 }
390
391 rc = ddev->skb_check_crc(resp);
392 if (rc) {
393 PROTOCOL_ERR("14.4.1.6");
394 goto error;
395 }
396
397 rc = digital_skb_pull_dep_sod(ddev, resp);
398 if (rc) {
399 PROTOCOL_ERR("14.4.1.2");
400 goto exit;
401 }
402
403 dep_res = (struct digital_dep_req_res *)resp->data;
404
405 if (resp->len < sizeof(struct digital_dep_req_res) ||
406 dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN ||
407 dep_res->cmd != DIGITAL_CMD_DEP_RES) {
408 rc = -EIO;
409 goto error;
410 }
411
412 pfb = dep_res->pfb;
413
414 switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
415 case DIGITAL_NFC_DEP_PFB_I_PDU:
416 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
417 PROTOCOL_ERR("14.12.3.3");
418 rc = -EIO;
419 goto error;
420 }
421
422 ddev->curr_nfc_dep_pni =
423 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
424 rc = 0;
425 break;
426
427 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200428 pr_err("Received a ACK/NACK PDU\n");
Thierry Escande7d0911c2013-09-19 17:55:29 +0200429 rc = -EIO;
430 goto error;
431
432 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
433 if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
434 rc = -EINVAL;
435 goto error;
436 }
437
438 rc = digital_in_send_rtox(ddev, data_exch, resp->data[3]);
439 if (rc)
440 goto error;
441
442 kfree_skb(resp);
443 return;
444 }
445
446 if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
Samuel Ortiz26042532013-09-20 16:56:40 +0200447 pr_err("MI bit set. Chained PDU not supported\n");
Thierry Escande7d0911c2013-09-19 17:55:29 +0200448 rc = -EIO;
449 goto error;
450 }
451
452 size = sizeof(struct digital_dep_req_res);
453
454 if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb))
455 size++;
456
457 if (size > resp->len) {
458 rc = -EIO;
459 goto error;
460 }
461
462 skb_pull(resp, size);
463
464exit:
465 data_exch->cb(data_exch->cb_context, resp, rc);
466
467error:
468 kfree(data_exch);
469
470 if (rc)
471 kfree_skb(resp);
472}
473
474int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
475 struct nfc_target *target, struct sk_buff *skb,
476 struct digital_data_exch *data_exch)
477{
478 struct digital_dep_req_res *dep_req;
479
480 skb_push(skb, sizeof(struct digital_dep_req_res));
481
482 dep_req = (struct digital_dep_req_res *)skb->data;
483 dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
484 dep_req->cmd = DIGITAL_CMD_DEP_REQ;
485 dep_req->pfb = ddev->curr_nfc_dep_pni;
486
487 digital_skb_push_dep_sod(ddev, skb);
488
489 ddev->skb_add_crc(skb);
490
491 return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
492 data_exch);
493}
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200494
Thierry Escandeb711ad52014-01-06 23:34:48 +0100495static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech)
496{
497 ddev->curr_rf_tech = rf_tech;
498
499 ddev->skb_add_crc = digital_skb_add_crc_none;
500 ddev->skb_check_crc = digital_skb_check_crc_none;
501
502 if (DIGITAL_DRV_CAPS_TG_CRC(ddev))
503 return;
504
505 switch (ddev->curr_rf_tech) {
506 case NFC_DIGITAL_RF_TECH_106A:
507 ddev->skb_add_crc = digital_skb_add_crc_a;
508 ddev->skb_check_crc = digital_skb_check_crc_a;
509 break;
510
511 case NFC_DIGITAL_RF_TECH_212F:
512 case NFC_DIGITAL_RF_TECH_424F:
513 ddev->skb_add_crc = digital_skb_add_crc_f;
514 ddev->skb_check_crc = digital_skb_check_crc_f;
515 break;
516
517 default:
518 break;
519 }
520}
521
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200522static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
523 struct sk_buff *resp)
524{
525 int rc;
526 struct digital_dep_req_res *dep_req;
527 size_t size;
528
529 if (IS_ERR(resp)) {
530 rc = PTR_ERR(resp);
531 resp = NULL;
532 goto exit;
533 }
534
535 rc = ddev->skb_check_crc(resp);
536 if (rc) {
537 PROTOCOL_ERR("14.4.1.6");
538 goto exit;
539 }
540
541 rc = digital_skb_pull_dep_sod(ddev, resp);
542 if (rc) {
543 PROTOCOL_ERR("14.4.1.2");
544 goto exit;
545 }
546
547 size = sizeof(struct digital_dep_req_res);
548 dep_req = (struct digital_dep_req_res *)resp->data;
549
550 if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
551 dep_req->cmd != DIGITAL_CMD_DEP_REQ) {
552 rc = -EIO;
553 goto exit;
554 }
555
556 if (DIGITAL_NFC_DEP_DID_BIT_SET(dep_req->pfb))
557 size++;
558
559 if (resp->len < size) {
560 rc = -EIO;
561 goto exit;
562 }
563
564 switch (DIGITAL_NFC_DEP_PFB_TYPE(dep_req->pfb)) {
565 case DIGITAL_NFC_DEP_PFB_I_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200566 pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200567 ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(dep_req->pfb);
568 break;
569 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200570 pr_err("Received a ACK/NACK PDU\n");
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200571 rc = -EINVAL;
572 goto exit;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200573 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200574 pr_err("Received a SUPERVISOR PDU\n");
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200575 rc = -EINVAL;
576 goto exit;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200577 }
578
579 skb_pull(resp, size);
580
581 rc = nfc_tm_data_received(ddev->nfc_dev, resp);
582
583exit:
584 if (rc)
585 kfree_skb(resp);
586}
587
588int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
589{
590 struct digital_dep_req_res *dep_res;
591
592 skb_push(skb, sizeof(struct digital_dep_req_res));
593 dep_res = (struct digital_dep_req_res *)skb->data;
594
595 dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
596 dep_res->cmd = DIGITAL_CMD_DEP_RES;
597 dep_res->pfb = ddev->curr_nfc_dep_pni;
598
599 digital_skb_push_dep_sod(ddev, skb);
600
601 ddev->skb_add_crc(skb);
602
603 return digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
604 NULL);
605}
606
607static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,
608 void *arg, struct sk_buff *resp)
609{
Thierry Escande67af1d72014-01-02 11:58:13 +0100610 u8 rf_tech = (unsigned long)arg;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200611
612 if (IS_ERR(resp))
613 return;
614
Thierry Escandeb711ad52014-01-06 23:34:48 +0100615 digital_tg_set_rf_tech(ddev, rf_tech);
616
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200617 digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
618
619 digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL);
620
621 dev_kfree_skb(resp);
622}
623
624static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did,
625 u8 rf_tech)
626{
627 struct digital_psl_res *psl_res;
628 struct sk_buff *skb;
629 int rc;
630
631 skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res));
632 if (!skb)
633 return -ENOMEM;
634
635 skb_put(skb, sizeof(struct digital_psl_res));
636
637 psl_res = (struct digital_psl_res *)skb->data;
638
639 psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
640 psl_res->cmd = DIGITAL_CMD_PSL_RES;
641 psl_res->did = did;
642
643 digital_skb_push_dep_sod(ddev, skb);
644
645 ddev->skb_add_crc(skb);
646
647 rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
Thierry Escande67af1d72014-01-02 11:58:13 +0100648 (void *)(unsigned long)rf_tech);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200649 if (rc)
650 kfree_skb(skb);
651
652 return rc;
653}
654
655static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg,
656 struct sk_buff *resp)
657{
658 int rc;
659 struct digital_psl_req *psl_req;
660 u8 rf_tech;
661 u8 dsi;
662
663 if (IS_ERR(resp)) {
664 rc = PTR_ERR(resp);
665 resp = NULL;
666 goto exit;
667 }
668
669 rc = ddev->skb_check_crc(resp);
670 if (rc) {
671 PROTOCOL_ERR("14.4.1.6");
672 goto exit;
673 }
674
675 rc = digital_skb_pull_dep_sod(ddev, resp);
676 if (rc) {
677 PROTOCOL_ERR("14.4.1.2");
678 goto exit;
679 }
680
681 psl_req = (struct digital_psl_req *)resp->data;
682
683 if (resp->len != sizeof(struct digital_psl_req) ||
684 psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
685 psl_req->cmd != DIGITAL_CMD_PSL_REQ) {
686 rc = -EIO;
687 goto exit;
688 }
689
690 dsi = (psl_req->brs >> 3) & 0x07;
691 switch (dsi) {
692 case 0:
693 rf_tech = NFC_DIGITAL_RF_TECH_106A;
694 break;
695 case 1:
696 rf_tech = NFC_DIGITAL_RF_TECH_212F;
697 break;
698 case 2:
699 rf_tech = NFC_DIGITAL_RF_TECH_424F;
700 break;
701 default:
Masanari Iida77d84ff2013-12-09 00:22:53 +0900702 pr_err("Unsupported dsi value %d\n", dsi);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200703 goto exit;
704 }
705
706 rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
707
708exit:
709 kfree_skb(resp);
710}
711
712static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev,
713 void *arg, struct sk_buff *resp)
714{
715 int offset;
716
717 if (IS_ERR(resp)) {
718 digital_poll_next_tech(ddev);
719 return;
720 }
721
722 offset = 2;
723 if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
724 offset++;
725
726 if (resp->data[offset] == DIGITAL_CMD_PSL_REQ)
727 digital_tg_recv_psl_req(ddev, arg, resp);
728 else
729 digital_tg_recv_dep_req(ddev, arg, resp);
730}
731
732static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,
733 struct digital_atr_req *atr_req)
734{
735 struct digital_atr_res *atr_res;
736 struct sk_buff *skb;
737 u8 *gb;
738 size_t gb_len;
739 int rc;
740
741 gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len);
742 if (!gb)
743 gb_len = 0;
744
745 skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len);
746 if (!skb)
747 return -ENOMEM;
748
749 skb_put(skb, sizeof(struct digital_atr_res));
750 atr_res = (struct digital_atr_res *)skb->data;
751
752 memset(atr_res, 0, sizeof(struct digital_atr_res));
753
754 atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
755 atr_res->cmd = DIGITAL_CMD_ATR_RES;
756 memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
757 atr_res->to = 8;
758 atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
759 if (gb_len) {
760 skb_put(skb, gb_len);
761
762 atr_res->pp |= DIGITAL_GB_BIT;
763 memcpy(atr_res->gb, gb, gb_len);
764 }
765
766 digital_skb_push_dep_sod(ddev, skb);
767
768 ddev->skb_add_crc(skb);
769
770 rc = digital_tg_send_cmd(ddev, skb, 999,
771 digital_tg_send_atr_res_complete, NULL);
Mark A. Greerb15829b2014-09-23 16:38:02 -0700772 if (rc)
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200773 kfree_skb(skb);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200774
775 return rc;
776}
777
778void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg,
779 struct sk_buff *resp)
780{
781 int rc;
782 struct digital_atr_req *atr_req;
783 size_t gb_len, min_size;
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700784 u8 poll_tech_count;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200785
786 if (IS_ERR(resp)) {
787 rc = PTR_ERR(resp);
788 resp = NULL;
789 goto exit;
790 }
791
792 if (!resp->len) {
793 rc = -EIO;
794 goto exit;
795 }
796
797 if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) {
798 min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2;
Thierry Escandeb711ad52014-01-06 23:34:48 +0100799 digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_106A);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200800 } else {
801 min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1;
Thierry Escandeb711ad52014-01-06 23:34:48 +0100802 digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_212F);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200803 }
804
805 if (resp->len < min_size) {
806 rc = -EIO;
807 goto exit;
808 }
809
Thierry Escande48e10442014-01-06 23:34:37 +0100810 ddev->curr_protocol = NFC_PROTO_NFC_DEP_MASK;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200811
812 rc = ddev->skb_check_crc(resp);
813 if (rc) {
814 PROTOCOL_ERR("14.4.1.6");
815 goto exit;
816 }
817
818 rc = digital_skb_pull_dep_sod(ddev, resp);
819 if (rc) {
820 PROTOCOL_ERR("14.4.1.2");
821 goto exit;
822 }
823
824 atr_req = (struct digital_atr_req *)resp->data;
825
826 if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
827 atr_req->cmd != DIGITAL_CMD_ATR_REQ) {
828 rc = -EINVAL;
829 goto exit;
830 }
831
832 rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
833 NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
834 if (rc)
835 goto exit;
836
837 rc = digital_tg_send_atr_res(ddev, atr_req);
838 if (rc)
839 goto exit;
840
841 gb_len = resp->len - sizeof(struct digital_atr_req);
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700842
843 poll_tech_count = ddev->poll_tech_count;
844 ddev->poll_tech_count = 0;
845
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200846 rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
847 NFC_COMM_PASSIVE, atr_req->gb, gb_len);
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700848 if (rc) {
849 ddev->poll_tech_count = poll_tech_count;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200850 goto exit;
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700851 }
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200852
853 rc = 0;
854exit:
855 if (rc)
856 digital_poll_next_tech(ddev);
857
858 dev_kfree_skb(resp);
859}