aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2013-09-19 11:55:28 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-09-24 20:02:25 -0400
commit8c0695e4998dd268ff2a05951961247b7e015651 (patch)
tree86087518d7435dbe788647ee04be2b460bab0ee8
parent2c66daecc4092e6049673c281b2e6f0d5e59a94c (diff)
NFC Digital: Add NFC-F technology support
This adds polling support for NFC-F technology at 212 kbits/s and 424 kbits/s. A user space application like neard can send type 3 tag commands through the NFC core. Process flow for NFC-F detection is as follow: 1 - The digital stack sends the SENSF_REQ command to the NFC device. 2 - A peer device replies with a SENSF_RES response. 3 - The digital stack notifies the NFC core of the presence of a target in the operation field and passes the target NFCID2. This also adds support for CRC calculation of type CRC-F. The CRC calculation is handled by the digital stack if the NFC device doesn't support it. Signed-off-by: Thierry Escande <thierry.escande@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--net/nfc/Kconfig1
-rw-r--r--net/nfc/digital.h13
-rw-r--r--net/nfc/digital_core.c18
-rw-r--r--net/nfc/digital_technology.c121
4 files changed, 153 insertions, 0 deletions
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig
index 4f4d2481325a..6e0fa0cce198 100644
--- a/net/nfc/Kconfig
+++ b/net/nfc/Kconfig
@@ -17,6 +17,7 @@ menuconfig NFC
17config NFC_DIGITAL 17config NFC_DIGITAL
18 depends on NFC 18 depends on NFC
19 select CRC_CCITT 19 select CRC_CCITT
20 select CRC_ITU_T
20 tristate "NFC Digital Protocol stack support" 21 tristate "NFC Digital Protocol stack support"
21 default n 22 default n
22 help 23 help
diff --git a/net/nfc/digital.h b/net/nfc/digital.h
index fb5324b792de..85bc74c988f8 100644
--- a/net/nfc/digital.h
+++ b/net/nfc/digital.h
@@ -20,6 +20,7 @@
20#include <net/nfc/digital.h> 20#include <net/nfc/digital.h>
21 21
22#include <linux/crc-ccitt.h> 22#include <linux/crc-ccitt.h>
23#include <linux/crc-itu-t.h>
23 24
24#define PR_DBG(fmt, ...) pr_debug("%s: " fmt "\n", __func__, ##__VA_ARGS__) 25#define PR_DBG(fmt, ...) pr_debug("%s: " fmt "\n", __func__, ##__VA_ARGS__)
25#define PR_ERR(fmt, ...) pr_err("%s: " fmt "\n", __func__, ##__VA_ARGS__) 26#define PR_ERR(fmt, ...) pr_err("%s: " fmt "\n", __func__, ##__VA_ARGS__)
@@ -64,6 +65,7 @@ static inline int digital_in_send_cmd(struct nfc_digital_dev *ddev,
64void digital_poll_next_tech(struct nfc_digital_dev *ddev); 65void digital_poll_next_tech(struct nfc_digital_dev *ddev);
65 66
66int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); 67int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech);
68int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech);
67 69
68int digital_target_found(struct nfc_digital_dev *ddev, 70int digital_target_found(struct nfc_digital_dev *ddev,
69 struct nfc_target *target, u8 protocol); 71 struct nfc_target *target, u8 protocol);
@@ -74,6 +76,7 @@ typedef u16 (*crc_func_t)(u16, const u8 *, size_t);
74 76
75#define CRC_A_INIT 0x6363 77#define CRC_A_INIT 0x6363
76#define CRC_B_INIT 0xFFFF 78#define CRC_B_INIT 0xFFFF
79#define CRC_F_INIT 0x0000
77 80
78void digital_skb_add_crc(struct sk_buff *skb, crc_func_t crc_func, u16 init, 81void digital_skb_add_crc(struct sk_buff *skb, crc_func_t crc_func, u16 init,
79 u8 bitwise_inv, u8 msb_first); 82 u8 bitwise_inv, u8 msb_first);
@@ -88,6 +91,11 @@ static inline void digital_skb_add_crc_b(struct sk_buff *skb)
88 digital_skb_add_crc(skb, crc_ccitt, CRC_B_INIT, 1, 0); 91 digital_skb_add_crc(skb, crc_ccitt, CRC_B_INIT, 1, 0);
89} 92}
90 93
94static inline void digital_skb_add_crc_f(struct sk_buff *skb)
95{
96 digital_skb_add_crc(skb, crc_itu_t, CRC_F_INIT, 0, 1);
97}
98
91static inline void digital_skb_add_crc_none(struct sk_buff *skb) 99static inline void digital_skb_add_crc_none(struct sk_buff *skb)
92{ 100{
93 return; 101 return;
@@ -106,6 +114,11 @@ static inline int digital_skb_check_crc_b(struct sk_buff *skb)
106 return digital_skb_check_crc(skb, crc_ccitt, CRC_B_INIT, 1, 0); 114 return digital_skb_check_crc(skb, crc_ccitt, CRC_B_INIT, 1, 0);
107} 115}
108 116
117static inline int digital_skb_check_crc_f(struct sk_buff *skb)
118{
119 return digital_skb_check_crc(skb, crc_itu_t, CRC_F_INIT, 0, 1);
120}
121
109static inline int digital_skb_check_crc_none(struct sk_buff *skb) 122static inline int digital_skb_check_crc_none(struct sk_buff *skb)
110{ 123{
111 return 0; 124 return 0;
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c
index 4b3ceb45834b..25e5bcb946e0 100644
--- a/net/nfc/digital_core.c
+++ b/net/nfc/digital_core.c
@@ -20,6 +20,8 @@
20#define DIGITAL_PROTO_NFCA_RF_TECH \ 20#define DIGITAL_PROTO_NFCA_RF_TECH \
21 (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK) 21 (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK)
22 22
23#define DIGITAL_PROTO_NFCF_RF_TECH (NFC_PROTO_FELICA_MASK)
24
23struct digital_cmd { 25struct digital_cmd {
24 struct list_head queue; 26 struct list_head queue;
25 27
@@ -252,6 +254,12 @@ int digital_target_found(struct nfc_digital_dev *ddev,
252 add_crc = digital_skb_add_crc_a; 254 add_crc = digital_skb_add_crc_a;
253 break; 255 break;
254 256
257 case NFC_PROTO_FELICA:
258 framing = NFC_DIGITAL_FRAMING_NFCF_T3T;
259 check_crc = digital_skb_check_crc_f;
260 add_crc = digital_skb_add_crc_f;
261 break;
262
255 default: 263 default:
256 PR_ERR("Invalid protocol %d", protocol); 264 PR_ERR("Invalid protocol %d", protocol);
257 return -EINVAL; 265 return -EINVAL;
@@ -383,6 +391,14 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols,
383 digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, 391 digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A,
384 digital_in_send_sens_req); 392 digital_in_send_sens_req);
385 393
394 if (im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) {
395 digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F,
396 digital_in_send_sensf_req);
397
398 digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_424F,
399 digital_in_send_sensf_req);
400 }
401
386 if (!ddev->poll_tech_count) { 402 if (!ddev->poll_tech_count) {
387 PR_ERR("Unsupported protocols: im=0x%x, tm=0x%x", 403 PR_ERR("Unsupported protocols: im=0x%x, tm=0x%x",
388 matching_im_protocols, matching_tm_protocols); 404 matching_im_protocols, matching_tm_protocols);
@@ -560,6 +576,8 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops,
560 ddev->protocols |= NFC_PROTO_JEWEL_MASK; 576 ddev->protocols |= NFC_PROTO_JEWEL_MASK;
561 if (supported_protocols & NFC_PROTO_MIFARE_MASK) 577 if (supported_protocols & NFC_PROTO_MIFARE_MASK)
562 ddev->protocols |= NFC_PROTO_MIFARE_MASK; 578 ddev->protocols |= NFC_PROTO_MIFARE_MASK;
579 if (supported_protocols & NFC_PROTO_FELICA_MASK)
580 ddev->protocols |= NFC_PROTO_FELICA_MASK;
563 581
564 ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; 582 ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN;
565 ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; 583 ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN;
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c
index 0cad38001c5f..bfe5ae17909e 100644
--- a/net/nfc/digital_technology.c
+++ b/net/nfc/digital_technology.c
@@ -37,6 +37,17 @@
37#define DIGITAL_MIFARE_READ_RES_LEN 16 37#define DIGITAL_MIFARE_READ_RES_LEN 16
38#define DIGITAL_MIFARE_ACK_RES 0x0A 38#define DIGITAL_MIFARE_ACK_RES 0x0A
39 39
40#define DIGITAL_CMD_SENSF_REQ 0x00
41#define DIGITAL_CMD_SENSF_RES 0x01
42
43#define DIGITAL_SENSF_RES_MIN_LENGTH 17
44#define DIGITAL_SENSF_RES_RD_AP_B1 0x00
45#define DIGITAL_SENSF_RES_RD_AP_B2 0x8F
46
47#define DIGITAL_SENSF_REQ_RC_NONE 0
48#define DIGITAL_SENSF_REQ_RC_SC 1
49#define DIGITAL_SENSF_REQ_RC_AP 2
50
40struct digital_sdd_res { 51struct digital_sdd_res {
41 u8 nfcid1[4]; 52 u8 nfcid1[4];
42 u8 bcc; 53 u8 bcc;
@@ -49,6 +60,25 @@ struct digital_sel_req {
49 u8 bcc; 60 u8 bcc;
50} __packed; 61} __packed;
51 62
63struct digital_sensf_req {
64 u8 cmd;
65 u8 sc1;
66 u8 sc2;
67 u8 rc;
68 u8 tsn;
69} __packed;
70
71struct digital_sensf_res {
72 u8 cmd;
73 u8 nfcid2[8];
74 u8 pad0[2];
75 u8 pad1[3];
76 u8 mrti_check;
77 u8 mrti_update;
78 u8 pad2;
79 u8 rd[2];
80} __packed;
81
52static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, 82static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
53 struct nfc_target *target); 83 struct nfc_target *target);
54 84
@@ -344,3 +374,94 @@ int digital_in_recv_mifare_res(struct sk_buff *resp)
344 /* NACK and any other responses are treated as error. */ 374 /* NACK and any other responses are treated as error. */
345 return -EIO; 375 return -EIO;
346} 376}
377
378static void digital_in_recv_sensf_res(struct nfc_digital_dev *ddev, void *arg,
379 struct sk_buff *resp)
380{
381 int rc;
382 struct nfc_target target;
383 struct digital_sensf_res *sensf_res;
384
385 if (IS_ERR(resp)) {
386 rc = PTR_ERR(resp);
387 resp = NULL;
388 goto exit;
389 }
390
391 if (resp->len < DIGITAL_SENSF_RES_MIN_LENGTH) {
392 rc = -EIO;
393 goto exit;
394 }
395
396 if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) {
397 rc = digital_skb_check_crc_f(resp);
398 if (rc) {
399 PROTOCOL_ERR("6.4.1.8");
400 goto exit;
401 }
402 }
403
404 skb_pull(resp, 1);
405
406 memset(&target, 0, sizeof(struct nfc_target));
407
408 sensf_res = (struct digital_sensf_res *)resp->data;
409
410 memcpy(target.sensf_res, sensf_res, resp->len);
411 target.sensf_res_len = resp->len;
412
413 memcpy(target.nfcid2, sensf_res->nfcid2, NFC_NFCID2_MAXSIZE);
414 target.nfcid2_len = NFC_NFCID2_MAXSIZE;
415
416 rc = digital_target_found(ddev, &target, NFC_PROTO_FELICA);
417
418exit:
419 dev_kfree_skb(resp);
420
421 if (rc)
422 digital_poll_next_tech(ddev);
423}
424
425int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech)
426{
427 struct digital_sensf_req *sensf_req;
428 struct sk_buff *skb;
429 int rc;
430 u8 size;
431
432 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
433 if (rc)
434 return rc;
435
436 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
437 NFC_DIGITAL_FRAMING_NFCF);
438 if (rc)
439 return rc;
440
441 size = sizeof(struct digital_sensf_req);
442
443 skb = digital_skb_alloc(ddev, size);
444 if (!skb)
445 return -ENOMEM;
446
447 skb_put(skb, size);
448
449 sensf_req = (struct digital_sensf_req *)skb->data;
450 sensf_req->cmd = DIGITAL_CMD_SENSF_REQ;
451 sensf_req->sc1 = 0xFF;
452 sensf_req->sc2 = 0xFF;
453 sensf_req->rc = 0;
454 sensf_req->tsn = 0;
455
456 *skb_push(skb, 1) = size + 1;
457
458 if (!DIGITAL_DRV_CAPS_IN_CRC(ddev))
459 digital_skb_add_crc_f(skb);
460
461 rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sensf_res,
462 NULL);
463 if (rc)
464 kfree_skb(skb);
465
466 return rc;
467}