blob: d07c9ab993c83ac11770471e60cf6a4fecf9900f [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. Greer3bc3f882014-09-23 16:38:04 -0700414 if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
415 PROTOCOL_ERR("14.8.2.1");
416 rc = -EIO;
417 goto error;
418 }
Mark A. Greer6ce30662014-09-23 16:38:03 -0700419
420 if (size > resp->len) {
421 rc = -EIO;
422 goto error;
423 }
424
425 skb_pull(resp, size);
426
Thierry Escande7d0911c2013-09-19 17:55:29 +0200427 switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
428 case DIGITAL_NFC_DEP_PFB_I_PDU:
429 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
430 PROTOCOL_ERR("14.12.3.3");
431 rc = -EIO;
432 goto error;
433 }
434
435 ddev->curr_nfc_dep_pni =
436 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
437 rc = 0;
438 break;
439
440 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200441 pr_err("Received a ACK/NACK PDU\n");
Thierry Escande7d0911c2013-09-19 17:55:29 +0200442 rc = -EIO;
443 goto error;
444
445 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
446 if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
447 rc = -EINVAL;
448 goto error;
449 }
450
Mark A. Greer6ce30662014-09-23 16:38:03 -0700451 rc = digital_in_send_rtox(ddev, data_exch, resp->data[0]);
Thierry Escande7d0911c2013-09-19 17:55:29 +0200452 if (rc)
453 goto error;
454
455 kfree_skb(resp);
456 return;
457 }
458
459 if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
Samuel Ortiz26042532013-09-20 16:56:40 +0200460 pr_err("MI bit set. Chained PDU not supported\n");
Thierry Escande7d0911c2013-09-19 17:55:29 +0200461 rc = -EIO;
462 goto error;
463 }
464
Thierry Escande7d0911c2013-09-19 17:55:29 +0200465exit:
466 data_exch->cb(data_exch->cb_context, resp, rc);
467
468error:
469 kfree(data_exch);
470
471 if (rc)
472 kfree_skb(resp);
473}
474
475int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
476 struct nfc_target *target, struct sk_buff *skb,
477 struct digital_data_exch *data_exch)
478{
479 struct digital_dep_req_res *dep_req;
480
481 skb_push(skb, sizeof(struct digital_dep_req_res));
482
483 dep_req = (struct digital_dep_req_res *)skb->data;
484 dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
485 dep_req->cmd = DIGITAL_CMD_DEP_REQ;
486 dep_req->pfb = ddev->curr_nfc_dep_pni;
487
488 digital_skb_push_dep_sod(ddev, skb);
489
490 ddev->skb_add_crc(skb);
491
492 return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
493 data_exch);
494}
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200495
Thierry Escandeb711ad52014-01-06 23:34:48 +0100496static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech)
497{
498 ddev->curr_rf_tech = rf_tech;
499
500 ddev->skb_add_crc = digital_skb_add_crc_none;
501 ddev->skb_check_crc = digital_skb_check_crc_none;
502
503 if (DIGITAL_DRV_CAPS_TG_CRC(ddev))
504 return;
505
506 switch (ddev->curr_rf_tech) {
507 case NFC_DIGITAL_RF_TECH_106A:
508 ddev->skb_add_crc = digital_skb_add_crc_a;
509 ddev->skb_check_crc = digital_skb_check_crc_a;
510 break;
511
512 case NFC_DIGITAL_RF_TECH_212F:
513 case NFC_DIGITAL_RF_TECH_424F:
514 ddev->skb_add_crc = digital_skb_add_crc_f;
515 ddev->skb_check_crc = digital_skb_check_crc_f;
516 break;
517
518 default:
519 break;
520 }
521}
522
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200523static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
524 struct sk_buff *resp)
525{
526 int rc;
527 struct digital_dep_req_res *dep_req;
Mark A. Greer6ce30662014-09-23 16:38:03 -0700528 u8 pfb;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200529 size_t size;
530
531 if (IS_ERR(resp)) {
532 rc = PTR_ERR(resp);
533 resp = NULL;
534 goto exit;
535 }
536
537 rc = ddev->skb_check_crc(resp);
538 if (rc) {
539 PROTOCOL_ERR("14.4.1.6");
540 goto exit;
541 }
542
543 rc = digital_skb_pull_dep_sod(ddev, resp);
544 if (rc) {
545 PROTOCOL_ERR("14.4.1.2");
546 goto exit;
547 }
548
549 size = sizeof(struct digital_dep_req_res);
550 dep_req = (struct digital_dep_req_res *)resp->data;
551
552 if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
553 dep_req->cmd != DIGITAL_CMD_DEP_REQ) {
554 rc = -EIO;
555 goto exit;
556 }
557
Mark A. Greer6ce30662014-09-23 16:38:03 -0700558 pfb = dep_req->pfb;
559
560 if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb))
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200561 size++;
562
Mark A. Greer6ce30662014-09-23 16:38:03 -0700563 if (size > resp->len) {
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200564 rc = -EIO;
565 goto exit;
566 }
567
Mark A. Greer6ce30662014-09-23 16:38:03 -0700568 skb_pull(resp, size);
569
570 switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200571 case DIGITAL_NFC_DEP_PFB_I_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200572 pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
Mark A. Greer6ce30662014-09-23 16:38:03 -0700573 ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(pfb);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200574 break;
575 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200576 pr_err("Received a ACK/NACK PDU\n");
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200577 rc = -EINVAL;
578 goto exit;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200579 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
Samuel Ortiz26042532013-09-20 16:56:40 +0200580 pr_err("Received a SUPERVISOR PDU\n");
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200581 rc = -EINVAL;
582 goto exit;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200583 }
584
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200585 rc = nfc_tm_data_received(ddev->nfc_dev, resp);
586
587exit:
588 if (rc)
589 kfree_skb(resp);
590}
591
592int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
593{
594 struct digital_dep_req_res *dep_res;
595
596 skb_push(skb, sizeof(struct digital_dep_req_res));
597 dep_res = (struct digital_dep_req_res *)skb->data;
598
599 dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
600 dep_res->cmd = DIGITAL_CMD_DEP_RES;
601 dep_res->pfb = ddev->curr_nfc_dep_pni;
602
603 digital_skb_push_dep_sod(ddev, skb);
604
605 ddev->skb_add_crc(skb);
606
607 return digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
608 NULL);
609}
610
611static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,
612 void *arg, struct sk_buff *resp)
613{
Thierry Escande67af1d72014-01-02 11:58:13 +0100614 u8 rf_tech = (unsigned long)arg;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200615
616 if (IS_ERR(resp))
617 return;
618
Thierry Escandeb711ad52014-01-06 23:34:48 +0100619 digital_tg_set_rf_tech(ddev, rf_tech);
620
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200621 digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
622
623 digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL);
624
625 dev_kfree_skb(resp);
626}
627
628static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did,
629 u8 rf_tech)
630{
631 struct digital_psl_res *psl_res;
632 struct sk_buff *skb;
633 int rc;
634
635 skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res));
636 if (!skb)
637 return -ENOMEM;
638
639 skb_put(skb, sizeof(struct digital_psl_res));
640
641 psl_res = (struct digital_psl_res *)skb->data;
642
643 psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
644 psl_res->cmd = DIGITAL_CMD_PSL_RES;
645 psl_res->did = did;
646
647 digital_skb_push_dep_sod(ddev, skb);
648
649 ddev->skb_add_crc(skb);
650
651 rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
Thierry Escande67af1d72014-01-02 11:58:13 +0100652 (void *)(unsigned long)rf_tech);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200653 if (rc)
654 kfree_skb(skb);
655
656 return rc;
657}
658
659static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg,
660 struct sk_buff *resp)
661{
662 int rc;
663 struct digital_psl_req *psl_req;
664 u8 rf_tech;
665 u8 dsi;
666
667 if (IS_ERR(resp)) {
668 rc = PTR_ERR(resp);
669 resp = NULL;
670 goto exit;
671 }
672
673 rc = ddev->skb_check_crc(resp);
674 if (rc) {
675 PROTOCOL_ERR("14.4.1.6");
676 goto exit;
677 }
678
679 rc = digital_skb_pull_dep_sod(ddev, resp);
680 if (rc) {
681 PROTOCOL_ERR("14.4.1.2");
682 goto exit;
683 }
684
685 psl_req = (struct digital_psl_req *)resp->data;
686
687 if (resp->len != sizeof(struct digital_psl_req) ||
688 psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
689 psl_req->cmd != DIGITAL_CMD_PSL_REQ) {
690 rc = -EIO;
691 goto exit;
692 }
693
694 dsi = (psl_req->brs >> 3) & 0x07;
695 switch (dsi) {
696 case 0:
697 rf_tech = NFC_DIGITAL_RF_TECH_106A;
698 break;
699 case 1:
700 rf_tech = NFC_DIGITAL_RF_TECH_212F;
701 break;
702 case 2:
703 rf_tech = NFC_DIGITAL_RF_TECH_424F;
704 break;
705 default:
Masanari Iida77d84ff2013-12-09 00:22:53 +0900706 pr_err("Unsupported dsi value %d\n", dsi);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200707 goto exit;
708 }
709
710 rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
711
712exit:
713 kfree_skb(resp);
714}
715
716static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev,
717 void *arg, struct sk_buff *resp)
718{
719 int offset;
720
721 if (IS_ERR(resp)) {
722 digital_poll_next_tech(ddev);
723 return;
724 }
725
726 offset = 2;
727 if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
728 offset++;
729
730 if (resp->data[offset] == DIGITAL_CMD_PSL_REQ)
731 digital_tg_recv_psl_req(ddev, arg, resp);
732 else
733 digital_tg_recv_dep_req(ddev, arg, resp);
734}
735
736static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,
737 struct digital_atr_req *atr_req)
738{
739 struct digital_atr_res *atr_res;
740 struct sk_buff *skb;
741 u8 *gb;
742 size_t gb_len;
743 int rc;
744
745 gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len);
746 if (!gb)
747 gb_len = 0;
748
749 skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len);
750 if (!skb)
751 return -ENOMEM;
752
753 skb_put(skb, sizeof(struct digital_atr_res));
754 atr_res = (struct digital_atr_res *)skb->data;
755
756 memset(atr_res, 0, sizeof(struct digital_atr_res));
757
758 atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
759 atr_res->cmd = DIGITAL_CMD_ATR_RES;
760 memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
761 atr_res->to = 8;
762 atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
763 if (gb_len) {
764 skb_put(skb, gb_len);
765
766 atr_res->pp |= DIGITAL_GB_BIT;
767 memcpy(atr_res->gb, gb, gb_len);
768 }
769
770 digital_skb_push_dep_sod(ddev, skb);
771
772 ddev->skb_add_crc(skb);
773
774 rc = digital_tg_send_cmd(ddev, skb, 999,
775 digital_tg_send_atr_res_complete, NULL);
Mark A. Greerb15829b2014-09-23 16:38:02 -0700776 if (rc)
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200777 kfree_skb(skb);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200778
779 return rc;
780}
781
782void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg,
783 struct sk_buff *resp)
784{
785 int rc;
786 struct digital_atr_req *atr_req;
787 size_t gb_len, min_size;
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700788 u8 poll_tech_count;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200789
790 if (IS_ERR(resp)) {
791 rc = PTR_ERR(resp);
792 resp = NULL;
793 goto exit;
794 }
795
796 if (!resp->len) {
797 rc = -EIO;
798 goto exit;
799 }
800
801 if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) {
802 min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2;
Thierry Escandeb711ad52014-01-06 23:34:48 +0100803 digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_106A);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200804 } else {
805 min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1;
Thierry Escandeb711ad52014-01-06 23:34:48 +0100806 digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_212F);
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200807 }
808
809 if (resp->len < min_size) {
810 rc = -EIO;
811 goto exit;
812 }
813
Thierry Escande48e10442014-01-06 23:34:37 +0100814 ddev->curr_protocol = NFC_PROTO_NFC_DEP_MASK;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200815
816 rc = ddev->skb_check_crc(resp);
817 if (rc) {
818 PROTOCOL_ERR("14.4.1.6");
819 goto exit;
820 }
821
822 rc = digital_skb_pull_dep_sod(ddev, resp);
823 if (rc) {
824 PROTOCOL_ERR("14.4.1.2");
825 goto exit;
826 }
827
828 atr_req = (struct digital_atr_req *)resp->data;
829
830 if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
831 atr_req->cmd != DIGITAL_CMD_ATR_REQ) {
832 rc = -EINVAL;
833 goto exit;
834 }
835
836 rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
837 NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
838 if (rc)
839 goto exit;
840
841 rc = digital_tg_send_atr_res(ddev, atr_req);
842 if (rc)
843 goto exit;
844
845 gb_len = resp->len - sizeof(struct digital_atr_req);
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700846
847 poll_tech_count = ddev->poll_tech_count;
848 ddev->poll_tech_count = 0;
849
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200850 rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
851 NFC_COMM_PASSIVE, atr_req->gb, gb_len);
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700852 if (rc) {
853 ddev->poll_tech_count = poll_tech_count;
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200854 goto exit;
Mark A. Greer0529a7a2014-07-02 09:03:49 -0700855 }
Thierry Escande1c7a4c22013-09-19 17:55:30 +0200856
857 rc = 0;
858exit:
859 if (rc)
860 digital_poll_next_tech(ddev);
861
862 dev_kfree_skb(resp);
863}