NFC Digital: Add NFC-A technology support
[linux-block.git] / net / nfc / digital_technology.c
1 /*
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
16 #include "digital.h"
17
18 #define DIGITAL_CMD_SENS_REQ    0x26
19 #define DIGITAL_CMD_ALL_REQ     0x52
20 #define DIGITAL_CMD_SEL_REQ_CL1 0x93
21 #define DIGITAL_CMD_SEL_REQ_CL2 0x95
22 #define DIGITAL_CMD_SEL_REQ_CL3 0x97
23
24 #define DIGITAL_SDD_REQ_SEL_PAR 0x20
25
26 #define DIGITAL_SDD_RES_CT  0x88
27 #define DIGITAL_SDD_RES_LEN 5
28
29 #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04))
30 #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60))
31
32 #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x000C) == 0x000C)
33 #define DIGITAL_SENS_RES_IS_VALID(sens_res) \
34         ((!((sens_res) & 0x1F00) && (((sens_res) & 0x000C) == 0x000C)) || \
35         (((sens_res) & 0x1F00) && ((sens_res) & 0x000C) != 0x000C))
36
37 #define DIGITAL_MIFARE_READ_RES_LEN 16
38 #define DIGITAL_MIFARE_ACK_RES  0x0A
39
40 struct digital_sdd_res {
41         u8 nfcid1[4];
42         u8 bcc;
43 } __packed;
44
45 struct digital_sel_req {
46         u8 sel_cmd;
47         u8 b2;
48         u8 nfcid1[4];
49         u8 bcc;
50 } __packed;
51
52 static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
53                                    struct nfc_target *target);
54
55 static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
56                                     struct sk_buff *resp)
57 {
58         struct nfc_target *target = arg;
59         int rc;
60         u8 sel_res;
61         u8 nfc_proto;
62
63         if (IS_ERR(resp)) {
64                 rc = PTR_ERR(resp);
65                 resp = NULL;
66                 goto exit;
67         }
68
69         if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) {
70                 rc = digital_skb_check_crc_a(resp);
71                 if (rc) {
72                         PROTOCOL_ERR("4.4.1.3");
73                         goto exit;
74                 }
75         }
76
77         if (!resp->len) {
78                 rc = -EIO;
79                 goto exit;
80         }
81
82         sel_res = resp->data[0];
83
84         if (!DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res)) {
85                 rc = digital_in_send_sdd_req(ddev, target);
86                 if (rc)
87                         goto exit;
88
89                 goto exit_free_skb;
90         }
91
92         if (DIGITAL_SEL_RES_IS_T2T(sel_res)) {
93                 nfc_proto = NFC_PROTO_MIFARE;
94         } else {
95                 rc = -EOPNOTSUPP;
96                 goto exit;
97         }
98
99         target->sel_res = sel_res;
100
101         rc = digital_target_found(ddev, target, nfc_proto);
102
103 exit:
104         kfree(target);
105
106 exit_free_skb:
107         dev_kfree_skb(resp);
108
109         if (rc)
110                 digital_poll_next_tech(ddev);
111 }
112
113 static int digital_in_send_sel_req(struct nfc_digital_dev *ddev,
114                                    struct nfc_target *target,
115                                    struct digital_sdd_res *sdd_res)
116 {
117         struct sk_buff *skb;
118         struct digital_sel_req *sel_req;
119         u8 sel_cmd;
120         int rc;
121
122         skb = digital_skb_alloc(ddev, sizeof(struct digital_sel_req));
123         if (!skb)
124                 return -ENOMEM;
125
126         skb_put(skb, sizeof(struct digital_sel_req));
127         sel_req = (struct digital_sel_req *)skb->data;
128
129         if (target->nfcid1_len <= 4)
130                 sel_cmd = DIGITAL_CMD_SEL_REQ_CL1;
131         else if (target->nfcid1_len < 10)
132                 sel_cmd = DIGITAL_CMD_SEL_REQ_CL2;
133         else
134                 sel_cmd = DIGITAL_CMD_SEL_REQ_CL3;
135
136         sel_req->sel_cmd = sel_cmd;
137         sel_req->b2 = 0x70;
138         memcpy(sel_req->nfcid1, sdd_res->nfcid1, 4);
139         sel_req->bcc = sdd_res->bcc;
140
141         if (DIGITAL_DRV_CAPS_IN_CRC(ddev)) {
142                 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
143                                 NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A);
144                 if (rc)
145                         goto exit;
146         } else {
147                 digital_skb_add_crc_a(skb);
148         }
149
150         rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sel_res,
151                                  target);
152 exit:
153         if (rc)
154                 kfree_skb(skb);
155
156         return rc;
157 }
158
159 static void digital_in_recv_sdd_res(struct nfc_digital_dev *ddev, void *arg,
160                                     struct sk_buff *resp)
161 {
162         struct nfc_target *target = arg;
163         struct digital_sdd_res *sdd_res;
164         int rc;
165         u8 offset, size;
166         u8 i, bcc;
167
168         if (IS_ERR(resp)) {
169                 rc = PTR_ERR(resp);
170                 resp = NULL;
171                 goto exit;
172         }
173
174         if (resp->len < DIGITAL_SDD_RES_LEN) {
175                 PROTOCOL_ERR("4.7.2.8");
176                 rc = -EINVAL;
177                 goto exit;
178         }
179
180         sdd_res = (struct digital_sdd_res *)resp->data;
181
182         for (i = 0, bcc = 0; i < 4; i++)
183                 bcc ^= sdd_res->nfcid1[i];
184
185         if (bcc != sdd_res->bcc) {
186                 PROTOCOL_ERR("4.7.2.6");
187                 rc = -EINVAL;
188                 goto exit;
189         }
190
191         if (sdd_res->nfcid1[0] == DIGITAL_SDD_RES_CT) {
192                 offset = 1;
193                 size = 3;
194         } else {
195                 offset = 0;
196                 size = 4;
197         }
198
199         memcpy(target->nfcid1 + target->nfcid1_len, sdd_res->nfcid1 + offset,
200                size);
201         target->nfcid1_len += size;
202
203         rc = digital_in_send_sel_req(ddev, target, sdd_res);
204
205 exit:
206         dev_kfree_skb(resp);
207
208         if (rc) {
209                 kfree(target);
210                 digital_poll_next_tech(ddev);
211         }
212 }
213
214 static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
215                                    struct nfc_target *target)
216 {
217         int rc;
218         struct sk_buff *skb;
219         u8 sel_cmd;
220
221         rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
222                                      NFC_DIGITAL_FRAMING_NFCA_STANDARD);
223         if (rc)
224                 return rc;
225
226         skb = digital_skb_alloc(ddev, 2);
227         if (!skb) {
228                 PR_ERR("alloc_skb failed");
229                 return -ENOMEM;
230         }
231
232         if (target->nfcid1_len == 0)
233                 sel_cmd = DIGITAL_CMD_SEL_REQ_CL1;
234         else if (target->nfcid1_len == 3)
235                 sel_cmd = DIGITAL_CMD_SEL_REQ_CL2;
236         else
237                 sel_cmd = DIGITAL_CMD_SEL_REQ_CL3;
238
239         *skb_put(skb, sizeof(u8)) = sel_cmd;
240         *skb_put(skb, sizeof(u8)) = DIGITAL_SDD_REQ_SEL_PAR;
241
242         return digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sdd_res,
243                                    target);
244 }
245
246 static void digital_in_recv_sens_res(struct nfc_digital_dev *ddev, void *arg,
247                                      struct sk_buff *resp)
248 {
249         struct nfc_target *target = NULL;
250         u16 sens_res;
251         int rc;
252
253         if (IS_ERR(resp)) {
254                 rc = PTR_ERR(resp);
255                 resp = NULL;
256                 goto exit;
257         }
258
259         if (resp->len < sizeof(u16)) {
260                 rc = -EIO;
261                 goto exit;
262         }
263
264         target = kzalloc(sizeof(struct nfc_target), GFP_KERNEL);
265         if (!target) {
266                 rc = -ENOMEM;
267                 goto exit;
268         }
269
270         memcpy(&target->sens_res, resp->data, sizeof(u16));
271
272         sens_res = be16_to_cpu(target->sens_res);
273
274         if (!DIGITAL_SENS_RES_IS_VALID(sens_res)) {
275                 PROTOCOL_ERR("4.6.3.3");
276                 rc = -EINVAL;
277                 goto exit;
278         }
279
280         if (DIGITAL_SENS_RES_IS_T1T(sens_res))
281                 rc = digital_target_found(ddev, target, NFC_PROTO_JEWEL);
282         else
283                 rc = digital_in_send_sdd_req(ddev, target);
284
285 exit:
286         dev_kfree_skb(resp);
287
288         if (rc) {
289                 kfree(target);
290                 digital_poll_next_tech(ddev);
291         }
292 }
293
294 int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech)
295 {
296         struct sk_buff *skb;
297         int rc;
298
299         rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
300                                      NFC_DIGITAL_RF_TECH_106A);
301         if (rc)
302                 return rc;
303
304         rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
305                                      NFC_DIGITAL_FRAMING_NFCA_SHORT);
306         if (rc)
307                 return rc;
308
309         skb = digital_skb_alloc(ddev, 1);
310         if (!skb)
311                 return -ENOMEM;
312
313         *skb_put(skb, sizeof(u8)) = DIGITAL_CMD_SENS_REQ;
314
315         rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sens_res, NULL);
316         if (rc)
317                 kfree_skb(skb);
318
319         return rc;
320 }
321
322 int digital_in_recv_mifare_res(struct sk_buff *resp)
323 {
324         /* Successful READ command response is 16 data bytes + 2 CRC bytes long.
325          * Since the driver can't differentiate a ACK/NACK response from a valid
326          * READ response, the CRC calculation must be handled at digital level
327          * even if the driver supports it for this technology.
328          */
329         if (resp->len == DIGITAL_MIFARE_READ_RES_LEN + DIGITAL_CRC_LEN) {
330                 if (digital_skb_check_crc_a(resp)) {
331                         PROTOCOL_ERR("9.4.1.2");
332                         return -EIO;
333                 }
334
335                 return 0;
336         }
337
338         /* ACK response (i.e. successful WRITE). */
339         if (resp->len == 1 && resp->data[0] == DIGITAL_MIFARE_ACK_RES) {
340                 resp->data[0] = 0;
341                 return 0;
342         }
343
344         /* NACK and any other responses are treated as error. */
345         return -EIO;
346 }