blob: f3f2b61fb5da3f3dbdf7637f0095910a1155571b [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
Mark A. Greer6ce30662014-09-23 16:38:03 -0700403 size = sizeof(struct digital_dep_req_res);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200404 dep_res = (struct digital_dep_req_res *)resp->data;
405
Mark A. Greer6ce30662014-09-23 16:38:03 -0700406 if (resp->len < size || dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN ||
Thierry Escande7d0911c2013-09-19 17:55:29 +0200407 dep_res->cmd != DIGITAL_CMD_DEP_RES) {
408 rc = -EIO;
409 goto error;
410 }
411
412 pfb = dep_res->pfb;
413
Mark A. Greer6ce30662014-09-23 16:38:03 -0700414 if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb))
415 size++;
416
417 if (size > resp->len) {
418 rc = -EIO;
419 goto error;
420 }
421
422 skb_pull(resp, size);
423
Thierry Escande7d0911c2013-09-19 17:55:29 +0200424 switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
425 case DIGITAL_NFC_DEP_PFB_I_PDU:
426 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
427 PROTOCOL_ERR("14.12.3.3");
428 rc = -EIO;
429 goto error;
430 }
431
432 ddev->curr_nfc_dep_pni =
433 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
434 rc = 0;
435 break;
436
437 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200438 pr_err("Received a ACK/NACK PDU\n");
Thierry Escande7d0911c2013-09-19 17:55:29 +0200439 rc = -EIO;
440 goto error;
441
442 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
443 if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
444 rc = -EINVAL;
445 goto error;
446 }
447
Mark A. Greer6ce30662014-09-23 16:38:03 -0700448 rc = digital_in_send_rtox(ddev, data_exch, resp->data[0]);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200449 if (rc)
450 goto error;
451
452 kfree_skb(resp);
453 return;
454 }
455
456 if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
Samuel Ortiz26042532013-09-20 16:56:40 +0200457 pr_err("MI bit set. Chained PDU not supported\n");
Thierry Escande7d0911c2013-09-19 17:55:29 +0200458 rc = -EIO;
459 goto error;
460 }
461
Thierry Escande7d0911c2013-09-19 17:55:29 +0200462exit:
463 data_exch->cb(data_exch->cb_context, resp, rc);
464
465error:
466 kfree(data_exch);
467
468 if (rc)
469 kfree_skb(resp);
470}
471
472int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
473 struct nfc_target *target, struct sk_buff *skb,
474 struct digital_data_exch *data_exch)
475{
476 struct digital_dep_req_res *dep_req;
477
478 skb_push(skb, sizeof(struct digital_dep_req_res));
479
480 dep_req = (struct digital_dep_req_res *)skb->data;
481 dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
482 dep_req->cmd = DIGITAL_CMD_DEP_REQ;
483 dep_req->pfb = ddev->curr_nfc_dep_pni;
484
485 digital_skb_push_dep_sod(ddev, skb);
486
487 ddev->skb_add_crc(skb);
488
489 return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
490 data_exch);
491}
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200492
Thierry Escandeb711ad52014-01-06 23:34:48 +0100493static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech)
494{
495 ddev->curr_rf_tech = rf_tech;
496
497 ddev->skb_add_crc = digital_skb_add_crc_none;
498 ddev->skb_check_crc = digital_skb_check_crc_none;
499
500 if (DIGITAL_DRV_CAPS_TG_CRC(ddev))
501 return;
502
503 switch (ddev->curr_rf_tech) {
504 case NFC_DIGITAL_RF_TECH_106A:
505 ddev->skb_add_crc = digital_skb_add_crc_a;
506 ddev->skb_check_crc = digital_skb_check_crc_a;
507 break;
508
509 case NFC_DIGITAL_RF_TECH_212F:
510 case NFC_DIGITAL_RF_TECH_424F:
511 ddev->skb_add_crc = digital_skb_add_crc_f;
512 ddev->skb_check_crc = digital_skb_check_crc_f;
513 break;
514
515 default:
516 break;
517 }
518}
519
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200520static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
521 struct sk_buff *resp)
522{
523 int rc;
524 struct digital_dep_req_res *dep_req;
Mark A. Greer6ce30662014-09-23 16:38:03 -0700525 u8 pfb;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200526 size_t size;
527
528 if (IS_ERR(resp)) {
529 rc = PTR_ERR(resp);
530 resp = NULL;
531 goto exit;
532 }
533
534 rc = ddev->skb_check_crc(resp);
535 if (rc) {
536 PROTOCOL_ERR("14.4.1.6");
537 goto exit;
538 }
539
540 rc = digital_skb_pull_dep_sod(ddev, resp);
541 if (rc) {
542 PROTOCOL_ERR("14.4.1.2");
543 goto exit;
544 }
545
546 size = sizeof(struct digital_dep_req_res);
547 dep_req = (struct digital_dep_req_res *)resp->data;
548
549 if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
550 dep_req->cmd != DIGITAL_CMD_DEP_REQ) {
551 rc = -EIO;
552 goto exit;
553 }
554
Mark A. Greer6ce30662014-09-23 16:38:03 -0700555 pfb = dep_req->pfb;
556
557 if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb))
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200558 size++;
559
Mark A. Greer6ce30662014-09-23 16:38:03 -0700560 if (size > resp->len) {
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200561 rc = -EIO;
562 goto exit;
563 }
564
Mark A. Greer6ce30662014-09-23 16:38:03 -0700565 skb_pull(resp, size);
566
567 switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200568 case DIGITAL_NFC_DEP_PFB_I_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200569 pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
Mark A. Greer6ce30662014-09-23 16:38:03 -0700570 ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(pfb);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200571 break;
572 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200573 pr_err("Received a ACK/NACK PDU\n");
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200574 rc = -EINVAL;
575 goto exit;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200576 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200577 pr_err("Received a SUPERVISOR PDU\n");
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200578 rc = -EINVAL;
579 goto exit;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200580 }
581
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200582 rc = nfc_tm_data_received(ddev->nfc_dev, resp);
583
584exit:
585 if (rc)
586 kfree_skb(resp);
587}
588
589int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
590{
591 struct digital_dep_req_res *dep_res;
592
593 skb_push(skb, sizeof(struct digital_dep_req_res));
594 dep_res = (struct digital_dep_req_res *)skb->data;
595
596 dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
597 dep_res->cmd = DIGITAL_CMD_DEP_RES;
598 dep_res->pfb = ddev->curr_nfc_dep_pni;
599
600 digital_skb_push_dep_sod(ddev, skb);
601
602 ddev->skb_add_crc(skb);
603
604 return digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
605 NULL);
606}
607
608static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,
609 void *arg, struct sk_buff *resp)
610{
Thierry Escande67af1d72014-01-02 11:58:13 +0100611 u8 rf_tech = (unsigned long)arg;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200612
613 if (IS_ERR(resp))
614 return;
615
Thierry Escandeb711ad52014-01-06 23:34:48 +0100616 digital_tg_set_rf_tech(ddev, rf_tech);
617
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200618 digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
619
620 digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL);
621
622 dev_kfree_skb(resp);
623}
624
625static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did,
626 u8 rf_tech)
627{
628 struct digital_psl_res *psl_res;
629 struct sk_buff *skb;
630 int rc;
631
632 skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res));
633 if (!skb)
634 return -ENOMEM;
635
636 skb_put(skb, sizeof(struct digital_psl_res));
637
638 psl_res = (struct digital_psl_res *)skb->data;
639
640 psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
641 psl_res->cmd = DIGITAL_CMD_PSL_RES;
642 psl_res->did = did;
643
644 digital_skb_push_dep_sod(ddev, skb);
645
646 ddev->skb_add_crc(skb);
647
648 rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
Thierry Escande67af1d72014-01-02 11:58:13 +0100649 (void *)(unsigned long)rf_tech);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200650 if (rc)
651 kfree_skb(skb);
652
653 return rc;
654}
655
656static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg,
657 struct sk_buff *resp)
658{
659 int rc;
660 struct digital_psl_req *psl_req;
661 u8 rf_tech;
662 u8 dsi;
663
664 if (IS_ERR(resp)) {
665 rc = PTR_ERR(resp);
666 resp = NULL;
667 goto exit;
668 }
669
670 rc = ddev->skb_check_crc(resp);
671 if (rc) {
672 PROTOCOL_ERR("14.4.1.6");
673 goto exit;
674 }
675
676 rc = digital_skb_pull_dep_sod(ddev, resp);
677 if (rc) {
678 PROTOCOL_ERR("14.4.1.2");
679 goto exit;
680 }
681
682 psl_req = (struct digital_psl_req *)resp->data;
683
684 if (resp->len != sizeof(struct digital_psl_req) ||
685 psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
686 psl_req->cmd != DIGITAL_CMD_PSL_REQ) {
687 rc = -EIO;
688 goto exit;
689 }
690
691 dsi = (psl_req->brs >> 3) & 0x07;
692 switch (dsi) {
693 case 0:
694 rf_tech = NFC_DIGITAL_RF_TECH_106A;
695 break;
696 case 1:
697 rf_tech = NFC_DIGITAL_RF_TECH_212F;
698 break;
699 case 2:
700 rf_tech = NFC_DIGITAL_RF_TECH_424F;
701 break;
702 default:
Masanari Iida77d84ff2013-12-09 00:22:53 +0900703 pr_err("Unsupported dsi value %d\n", dsi);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200704 goto exit;
705 }
706
707 rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
708
709exit:
710 kfree_skb(resp);
711}
712
713static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev,
714 void *arg, struct sk_buff *resp)
715{
716 int offset;
717
718 if (IS_ERR(resp)) {
719 digital_poll_next_tech(ddev);
720 return;
721 }
722
723 offset = 2;
724 if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
725 offset++;
726
727 if (resp->data[offset] == DIGITAL_CMD_PSL_REQ)
728 digital_tg_recv_psl_req(ddev, arg, resp);
729 else
730 digital_tg_recv_dep_req(ddev, arg, resp);
731}
732
733static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,
734 struct digital_atr_req *atr_req)
735{
736 struct digital_atr_res *atr_res;
737 struct sk_buff *skb;
738 u8 *gb;
739 size_t gb_len;
740 int rc;
741
742 gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len);
743 if (!gb)
744 gb_len = 0;
745
746 skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len);
747 if (!skb)
748 return -ENOMEM;
749
750 skb_put(skb, sizeof(struct digital_atr_res));
751 atr_res = (struct digital_atr_res *)skb->data;
752
753 memset(atr_res, 0, sizeof(struct digital_atr_res));
754
755 atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
756 atr_res->cmd = DIGITAL_CMD_ATR_RES;
757 memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
758 atr_res->to = 8;
759 atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
760 if (gb_len) {
761 skb_put(skb, gb_len);
762
763 atr_res->pp |= DIGITAL_GB_BIT;
764 memcpy(atr_res->gb, gb, gb_len);
765 }
766
767 digital_skb_push_dep_sod(ddev, skb);
768
769 ddev->skb_add_crc(skb);
770
771 rc = digital_tg_send_cmd(ddev, skb, 999,
772 digital_tg_send_atr_res_complete, NULL);
Mark A. Greerb15829b2014-09-23 16:38:02 -0700773 if (rc)
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200774 kfree_skb(skb);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200775
776 return rc;
777}
778
779void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg,
780 struct sk_buff *resp)
781{
782 int rc;
783 struct digital_atr_req *atr_req;
784 size_t gb_len, min_size;
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700785 u8 poll_tech_count;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200786
787 if (IS_ERR(resp)) {
788 rc = PTR_ERR(resp);
789 resp = NULL;
790 goto exit;
791 }
792
793 if (!resp->len) {
794 rc = -EIO;
795 goto exit;
796 }
797
798 if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) {
799 min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2;
Thierry Escandeb711ad52014-01-06 23:34:48 +0100800 digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_106A);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200801 } else {
802 min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1;
Thierry Escandeb711ad52014-01-06 23:34:48 +0100803 digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_212F);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200804 }
805
806 if (resp->len < min_size) {
807 rc = -EIO;
808 goto exit;
809 }
810
Thierry Escande48e10442014-01-06 23:34:37 +0100811 ddev->curr_protocol = NFC_PROTO_NFC_DEP_MASK;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200812
813 rc = ddev->skb_check_crc(resp);
814 if (rc) {
815 PROTOCOL_ERR("14.4.1.6");
816 goto exit;
817 }
818
819 rc = digital_skb_pull_dep_sod(ddev, resp);
820 if (rc) {
821 PROTOCOL_ERR("14.4.1.2");
822 goto exit;
823 }
824
825 atr_req = (struct digital_atr_req *)resp->data;
826
827 if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
828 atr_req->cmd != DIGITAL_CMD_ATR_REQ) {
829 rc = -EINVAL;
830 goto exit;
831 }
832
833 rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
834 NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
835 if (rc)
836 goto exit;
837
838 rc = digital_tg_send_atr_res(ddev, atr_req);
839 if (rc)
840 goto exit;
841
842 gb_len = resp->len - sizeof(struct digital_atr_req);
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700843
844 poll_tech_count = ddev->poll_tech_count;
845 ddev->poll_tech_count = 0;
846
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200847 rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
848 NFC_COMM_PASSIVE, atr_req->gb, gb_len);
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700849 if (rc) {
850 ddev->poll_tech_count = poll_tech_count;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200851 goto exit;
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700852 }
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200853
854 rc = 0;
855exit:
856 if (rc)
857 digital_poll_next_tech(ddev);
858
859 dev_kfree_skb(resp);
860}