aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2014-01-26 18:31:31 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2014-02-16 17:49:54 -0500
commit12e3d241e42956da168fd499347855af799f62fb (patch)
tree8308212156ce23e3778c7745d58bc8a9583dca76 /net
parentd3815ea95c67e62a2c651e7b5b4e08e95a4cbb13 (diff)
NFC: digital: Add poll support for type 4A tag platform
This adds support for ATS request and response handling for type 4A tag activation. Signed-off-by: Thierry Escande <thierry.escande@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/nfc/digital_core.c7
-rw-r--r--net/nfc/digital_technology.c81
2 files changed, 86 insertions, 2 deletions
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c
index 48906ca60540..e1f240266adf 100644
--- a/net/nfc/digital_core.c
+++ b/net/nfc/digital_core.c
@@ -337,6 +337,11 @@ int digital_target_found(struct nfc_digital_dev *ddev,
337 framing = NFC_DIGITAL_FRAMING_ISO15693_TVT; 337 framing = NFC_DIGITAL_FRAMING_ISO15693_TVT;
338 check_crc = digital_skb_check_crc_b; 338 check_crc = digital_skb_check_crc_b;
339 add_crc = digital_skb_add_crc_b; 339 add_crc = digital_skb_add_crc_b;
340
341 case NFC_PROTO_ISO14443:
342 framing = NFC_DIGITAL_FRAMING_NFCA_T4T;
343 check_crc = digital_skb_check_crc_a;
344 add_crc = digital_skb_add_crc_a;
340 break; 345 break;
341 346
342 default: 347 default:
@@ -714,6 +719,8 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops,
714 ddev->protocols |= NFC_PROTO_NFC_DEP_MASK; 719 ddev->protocols |= NFC_PROTO_NFC_DEP_MASK;
715 if (supported_protocols & NFC_PROTO_ISO15693_MASK) 720 if (supported_protocols & NFC_PROTO_ISO15693_MASK)
716 ddev->protocols |= NFC_PROTO_ISO15693_MASK; 721 ddev->protocols |= NFC_PROTO_ISO15693_MASK;
722 if (supported_protocols & NFC_PROTO_ISO14443_MASK)
723 ddev->protocols |= NFC_PROTO_ISO14443_MASK;
717 724
718 ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; 725 ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN;
719 ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; 726 ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN;
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c
index 97d3f602fc06..6649d9461dff 100644
--- a/net/nfc/digital_technology.c
+++ b/net/nfc/digital_technology.c
@@ -30,6 +30,7 @@
30 30
31#define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) 31#define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04))
32#define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) 32#define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60))
33#define DIGITAL_SEL_RES_IS_T4T(sel_res) ((sel_res) & 0x20)
33#define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) 34#define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40)
34 35
35#define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) 36#define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00)
@@ -60,6 +61,16 @@
60#define DIGITAL_ISO15693_RES_IS_VALID(flags) \ 61#define DIGITAL_ISO15693_RES_IS_VALID(flags) \
61 (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR)) 62 (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR))
62 63
64static const u8 digital_ats_fsc[] = {
65 16, 24, 32, 40, 48, 64, 96, 128,
66};
67
68#define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F)
69#define DIGITAL_ATS_MAX_FSC 256
70
71#define DIGITAL_RATS_BYTE1 0xE0
72#define DIGITAL_RATS_PARAM 0x80
73
63struct digital_sdd_res { 74struct digital_sdd_res {
64 u8 nfcid1[4]; 75 u8 nfcid1[4];
65 u8 bcc; 76 u8 bcc;
@@ -107,6 +118,63 @@ struct digital_iso15693_inv_res {
107static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, 118static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
108 struct nfc_target *target); 119 struct nfc_target *target);
109 120
121static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg,
122 struct sk_buff *resp)
123{
124 struct nfc_target *target = arg;
125 u8 fsdi;
126 int rc;
127
128 if (IS_ERR(resp)) {
129 rc = PTR_ERR(resp);
130 resp = NULL;
131 goto exit;
132 }
133
134 if (resp->len < 2) {
135 rc = -EIO;
136 goto exit;
137 }
138
139 fsdi = DIGITAL_ATS_FSCI(resp->data[1]);
140 if (fsdi >= 8)
141 ddev->target_fsc = DIGITAL_ATS_MAX_FSC;
142 else
143 ddev->target_fsc = digital_ats_fsc[fsdi];
144
145 ddev->curr_nfc_dep_pni = 0;
146
147 rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443);
148
149exit:
150 dev_kfree_skb(resp);
151 kfree(target);
152
153 if (rc)
154 digital_poll_next_tech(ddev);
155}
156
157static int digital_in_send_rats(struct nfc_digital_dev *ddev,
158 struct nfc_target *target)
159{
160 int rc;
161 struct sk_buff *skb;
162
163 skb = digital_skb_alloc(ddev, 2);
164 if (!skb)
165 return -ENOMEM;
166
167 *skb_put(skb, 1) = DIGITAL_RATS_BYTE1;
168 *skb_put(skb, 1) = DIGITAL_RATS_PARAM;
169
170 rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_ats,
171 target);
172 if (rc)
173 kfree_skb(skb);
174
175 return rc;
176}
177
110static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, 178static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
111 struct sk_buff *resp) 179 struct sk_buff *resp)
112{ 180{
@@ -144,8 +212,19 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
144 goto exit_free_skb; 212 goto exit_free_skb;
145 } 213 }
146 214
215 target->sel_res = sel_res;
216
147 if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { 217 if (DIGITAL_SEL_RES_IS_T2T(sel_res)) {
148 nfc_proto = NFC_PROTO_MIFARE; 218 nfc_proto = NFC_PROTO_MIFARE;
219 } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) {
220 rc = digital_in_send_rats(ddev, target);
221 if (rc)
222 goto exit;
223 /*
224 * Skip target_found and don't free it for now. This will be
225 * done when receiving the ATS
226 */
227 goto exit_free_skb;
149 } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { 228 } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) {
150 nfc_proto = NFC_PROTO_NFC_DEP; 229 nfc_proto = NFC_PROTO_NFC_DEP;
151 } else { 230 } else {
@@ -153,8 +232,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
153 goto exit; 232 goto exit;
154 } 233 }
155 234
156 target->sel_res = sel_res;
157
158 rc = digital_target_found(ddev, target, nfc_proto); 235 rc = digital_target_found(ddev, target, nfc_proto);
159 236
160exit: 237exit: