1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * NFC Digital Protocol stack
4*4882a593Smuzhiyun * Copyright (c) 2013, Intel Corporation.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #define pr_fmt(fmt) "digital: %s: " fmt, __func__
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include "digital.h"
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #define DIGITAL_CMD_SENS_REQ 0x26
12*4882a593Smuzhiyun #define DIGITAL_CMD_ALL_REQ 0x52
13*4882a593Smuzhiyun #define DIGITAL_CMD_SEL_REQ_CL1 0x93
14*4882a593Smuzhiyun #define DIGITAL_CMD_SEL_REQ_CL2 0x95
15*4882a593Smuzhiyun #define DIGITAL_CMD_SEL_REQ_CL3 0x97
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define DIGITAL_SDD_REQ_SEL_PAR 0x20
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define DIGITAL_SDD_RES_CT 0x88
20*4882a593Smuzhiyun #define DIGITAL_SDD_RES_LEN 5
21*4882a593Smuzhiyun #define DIGITAL_SEL_RES_LEN 1
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04))
24*4882a593Smuzhiyun #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60))
25*4882a593Smuzhiyun #define DIGITAL_SEL_RES_IS_T4T(sel_res) ((sel_res) & 0x20)
26*4882a593Smuzhiyun #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40)
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00)
29*4882a593Smuzhiyun #define DIGITAL_SENS_RES_IS_VALID(sens_res) \
30*4882a593Smuzhiyun ((!((sens_res) & 0x001F) && (((sens_res) & 0x0C00) == 0x0C00)) || \
31*4882a593Smuzhiyun (((sens_res) & 0x001F) && ((sens_res) & 0x0C00) != 0x0C00))
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define DIGITAL_MIFARE_READ_RES_LEN 16
34*4882a593Smuzhiyun #define DIGITAL_MIFARE_ACK_RES 0x0A
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #define DIGITAL_CMD_SENSB_REQ 0x05
37*4882a593Smuzhiyun #define DIGITAL_SENSB_ADVANCED BIT(5)
38*4882a593Smuzhiyun #define DIGITAL_SENSB_EXTENDED BIT(4)
39*4882a593Smuzhiyun #define DIGITAL_SENSB_ALLB_REQ BIT(3)
40*4882a593Smuzhiyun #define DIGITAL_SENSB_N(n) ((n) & 0x7)
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #define DIGITAL_CMD_SENSB_RES 0x50
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #define DIGITAL_CMD_ATTRIB_REQ 0x1D
45*4882a593Smuzhiyun #define DIGITAL_ATTRIB_P1_TR0_DEFAULT (0x0 << 6)
46*4882a593Smuzhiyun #define DIGITAL_ATTRIB_P1_TR1_DEFAULT (0x0 << 4)
47*4882a593Smuzhiyun #define DIGITAL_ATTRIB_P1_SUPRESS_EOS BIT(3)
48*4882a593Smuzhiyun #define DIGITAL_ATTRIB_P1_SUPRESS_SOS BIT(2)
49*4882a593Smuzhiyun #define DIGITAL_ATTRIB_P2_LISTEN_POLL_1 (0x0 << 6)
50*4882a593Smuzhiyun #define DIGITAL_ATTRIB_P2_POLL_LISTEN_1 (0x0 << 4)
51*4882a593Smuzhiyun #define DIGITAL_ATTRIB_P2_MAX_FRAME_256 0x8
52*4882a593Smuzhiyun #define DIGITAL_ATTRIB_P4_DID(n) ((n) & 0xf)
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #define DIGITAL_CMD_SENSF_REQ 0x00
55*4882a593Smuzhiyun #define DIGITAL_CMD_SENSF_RES 0x01
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun #define DIGITAL_SENSF_RES_MIN_LENGTH 17
58*4882a593Smuzhiyun #define DIGITAL_SENSF_RES_RD_AP_B1 0x00
59*4882a593Smuzhiyun #define DIGITAL_SENSF_RES_RD_AP_B2 0x8F
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun #define DIGITAL_SENSF_REQ_RC_NONE 0
62*4882a593Smuzhiyun #define DIGITAL_SENSF_REQ_RC_SC 1
63*4882a593Smuzhiyun #define DIGITAL_SENSF_REQ_RC_AP 2
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun #define DIGITAL_CMD_ISO15693_INVENTORY_REQ 0x01
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun #define DIGITAL_ISO15693_REQ_FLAG_DATA_RATE BIT(1)
68*4882a593Smuzhiyun #define DIGITAL_ISO15693_REQ_FLAG_INVENTORY BIT(2)
69*4882a593Smuzhiyun #define DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS BIT(5)
70*4882a593Smuzhiyun #define DIGITAL_ISO15693_RES_FLAG_ERROR BIT(0)
71*4882a593Smuzhiyun #define DIGITAL_ISO15693_RES_IS_VALID(flags) \
72*4882a593Smuzhiyun (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR))
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun #define DIGITAL_ISO_DEP_I_PCB 0x02
75*4882a593Smuzhiyun #define DIGITAL_ISO_DEP_PNI(pni) ((pni) & 0x01)
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun #define DIGITAL_ISO_DEP_PCB_TYPE(pcb) ((pcb) & 0xC0)
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun #define DIGITAL_ISO_DEP_I_BLOCK 0x00
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun #define DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb) ((pcb) & 0x08)
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun static const u8 digital_ats_fsc[] = {
84*4882a593Smuzhiyun 16, 24, 32, 40, 48, 64, 96, 128,
85*4882a593Smuzhiyun };
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun #define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F)
88*4882a593Smuzhiyun #define DIGITAL_SENSB_FSCI(pi2) (((pi2) & 0xF0) >> 4)
89*4882a593Smuzhiyun #define DIGITAL_ATS_MAX_FSC 256
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun #define DIGITAL_RATS_BYTE1 0xE0
92*4882a593Smuzhiyun #define DIGITAL_RATS_PARAM 0x80
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun struct digital_sdd_res {
95*4882a593Smuzhiyun u8 nfcid1[4];
96*4882a593Smuzhiyun u8 bcc;
97*4882a593Smuzhiyun } __packed;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun struct digital_sel_req {
100*4882a593Smuzhiyun u8 sel_cmd;
101*4882a593Smuzhiyun u8 b2;
102*4882a593Smuzhiyun u8 nfcid1[4];
103*4882a593Smuzhiyun u8 bcc;
104*4882a593Smuzhiyun } __packed;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun struct digital_sensb_req {
107*4882a593Smuzhiyun u8 cmd;
108*4882a593Smuzhiyun u8 afi;
109*4882a593Smuzhiyun u8 param;
110*4882a593Smuzhiyun } __packed;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun struct digital_sensb_res {
113*4882a593Smuzhiyun u8 cmd;
114*4882a593Smuzhiyun u8 nfcid0[4];
115*4882a593Smuzhiyun u8 app_data[4];
116*4882a593Smuzhiyun u8 proto_info[3];
117*4882a593Smuzhiyun } __packed;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun struct digital_attrib_req {
120*4882a593Smuzhiyun u8 cmd;
121*4882a593Smuzhiyun u8 nfcid0[4];
122*4882a593Smuzhiyun u8 param1;
123*4882a593Smuzhiyun u8 param2;
124*4882a593Smuzhiyun u8 param3;
125*4882a593Smuzhiyun u8 param4;
126*4882a593Smuzhiyun } __packed;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun struct digital_attrib_res {
129*4882a593Smuzhiyun u8 mbli_did;
130*4882a593Smuzhiyun } __packed;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun struct digital_sensf_req {
133*4882a593Smuzhiyun u8 cmd;
134*4882a593Smuzhiyun u8 sc1;
135*4882a593Smuzhiyun u8 sc2;
136*4882a593Smuzhiyun u8 rc;
137*4882a593Smuzhiyun u8 tsn;
138*4882a593Smuzhiyun } __packed;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun struct digital_sensf_res {
141*4882a593Smuzhiyun u8 cmd;
142*4882a593Smuzhiyun u8 nfcid2[8];
143*4882a593Smuzhiyun u8 pad0[2];
144*4882a593Smuzhiyun u8 pad1[3];
145*4882a593Smuzhiyun u8 mrti_check;
146*4882a593Smuzhiyun u8 mrti_update;
147*4882a593Smuzhiyun u8 pad2;
148*4882a593Smuzhiyun u8 rd[2];
149*4882a593Smuzhiyun } __packed;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun struct digital_iso15693_inv_req {
152*4882a593Smuzhiyun u8 flags;
153*4882a593Smuzhiyun u8 cmd;
154*4882a593Smuzhiyun u8 mask_len;
155*4882a593Smuzhiyun u64 mask;
156*4882a593Smuzhiyun } __packed;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun struct digital_iso15693_inv_res {
159*4882a593Smuzhiyun u8 flags;
160*4882a593Smuzhiyun u8 dsfid;
161*4882a593Smuzhiyun u64 uid;
162*4882a593Smuzhiyun } __packed;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
165*4882a593Smuzhiyun struct nfc_target *target);
166*4882a593Smuzhiyun
digital_in_iso_dep_pull_sod(struct nfc_digital_dev * ddev,struct sk_buff * skb)167*4882a593Smuzhiyun int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev,
168*4882a593Smuzhiyun struct sk_buff *skb)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun u8 pcb;
171*4882a593Smuzhiyun u8 block_type;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun if (skb->len < 1)
174*4882a593Smuzhiyun return -EIO;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun pcb = *skb->data;
177*4882a593Smuzhiyun block_type = DIGITAL_ISO_DEP_PCB_TYPE(pcb);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /* No support fo R-block nor S-block */
180*4882a593Smuzhiyun if (block_type != DIGITAL_ISO_DEP_I_BLOCK) {
181*4882a593Smuzhiyun pr_err("ISO_DEP R-block and S-block not supported\n");
182*4882a593Smuzhiyun return -EIO;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun if (DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb)) {
186*4882a593Smuzhiyun pr_err("DID field in ISO_DEP PCB not supported\n");
187*4882a593Smuzhiyun return -EIO;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun skb_pull(skb, 1);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun return 0;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
digital_in_iso_dep_push_sod(struct nfc_digital_dev * ddev,struct sk_buff * skb)195*4882a593Smuzhiyun int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev,
196*4882a593Smuzhiyun struct sk_buff *skb)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun /*
199*4882a593Smuzhiyun * Chaining not supported so skb->len + 1 PCB byte + 2 CRC bytes must
200*4882a593Smuzhiyun * not be greater than remote FSC
201*4882a593Smuzhiyun */
202*4882a593Smuzhiyun if (skb->len + 3 > ddev->target_fsc)
203*4882a593Smuzhiyun return -EIO;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun skb_push(skb, 1);
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun *skb->data = DIGITAL_ISO_DEP_I_PCB | ddev->curr_nfc_dep_pni;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun ddev->curr_nfc_dep_pni =
210*4882a593Smuzhiyun DIGITAL_ISO_DEP_PNI(ddev->curr_nfc_dep_pni + 1);
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun return 0;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun
digital_in_recv_ats(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)215*4882a593Smuzhiyun static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg,
216*4882a593Smuzhiyun struct sk_buff *resp)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun struct nfc_target *target = arg;
219*4882a593Smuzhiyun u8 fsdi;
220*4882a593Smuzhiyun int rc;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if (IS_ERR(resp)) {
223*4882a593Smuzhiyun rc = PTR_ERR(resp);
224*4882a593Smuzhiyun resp = NULL;
225*4882a593Smuzhiyun goto exit;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun if (resp->len < 2) {
229*4882a593Smuzhiyun rc = -EIO;
230*4882a593Smuzhiyun goto exit;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun fsdi = DIGITAL_ATS_FSCI(resp->data[1]);
234*4882a593Smuzhiyun if (fsdi >= 8)
235*4882a593Smuzhiyun ddev->target_fsc = DIGITAL_ATS_MAX_FSC;
236*4882a593Smuzhiyun else
237*4882a593Smuzhiyun ddev->target_fsc = digital_ats_fsc[fsdi];
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun ddev->curr_nfc_dep_pni = 0;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun exit:
244*4882a593Smuzhiyun dev_kfree_skb(resp);
245*4882a593Smuzhiyun kfree(target);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun if (rc)
248*4882a593Smuzhiyun digital_poll_next_tech(ddev);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
digital_in_send_rats(struct nfc_digital_dev * ddev,struct nfc_target * target)251*4882a593Smuzhiyun static int digital_in_send_rats(struct nfc_digital_dev *ddev,
252*4882a593Smuzhiyun struct nfc_target *target)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun int rc;
255*4882a593Smuzhiyun struct sk_buff *skb;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, 2);
258*4882a593Smuzhiyun if (!skb)
259*4882a593Smuzhiyun return -ENOMEM;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun skb_put_u8(skb, DIGITAL_RATS_BYTE1);
262*4882a593Smuzhiyun skb_put_u8(skb, DIGITAL_RATS_PARAM);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_ats,
265*4882a593Smuzhiyun target);
266*4882a593Smuzhiyun if (rc)
267*4882a593Smuzhiyun kfree_skb(skb);
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun return rc;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
digital_in_recv_sel_res(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)272*4882a593Smuzhiyun static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
273*4882a593Smuzhiyun struct sk_buff *resp)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun struct nfc_target *target = arg;
276*4882a593Smuzhiyun int rc;
277*4882a593Smuzhiyun u8 sel_res;
278*4882a593Smuzhiyun u8 nfc_proto;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun if (IS_ERR(resp)) {
281*4882a593Smuzhiyun rc = PTR_ERR(resp);
282*4882a593Smuzhiyun resp = NULL;
283*4882a593Smuzhiyun goto exit;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) {
287*4882a593Smuzhiyun rc = digital_skb_check_crc_a(resp);
288*4882a593Smuzhiyun if (rc) {
289*4882a593Smuzhiyun PROTOCOL_ERR("4.4.1.3");
290*4882a593Smuzhiyun goto exit;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun if (resp->len != DIGITAL_SEL_RES_LEN) {
295*4882a593Smuzhiyun rc = -EIO;
296*4882a593Smuzhiyun goto exit;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun sel_res = resp->data[0];
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun if (!DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res)) {
302*4882a593Smuzhiyun rc = digital_in_send_sdd_req(ddev, target);
303*4882a593Smuzhiyun if (rc)
304*4882a593Smuzhiyun goto exit;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun goto exit_free_skb;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun target->sel_res = sel_res;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun if (DIGITAL_SEL_RES_IS_T2T(sel_res)) {
312*4882a593Smuzhiyun nfc_proto = NFC_PROTO_MIFARE;
313*4882a593Smuzhiyun } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) {
314*4882a593Smuzhiyun nfc_proto = NFC_PROTO_NFC_DEP;
315*4882a593Smuzhiyun } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) {
316*4882a593Smuzhiyun rc = digital_in_send_rats(ddev, target);
317*4882a593Smuzhiyun if (rc)
318*4882a593Smuzhiyun goto exit;
319*4882a593Smuzhiyun /*
320*4882a593Smuzhiyun * Skip target_found and don't free it for now. This will be
321*4882a593Smuzhiyun * done when receiving the ATS
322*4882a593Smuzhiyun */
323*4882a593Smuzhiyun goto exit_free_skb;
324*4882a593Smuzhiyun } else {
325*4882a593Smuzhiyun rc = -EOPNOTSUPP;
326*4882a593Smuzhiyun goto exit;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun rc = digital_target_found(ddev, target, nfc_proto);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun exit:
332*4882a593Smuzhiyun kfree(target);
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun exit_free_skb:
335*4882a593Smuzhiyun dev_kfree_skb(resp);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun if (rc)
338*4882a593Smuzhiyun digital_poll_next_tech(ddev);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
digital_in_send_sel_req(struct nfc_digital_dev * ddev,struct nfc_target * target,struct digital_sdd_res * sdd_res)341*4882a593Smuzhiyun static int digital_in_send_sel_req(struct nfc_digital_dev *ddev,
342*4882a593Smuzhiyun struct nfc_target *target,
343*4882a593Smuzhiyun struct digital_sdd_res *sdd_res)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun struct sk_buff *skb;
346*4882a593Smuzhiyun struct digital_sel_req *sel_req;
347*4882a593Smuzhiyun u8 sel_cmd;
348*4882a593Smuzhiyun int rc;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, sizeof(struct digital_sel_req));
351*4882a593Smuzhiyun if (!skb)
352*4882a593Smuzhiyun return -ENOMEM;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun skb_put(skb, sizeof(struct digital_sel_req));
355*4882a593Smuzhiyun sel_req = (struct digital_sel_req *)skb->data;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun if (target->nfcid1_len <= 4)
358*4882a593Smuzhiyun sel_cmd = DIGITAL_CMD_SEL_REQ_CL1;
359*4882a593Smuzhiyun else if (target->nfcid1_len < 10)
360*4882a593Smuzhiyun sel_cmd = DIGITAL_CMD_SEL_REQ_CL2;
361*4882a593Smuzhiyun else
362*4882a593Smuzhiyun sel_cmd = DIGITAL_CMD_SEL_REQ_CL3;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun sel_req->sel_cmd = sel_cmd;
365*4882a593Smuzhiyun sel_req->b2 = 0x70;
366*4882a593Smuzhiyun memcpy(sel_req->nfcid1, sdd_res->nfcid1, 4);
367*4882a593Smuzhiyun sel_req->bcc = sdd_res->bcc;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun if (DIGITAL_DRV_CAPS_IN_CRC(ddev)) {
370*4882a593Smuzhiyun rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
371*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A);
372*4882a593Smuzhiyun if (rc)
373*4882a593Smuzhiyun goto exit;
374*4882a593Smuzhiyun } else {
375*4882a593Smuzhiyun digital_skb_add_crc_a(skb);
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sel_res,
379*4882a593Smuzhiyun target);
380*4882a593Smuzhiyun exit:
381*4882a593Smuzhiyun if (rc)
382*4882a593Smuzhiyun kfree_skb(skb);
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun return rc;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
digital_in_recv_sdd_res(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)387*4882a593Smuzhiyun static void digital_in_recv_sdd_res(struct nfc_digital_dev *ddev, void *arg,
388*4882a593Smuzhiyun struct sk_buff *resp)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun struct nfc_target *target = arg;
391*4882a593Smuzhiyun struct digital_sdd_res *sdd_res;
392*4882a593Smuzhiyun int rc;
393*4882a593Smuzhiyun u8 offset, size;
394*4882a593Smuzhiyun u8 i, bcc;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun if (IS_ERR(resp)) {
397*4882a593Smuzhiyun rc = PTR_ERR(resp);
398*4882a593Smuzhiyun resp = NULL;
399*4882a593Smuzhiyun goto exit;
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun if (resp->len < DIGITAL_SDD_RES_LEN) {
403*4882a593Smuzhiyun PROTOCOL_ERR("4.7.2.8");
404*4882a593Smuzhiyun rc = -EINVAL;
405*4882a593Smuzhiyun goto exit;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun sdd_res = (struct digital_sdd_res *)resp->data;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun for (i = 0, bcc = 0; i < 4; i++)
411*4882a593Smuzhiyun bcc ^= sdd_res->nfcid1[i];
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun if (bcc != sdd_res->bcc) {
414*4882a593Smuzhiyun PROTOCOL_ERR("4.7.2.6");
415*4882a593Smuzhiyun rc = -EINVAL;
416*4882a593Smuzhiyun goto exit;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun if (sdd_res->nfcid1[0] == DIGITAL_SDD_RES_CT) {
420*4882a593Smuzhiyun offset = 1;
421*4882a593Smuzhiyun size = 3;
422*4882a593Smuzhiyun } else {
423*4882a593Smuzhiyun offset = 0;
424*4882a593Smuzhiyun size = 4;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun memcpy(target->nfcid1 + target->nfcid1_len, sdd_res->nfcid1 + offset,
428*4882a593Smuzhiyun size);
429*4882a593Smuzhiyun target->nfcid1_len += size;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun rc = digital_in_send_sel_req(ddev, target, sdd_res);
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun exit:
434*4882a593Smuzhiyun dev_kfree_skb(resp);
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun if (rc) {
437*4882a593Smuzhiyun kfree(target);
438*4882a593Smuzhiyun digital_poll_next_tech(ddev);
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun
digital_in_send_sdd_req(struct nfc_digital_dev * ddev,struct nfc_target * target)442*4882a593Smuzhiyun static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
443*4882a593Smuzhiyun struct nfc_target *target)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun int rc;
446*4882a593Smuzhiyun struct sk_buff *skb;
447*4882a593Smuzhiyun u8 sel_cmd;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
450*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_NFCA_STANDARD);
451*4882a593Smuzhiyun if (rc)
452*4882a593Smuzhiyun return rc;
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, 2);
455*4882a593Smuzhiyun if (!skb)
456*4882a593Smuzhiyun return -ENOMEM;
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun if (target->nfcid1_len == 0)
459*4882a593Smuzhiyun sel_cmd = DIGITAL_CMD_SEL_REQ_CL1;
460*4882a593Smuzhiyun else if (target->nfcid1_len == 3)
461*4882a593Smuzhiyun sel_cmd = DIGITAL_CMD_SEL_REQ_CL2;
462*4882a593Smuzhiyun else
463*4882a593Smuzhiyun sel_cmd = DIGITAL_CMD_SEL_REQ_CL3;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun skb_put_u8(skb, sel_cmd);
466*4882a593Smuzhiyun skb_put_u8(skb, DIGITAL_SDD_REQ_SEL_PAR);
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sdd_res,
469*4882a593Smuzhiyun target);
470*4882a593Smuzhiyun if (rc)
471*4882a593Smuzhiyun kfree_skb(skb);
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun return rc;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
digital_in_recv_sens_res(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)476*4882a593Smuzhiyun static void digital_in_recv_sens_res(struct nfc_digital_dev *ddev, void *arg,
477*4882a593Smuzhiyun struct sk_buff *resp)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun struct nfc_target *target = NULL;
480*4882a593Smuzhiyun int rc;
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun if (IS_ERR(resp)) {
483*4882a593Smuzhiyun rc = PTR_ERR(resp);
484*4882a593Smuzhiyun resp = NULL;
485*4882a593Smuzhiyun goto exit;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun if (resp->len < sizeof(u16)) {
489*4882a593Smuzhiyun rc = -EIO;
490*4882a593Smuzhiyun goto exit;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun target = kzalloc(sizeof(struct nfc_target), GFP_KERNEL);
494*4882a593Smuzhiyun if (!target) {
495*4882a593Smuzhiyun rc = -ENOMEM;
496*4882a593Smuzhiyun goto exit;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun target->sens_res = __le16_to_cpu(*(__le16 *)resp->data);
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun if (!DIGITAL_SENS_RES_IS_VALID(target->sens_res)) {
502*4882a593Smuzhiyun PROTOCOL_ERR("4.6.3.3");
503*4882a593Smuzhiyun rc = -EINVAL;
504*4882a593Smuzhiyun goto exit;
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun if (DIGITAL_SENS_RES_IS_T1T(target->sens_res))
508*4882a593Smuzhiyun rc = digital_target_found(ddev, target, NFC_PROTO_JEWEL);
509*4882a593Smuzhiyun else
510*4882a593Smuzhiyun rc = digital_in_send_sdd_req(ddev, target);
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun exit:
513*4882a593Smuzhiyun dev_kfree_skb(resp);
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun if (rc) {
516*4882a593Smuzhiyun kfree(target);
517*4882a593Smuzhiyun digital_poll_next_tech(ddev);
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
digital_in_send_sens_req(struct nfc_digital_dev * ddev,u8 rf_tech)521*4882a593Smuzhiyun int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun struct sk_buff *skb;
524*4882a593Smuzhiyun int rc;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
527*4882a593Smuzhiyun NFC_DIGITAL_RF_TECH_106A);
528*4882a593Smuzhiyun if (rc)
529*4882a593Smuzhiyun return rc;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
532*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_NFCA_SHORT);
533*4882a593Smuzhiyun if (rc)
534*4882a593Smuzhiyun return rc;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, 1);
537*4882a593Smuzhiyun if (!skb)
538*4882a593Smuzhiyun return -ENOMEM;
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun skb_put_u8(skb, DIGITAL_CMD_SENS_REQ);
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sens_res, NULL);
543*4882a593Smuzhiyun if (rc)
544*4882a593Smuzhiyun kfree_skb(skb);
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun return rc;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun
digital_in_recv_mifare_res(struct sk_buff * resp)549*4882a593Smuzhiyun int digital_in_recv_mifare_res(struct sk_buff *resp)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun /* Successful READ command response is 16 data bytes + 2 CRC bytes long.
552*4882a593Smuzhiyun * Since the driver can't differentiate a ACK/NACK response from a valid
553*4882a593Smuzhiyun * READ response, the CRC calculation must be handled at digital level
554*4882a593Smuzhiyun * even if the driver supports it for this technology.
555*4882a593Smuzhiyun */
556*4882a593Smuzhiyun if (resp->len == DIGITAL_MIFARE_READ_RES_LEN + DIGITAL_CRC_LEN) {
557*4882a593Smuzhiyun if (digital_skb_check_crc_a(resp)) {
558*4882a593Smuzhiyun PROTOCOL_ERR("9.4.1.2");
559*4882a593Smuzhiyun return -EIO;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun return 0;
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun /* ACK response (i.e. successful WRITE). */
566*4882a593Smuzhiyun if (resp->len == 1 && resp->data[0] == DIGITAL_MIFARE_ACK_RES) {
567*4882a593Smuzhiyun resp->data[0] = 0;
568*4882a593Smuzhiyun return 0;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun /* NACK and any other responses are treated as error. */
572*4882a593Smuzhiyun return -EIO;
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun
digital_in_recv_attrib_res(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)575*4882a593Smuzhiyun static void digital_in_recv_attrib_res(struct nfc_digital_dev *ddev, void *arg,
576*4882a593Smuzhiyun struct sk_buff *resp)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun struct nfc_target *target = arg;
579*4882a593Smuzhiyun struct digital_attrib_res *attrib_res;
580*4882a593Smuzhiyun int rc;
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun if (IS_ERR(resp)) {
583*4882a593Smuzhiyun rc = PTR_ERR(resp);
584*4882a593Smuzhiyun resp = NULL;
585*4882a593Smuzhiyun goto exit;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun if (resp->len < sizeof(*attrib_res)) {
589*4882a593Smuzhiyun PROTOCOL_ERR("12.6.2");
590*4882a593Smuzhiyun rc = -EIO;
591*4882a593Smuzhiyun goto exit;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun attrib_res = (struct digital_attrib_res *)resp->data;
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun if (attrib_res->mbli_did & 0x0f) {
597*4882a593Smuzhiyun PROTOCOL_ERR("12.6.2.1");
598*4882a593Smuzhiyun rc = -EIO;
599*4882a593Smuzhiyun goto exit;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443_B);
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun exit:
605*4882a593Smuzhiyun dev_kfree_skb(resp);
606*4882a593Smuzhiyun kfree(target);
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun if (rc)
609*4882a593Smuzhiyun digital_poll_next_tech(ddev);
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun
digital_in_send_attrib_req(struct nfc_digital_dev * ddev,struct nfc_target * target,struct digital_sensb_res * sensb_res)612*4882a593Smuzhiyun static int digital_in_send_attrib_req(struct nfc_digital_dev *ddev,
613*4882a593Smuzhiyun struct nfc_target *target,
614*4882a593Smuzhiyun struct digital_sensb_res *sensb_res)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun struct digital_attrib_req *attrib_req;
617*4882a593Smuzhiyun struct sk_buff *skb;
618*4882a593Smuzhiyun int rc;
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, sizeof(*attrib_req));
621*4882a593Smuzhiyun if (!skb)
622*4882a593Smuzhiyun return -ENOMEM;
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun attrib_req = skb_put(skb, sizeof(*attrib_req));
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun attrib_req->cmd = DIGITAL_CMD_ATTRIB_REQ;
627*4882a593Smuzhiyun memcpy(attrib_req->nfcid0, sensb_res->nfcid0,
628*4882a593Smuzhiyun sizeof(attrib_req->nfcid0));
629*4882a593Smuzhiyun attrib_req->param1 = DIGITAL_ATTRIB_P1_TR0_DEFAULT |
630*4882a593Smuzhiyun DIGITAL_ATTRIB_P1_TR1_DEFAULT;
631*4882a593Smuzhiyun attrib_req->param2 = DIGITAL_ATTRIB_P2_LISTEN_POLL_1 |
632*4882a593Smuzhiyun DIGITAL_ATTRIB_P2_POLL_LISTEN_1 |
633*4882a593Smuzhiyun DIGITAL_ATTRIB_P2_MAX_FRAME_256;
634*4882a593Smuzhiyun attrib_req->param3 = sensb_res->proto_info[1] & 0x07;
635*4882a593Smuzhiyun attrib_req->param4 = DIGITAL_ATTRIB_P4_DID(0);
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_attrib_res,
638*4882a593Smuzhiyun target);
639*4882a593Smuzhiyun if (rc)
640*4882a593Smuzhiyun kfree_skb(skb);
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun return rc;
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun
digital_in_recv_sensb_res(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)645*4882a593Smuzhiyun static void digital_in_recv_sensb_res(struct nfc_digital_dev *ddev, void *arg,
646*4882a593Smuzhiyun struct sk_buff *resp)
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun struct nfc_target *target = NULL;
649*4882a593Smuzhiyun struct digital_sensb_res *sensb_res;
650*4882a593Smuzhiyun u8 fsci;
651*4882a593Smuzhiyun int rc;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun if (IS_ERR(resp)) {
654*4882a593Smuzhiyun rc = PTR_ERR(resp);
655*4882a593Smuzhiyun resp = NULL;
656*4882a593Smuzhiyun goto exit;
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun if (resp->len != sizeof(*sensb_res)) {
660*4882a593Smuzhiyun PROTOCOL_ERR("5.6.2.1");
661*4882a593Smuzhiyun rc = -EIO;
662*4882a593Smuzhiyun goto exit;
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun sensb_res = (struct digital_sensb_res *)resp->data;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun if (sensb_res->cmd != DIGITAL_CMD_SENSB_RES) {
668*4882a593Smuzhiyun PROTOCOL_ERR("5.6.2");
669*4882a593Smuzhiyun rc = -EIO;
670*4882a593Smuzhiyun goto exit;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun if (!(sensb_res->proto_info[1] & BIT(0))) {
674*4882a593Smuzhiyun PROTOCOL_ERR("5.6.2.12");
675*4882a593Smuzhiyun rc = -EIO;
676*4882a593Smuzhiyun goto exit;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun if (sensb_res->proto_info[1] & BIT(3)) {
680*4882a593Smuzhiyun PROTOCOL_ERR("5.6.2.16");
681*4882a593Smuzhiyun rc = -EIO;
682*4882a593Smuzhiyun goto exit;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun fsci = DIGITAL_SENSB_FSCI(sensb_res->proto_info[1]);
686*4882a593Smuzhiyun if (fsci >= 8)
687*4882a593Smuzhiyun ddev->target_fsc = DIGITAL_ATS_MAX_FSC;
688*4882a593Smuzhiyun else
689*4882a593Smuzhiyun ddev->target_fsc = digital_ats_fsc[fsci];
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun target = kzalloc(sizeof(struct nfc_target), GFP_KERNEL);
692*4882a593Smuzhiyun if (!target) {
693*4882a593Smuzhiyun rc = -ENOMEM;
694*4882a593Smuzhiyun goto exit;
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun rc = digital_in_send_attrib_req(ddev, target, sensb_res);
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun exit:
700*4882a593Smuzhiyun dev_kfree_skb(resp);
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun if (rc) {
703*4882a593Smuzhiyun kfree(target);
704*4882a593Smuzhiyun digital_poll_next_tech(ddev);
705*4882a593Smuzhiyun }
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun
digital_in_send_sensb_req(struct nfc_digital_dev * ddev,u8 rf_tech)708*4882a593Smuzhiyun int digital_in_send_sensb_req(struct nfc_digital_dev *ddev, u8 rf_tech)
709*4882a593Smuzhiyun {
710*4882a593Smuzhiyun struct digital_sensb_req *sensb_req;
711*4882a593Smuzhiyun struct sk_buff *skb;
712*4882a593Smuzhiyun int rc;
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
715*4882a593Smuzhiyun NFC_DIGITAL_RF_TECH_106B);
716*4882a593Smuzhiyun if (rc)
717*4882a593Smuzhiyun return rc;
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
720*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_NFCB);
721*4882a593Smuzhiyun if (rc)
722*4882a593Smuzhiyun return rc;
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, sizeof(*sensb_req));
725*4882a593Smuzhiyun if (!skb)
726*4882a593Smuzhiyun return -ENOMEM;
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun sensb_req = skb_put(skb, sizeof(*sensb_req));
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun sensb_req->cmd = DIGITAL_CMD_SENSB_REQ;
731*4882a593Smuzhiyun sensb_req->afi = 0x00; /* All families and sub-families */
732*4882a593Smuzhiyun sensb_req->param = DIGITAL_SENSB_N(0);
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sensb_res,
735*4882a593Smuzhiyun NULL);
736*4882a593Smuzhiyun if (rc)
737*4882a593Smuzhiyun kfree_skb(skb);
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun return rc;
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun
digital_in_recv_sensf_res(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)742*4882a593Smuzhiyun static void digital_in_recv_sensf_res(struct nfc_digital_dev *ddev, void *arg,
743*4882a593Smuzhiyun struct sk_buff *resp)
744*4882a593Smuzhiyun {
745*4882a593Smuzhiyun int rc;
746*4882a593Smuzhiyun u8 proto;
747*4882a593Smuzhiyun struct nfc_target target;
748*4882a593Smuzhiyun struct digital_sensf_res *sensf_res;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun if (IS_ERR(resp)) {
751*4882a593Smuzhiyun rc = PTR_ERR(resp);
752*4882a593Smuzhiyun resp = NULL;
753*4882a593Smuzhiyun goto exit;
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun if (resp->len < DIGITAL_SENSF_RES_MIN_LENGTH) {
757*4882a593Smuzhiyun rc = -EIO;
758*4882a593Smuzhiyun goto exit;
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) {
762*4882a593Smuzhiyun rc = digital_skb_check_crc_f(resp);
763*4882a593Smuzhiyun if (rc) {
764*4882a593Smuzhiyun PROTOCOL_ERR("6.4.1.8");
765*4882a593Smuzhiyun goto exit;
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun skb_pull(resp, 1);
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun memset(&target, 0, sizeof(struct nfc_target));
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun sensf_res = (struct digital_sensf_res *)resp->data;
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun memcpy(target.sensf_res, sensf_res, resp->len);
776*4882a593Smuzhiyun target.sensf_res_len = resp->len;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun memcpy(target.nfcid2, sensf_res->nfcid2, NFC_NFCID2_MAXSIZE);
779*4882a593Smuzhiyun target.nfcid2_len = NFC_NFCID2_MAXSIZE;
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun if (target.nfcid2[0] == DIGITAL_SENSF_NFCID2_NFC_DEP_B1 &&
782*4882a593Smuzhiyun target.nfcid2[1] == DIGITAL_SENSF_NFCID2_NFC_DEP_B2)
783*4882a593Smuzhiyun proto = NFC_PROTO_NFC_DEP;
784*4882a593Smuzhiyun else
785*4882a593Smuzhiyun proto = NFC_PROTO_FELICA;
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun rc = digital_target_found(ddev, &target, proto);
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun exit:
790*4882a593Smuzhiyun dev_kfree_skb(resp);
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun if (rc)
793*4882a593Smuzhiyun digital_poll_next_tech(ddev);
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun
digital_in_send_sensf_req(struct nfc_digital_dev * ddev,u8 rf_tech)796*4882a593Smuzhiyun int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech)
797*4882a593Smuzhiyun {
798*4882a593Smuzhiyun struct digital_sensf_req *sensf_req;
799*4882a593Smuzhiyun struct sk_buff *skb;
800*4882a593Smuzhiyun int rc;
801*4882a593Smuzhiyun u8 size;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
804*4882a593Smuzhiyun if (rc)
805*4882a593Smuzhiyun return rc;
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
808*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_NFCF);
809*4882a593Smuzhiyun if (rc)
810*4882a593Smuzhiyun return rc;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun size = sizeof(struct digital_sensf_req);
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, size);
815*4882a593Smuzhiyun if (!skb)
816*4882a593Smuzhiyun return -ENOMEM;
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun skb_put(skb, size);
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun sensf_req = (struct digital_sensf_req *)skb->data;
821*4882a593Smuzhiyun sensf_req->cmd = DIGITAL_CMD_SENSF_REQ;
822*4882a593Smuzhiyun sensf_req->sc1 = 0xFF;
823*4882a593Smuzhiyun sensf_req->sc2 = 0xFF;
824*4882a593Smuzhiyun sensf_req->rc = 0;
825*4882a593Smuzhiyun sensf_req->tsn = 0;
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun *(u8 *)skb_push(skb, 1) = size + 1;
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun if (!DIGITAL_DRV_CAPS_IN_CRC(ddev))
830*4882a593Smuzhiyun digital_skb_add_crc_f(skb);
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sensf_res,
833*4882a593Smuzhiyun NULL);
834*4882a593Smuzhiyun if (rc)
835*4882a593Smuzhiyun kfree_skb(skb);
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun return rc;
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun
digital_in_recv_iso15693_inv_res(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)840*4882a593Smuzhiyun static void digital_in_recv_iso15693_inv_res(struct nfc_digital_dev *ddev,
841*4882a593Smuzhiyun void *arg, struct sk_buff *resp)
842*4882a593Smuzhiyun {
843*4882a593Smuzhiyun struct digital_iso15693_inv_res *res;
844*4882a593Smuzhiyun struct nfc_target *target = NULL;
845*4882a593Smuzhiyun int rc;
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun if (IS_ERR(resp)) {
848*4882a593Smuzhiyun rc = PTR_ERR(resp);
849*4882a593Smuzhiyun resp = NULL;
850*4882a593Smuzhiyun goto out_free_skb;
851*4882a593Smuzhiyun }
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun if (resp->len != sizeof(*res)) {
854*4882a593Smuzhiyun rc = -EIO;
855*4882a593Smuzhiyun goto out_free_skb;
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun res = (struct digital_iso15693_inv_res *)resp->data;
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun if (!DIGITAL_ISO15693_RES_IS_VALID(res->flags)) {
861*4882a593Smuzhiyun PROTOCOL_ERR("ISO15693 - 10.3.1");
862*4882a593Smuzhiyun rc = -EINVAL;
863*4882a593Smuzhiyun goto out_free_skb;
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun target = kzalloc(sizeof(*target), GFP_KERNEL);
867*4882a593Smuzhiyun if (!target) {
868*4882a593Smuzhiyun rc = -ENOMEM;
869*4882a593Smuzhiyun goto out_free_skb;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun target->is_iso15693 = 1;
873*4882a593Smuzhiyun target->iso15693_dsfid = res->dsfid;
874*4882a593Smuzhiyun memcpy(target->iso15693_uid, &res->uid, sizeof(target->iso15693_uid));
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun rc = digital_target_found(ddev, target, NFC_PROTO_ISO15693);
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun kfree(target);
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun out_free_skb:
881*4882a593Smuzhiyun dev_kfree_skb(resp);
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun if (rc)
884*4882a593Smuzhiyun digital_poll_next_tech(ddev);
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun
digital_in_send_iso15693_inv_req(struct nfc_digital_dev * ddev,u8 rf_tech)887*4882a593Smuzhiyun int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun struct digital_iso15693_inv_req *req;
890*4882a593Smuzhiyun struct sk_buff *skb;
891*4882a593Smuzhiyun int rc;
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
894*4882a593Smuzhiyun NFC_DIGITAL_RF_TECH_ISO15693);
895*4882a593Smuzhiyun if (rc)
896*4882a593Smuzhiyun return rc;
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
899*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_ISO15693_INVENTORY);
900*4882a593Smuzhiyun if (rc)
901*4882a593Smuzhiyun return rc;
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, sizeof(*req));
904*4882a593Smuzhiyun if (!skb)
905*4882a593Smuzhiyun return -ENOMEM;
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun skb_put(skb, sizeof(*req) - sizeof(req->mask)); /* No mask */
908*4882a593Smuzhiyun req = (struct digital_iso15693_inv_req *)skb->data;
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun /* Single sub-carrier, high data rate, no AFI, single slot
911*4882a593Smuzhiyun * Inventory command
912*4882a593Smuzhiyun */
913*4882a593Smuzhiyun req->flags = DIGITAL_ISO15693_REQ_FLAG_DATA_RATE |
914*4882a593Smuzhiyun DIGITAL_ISO15693_REQ_FLAG_INVENTORY |
915*4882a593Smuzhiyun DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS;
916*4882a593Smuzhiyun req->cmd = DIGITAL_CMD_ISO15693_INVENTORY_REQ;
917*4882a593Smuzhiyun req->mask_len = 0;
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun rc = digital_in_send_cmd(ddev, skb, 30,
920*4882a593Smuzhiyun digital_in_recv_iso15693_inv_res, NULL);
921*4882a593Smuzhiyun if (rc)
922*4882a593Smuzhiyun kfree_skb(skb);
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun return rc;
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun
digital_tg_send_sel_res(struct nfc_digital_dev * ddev)927*4882a593Smuzhiyun static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev)
928*4882a593Smuzhiyun {
929*4882a593Smuzhiyun struct sk_buff *skb;
930*4882a593Smuzhiyun int rc;
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, 1);
933*4882a593Smuzhiyun if (!skb)
934*4882a593Smuzhiyun return -ENOMEM;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun skb_put_u8(skb, DIGITAL_SEL_RES_NFC_DEP);
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun if (!DIGITAL_DRV_CAPS_TG_CRC(ddev))
939*4882a593Smuzhiyun digital_skb_add_crc_a(skb);
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
942*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE);
943*4882a593Smuzhiyun if (rc) {
944*4882a593Smuzhiyun kfree_skb(skb);
945*4882a593Smuzhiyun return rc;
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_atr_req,
949*4882a593Smuzhiyun NULL);
950*4882a593Smuzhiyun if (rc)
951*4882a593Smuzhiyun kfree_skb(skb);
952*4882a593Smuzhiyun
953*4882a593Smuzhiyun return rc;
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun
digital_tg_recv_sel_req(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)956*4882a593Smuzhiyun static void digital_tg_recv_sel_req(struct nfc_digital_dev *ddev, void *arg,
957*4882a593Smuzhiyun struct sk_buff *resp)
958*4882a593Smuzhiyun {
959*4882a593Smuzhiyun int rc;
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun if (IS_ERR(resp)) {
962*4882a593Smuzhiyun rc = PTR_ERR(resp);
963*4882a593Smuzhiyun resp = NULL;
964*4882a593Smuzhiyun goto exit;
965*4882a593Smuzhiyun }
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) {
968*4882a593Smuzhiyun rc = digital_skb_check_crc_a(resp);
969*4882a593Smuzhiyun if (rc) {
970*4882a593Smuzhiyun PROTOCOL_ERR("4.4.1.3");
971*4882a593Smuzhiyun goto exit;
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun /* Silently ignore SEL_REQ content and send a SEL_RES for NFC-DEP */
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun rc = digital_tg_send_sel_res(ddev);
978*4882a593Smuzhiyun
979*4882a593Smuzhiyun exit:
980*4882a593Smuzhiyun if (rc)
981*4882a593Smuzhiyun digital_poll_next_tech(ddev);
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun dev_kfree_skb(resp);
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun
digital_tg_send_sdd_res(struct nfc_digital_dev * ddev)986*4882a593Smuzhiyun static int digital_tg_send_sdd_res(struct nfc_digital_dev *ddev)
987*4882a593Smuzhiyun {
988*4882a593Smuzhiyun struct sk_buff *skb;
989*4882a593Smuzhiyun struct digital_sdd_res *sdd_res;
990*4882a593Smuzhiyun int rc, i;
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, sizeof(struct digital_sdd_res));
993*4882a593Smuzhiyun if (!skb)
994*4882a593Smuzhiyun return -ENOMEM;
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun skb_put(skb, sizeof(struct digital_sdd_res));
997*4882a593Smuzhiyun sdd_res = (struct digital_sdd_res *)skb->data;
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun sdd_res->nfcid1[0] = 0x08;
1000*4882a593Smuzhiyun get_random_bytes(sdd_res->nfcid1 + 1, 3);
1001*4882a593Smuzhiyun
1002*4882a593Smuzhiyun sdd_res->bcc = 0;
1003*4882a593Smuzhiyun for (i = 0; i < 4; i++)
1004*4882a593Smuzhiyun sdd_res->bcc ^= sdd_res->nfcid1[i];
1005*4882a593Smuzhiyun
1006*4882a593Smuzhiyun rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
1007*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A);
1008*4882a593Smuzhiyun if (rc) {
1009*4882a593Smuzhiyun kfree_skb(skb);
1010*4882a593Smuzhiyun return rc;
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sel_req,
1014*4882a593Smuzhiyun NULL);
1015*4882a593Smuzhiyun if (rc)
1016*4882a593Smuzhiyun kfree_skb(skb);
1017*4882a593Smuzhiyun
1018*4882a593Smuzhiyun return rc;
1019*4882a593Smuzhiyun }
1020*4882a593Smuzhiyun
digital_tg_recv_sdd_req(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)1021*4882a593Smuzhiyun static void digital_tg_recv_sdd_req(struct nfc_digital_dev *ddev, void *arg,
1022*4882a593Smuzhiyun struct sk_buff *resp)
1023*4882a593Smuzhiyun {
1024*4882a593Smuzhiyun u8 *sdd_req;
1025*4882a593Smuzhiyun int rc;
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun if (IS_ERR(resp)) {
1028*4882a593Smuzhiyun rc = PTR_ERR(resp);
1029*4882a593Smuzhiyun resp = NULL;
1030*4882a593Smuzhiyun goto exit;
1031*4882a593Smuzhiyun }
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun sdd_req = resp->data;
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun if (resp->len < 2 || sdd_req[0] != DIGITAL_CMD_SEL_REQ_CL1 ||
1036*4882a593Smuzhiyun sdd_req[1] != DIGITAL_SDD_REQ_SEL_PAR) {
1037*4882a593Smuzhiyun rc = -EINVAL;
1038*4882a593Smuzhiyun goto exit;
1039*4882a593Smuzhiyun }
1040*4882a593Smuzhiyun
1041*4882a593Smuzhiyun rc = digital_tg_send_sdd_res(ddev);
1042*4882a593Smuzhiyun
1043*4882a593Smuzhiyun exit:
1044*4882a593Smuzhiyun if (rc)
1045*4882a593Smuzhiyun digital_poll_next_tech(ddev);
1046*4882a593Smuzhiyun
1047*4882a593Smuzhiyun dev_kfree_skb(resp);
1048*4882a593Smuzhiyun }
1049*4882a593Smuzhiyun
digital_tg_send_sens_res(struct nfc_digital_dev * ddev)1050*4882a593Smuzhiyun static int digital_tg_send_sens_res(struct nfc_digital_dev *ddev)
1051*4882a593Smuzhiyun {
1052*4882a593Smuzhiyun struct sk_buff *skb;
1053*4882a593Smuzhiyun u8 *sens_res;
1054*4882a593Smuzhiyun int rc;
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, 2);
1057*4882a593Smuzhiyun if (!skb)
1058*4882a593Smuzhiyun return -ENOMEM;
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun sens_res = skb_put(skb, 2);
1061*4882a593Smuzhiyun
1062*4882a593Smuzhiyun sens_res[0] = (DIGITAL_SENS_RES_NFC_DEP >> 8) & 0xFF;
1063*4882a593Smuzhiyun sens_res[1] = DIGITAL_SENS_RES_NFC_DEP & 0xFF;
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
1066*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_NFCA_STANDARD);
1067*4882a593Smuzhiyun if (rc) {
1068*4882a593Smuzhiyun kfree_skb(skb);
1069*4882a593Smuzhiyun return rc;
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun
1072*4882a593Smuzhiyun rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sdd_req,
1073*4882a593Smuzhiyun NULL);
1074*4882a593Smuzhiyun if (rc)
1075*4882a593Smuzhiyun kfree_skb(skb);
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun return rc;
1078*4882a593Smuzhiyun }
1079*4882a593Smuzhiyun
digital_tg_recv_sens_req(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)1080*4882a593Smuzhiyun void digital_tg_recv_sens_req(struct nfc_digital_dev *ddev, void *arg,
1081*4882a593Smuzhiyun struct sk_buff *resp)
1082*4882a593Smuzhiyun {
1083*4882a593Smuzhiyun u8 sens_req;
1084*4882a593Smuzhiyun int rc;
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun if (IS_ERR(resp)) {
1087*4882a593Smuzhiyun rc = PTR_ERR(resp);
1088*4882a593Smuzhiyun resp = NULL;
1089*4882a593Smuzhiyun goto exit;
1090*4882a593Smuzhiyun }
1091*4882a593Smuzhiyun
1092*4882a593Smuzhiyun sens_req = resp->data[0];
1093*4882a593Smuzhiyun
1094*4882a593Smuzhiyun if (!resp->len || (sens_req != DIGITAL_CMD_SENS_REQ &&
1095*4882a593Smuzhiyun sens_req != DIGITAL_CMD_ALL_REQ)) {
1096*4882a593Smuzhiyun rc = -EINVAL;
1097*4882a593Smuzhiyun goto exit;
1098*4882a593Smuzhiyun }
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun rc = digital_tg_send_sens_res(ddev);
1101*4882a593Smuzhiyun
1102*4882a593Smuzhiyun exit:
1103*4882a593Smuzhiyun if (rc)
1104*4882a593Smuzhiyun digital_poll_next_tech(ddev);
1105*4882a593Smuzhiyun
1106*4882a593Smuzhiyun dev_kfree_skb(resp);
1107*4882a593Smuzhiyun }
1108*4882a593Smuzhiyun
digital_tg_recv_atr_or_sensf_req(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)1109*4882a593Smuzhiyun static void digital_tg_recv_atr_or_sensf_req(struct nfc_digital_dev *ddev,
1110*4882a593Smuzhiyun void *arg, struct sk_buff *resp)
1111*4882a593Smuzhiyun {
1112*4882a593Smuzhiyun if (!IS_ERR(resp) && (resp->len >= 2) &&
1113*4882a593Smuzhiyun (resp->data[1] == DIGITAL_CMD_SENSF_REQ))
1114*4882a593Smuzhiyun digital_tg_recv_sensf_req(ddev, arg, resp);
1115*4882a593Smuzhiyun else
1116*4882a593Smuzhiyun digital_tg_recv_atr_req(ddev, arg, resp);
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun return;
1119*4882a593Smuzhiyun }
1120*4882a593Smuzhiyun
digital_tg_send_sensf_res(struct nfc_digital_dev * ddev,struct digital_sensf_req * sensf_req)1121*4882a593Smuzhiyun static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev,
1122*4882a593Smuzhiyun struct digital_sensf_req *sensf_req)
1123*4882a593Smuzhiyun {
1124*4882a593Smuzhiyun struct sk_buff *skb;
1125*4882a593Smuzhiyun u8 size;
1126*4882a593Smuzhiyun int rc;
1127*4882a593Smuzhiyun struct digital_sensf_res *sensf_res;
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun size = sizeof(struct digital_sensf_res);
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun if (sensf_req->rc == DIGITAL_SENSF_REQ_RC_NONE)
1132*4882a593Smuzhiyun size -= sizeof(sensf_res->rd);
1133*4882a593Smuzhiyun
1134*4882a593Smuzhiyun skb = digital_skb_alloc(ddev, size);
1135*4882a593Smuzhiyun if (!skb)
1136*4882a593Smuzhiyun return -ENOMEM;
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun skb_put(skb, size);
1139*4882a593Smuzhiyun
1140*4882a593Smuzhiyun sensf_res = (struct digital_sensf_res *)skb->data;
1141*4882a593Smuzhiyun
1142*4882a593Smuzhiyun memset(sensf_res, 0, size);
1143*4882a593Smuzhiyun
1144*4882a593Smuzhiyun sensf_res->cmd = DIGITAL_CMD_SENSF_RES;
1145*4882a593Smuzhiyun sensf_res->nfcid2[0] = DIGITAL_SENSF_NFCID2_NFC_DEP_B1;
1146*4882a593Smuzhiyun sensf_res->nfcid2[1] = DIGITAL_SENSF_NFCID2_NFC_DEP_B2;
1147*4882a593Smuzhiyun get_random_bytes(&sensf_res->nfcid2[2], 6);
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun switch (sensf_req->rc) {
1150*4882a593Smuzhiyun case DIGITAL_SENSF_REQ_RC_SC:
1151*4882a593Smuzhiyun sensf_res->rd[0] = sensf_req->sc1;
1152*4882a593Smuzhiyun sensf_res->rd[1] = sensf_req->sc2;
1153*4882a593Smuzhiyun break;
1154*4882a593Smuzhiyun case DIGITAL_SENSF_REQ_RC_AP:
1155*4882a593Smuzhiyun sensf_res->rd[0] = DIGITAL_SENSF_RES_RD_AP_B1;
1156*4882a593Smuzhiyun sensf_res->rd[1] = DIGITAL_SENSF_RES_RD_AP_B2;
1157*4882a593Smuzhiyun break;
1158*4882a593Smuzhiyun }
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun *(u8 *)skb_push(skb, sizeof(u8)) = size + 1;
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun if (!DIGITAL_DRV_CAPS_TG_CRC(ddev))
1163*4882a593Smuzhiyun digital_skb_add_crc_f(skb);
1164*4882a593Smuzhiyun
1165*4882a593Smuzhiyun rc = digital_tg_send_cmd(ddev, skb, 300,
1166*4882a593Smuzhiyun digital_tg_recv_atr_or_sensf_req, NULL);
1167*4882a593Smuzhiyun if (rc)
1168*4882a593Smuzhiyun kfree_skb(skb);
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun return rc;
1171*4882a593Smuzhiyun }
1172*4882a593Smuzhiyun
digital_tg_recv_sensf_req(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)1173*4882a593Smuzhiyun void digital_tg_recv_sensf_req(struct nfc_digital_dev *ddev, void *arg,
1174*4882a593Smuzhiyun struct sk_buff *resp)
1175*4882a593Smuzhiyun {
1176*4882a593Smuzhiyun struct digital_sensf_req *sensf_req;
1177*4882a593Smuzhiyun int rc;
1178*4882a593Smuzhiyun
1179*4882a593Smuzhiyun if (IS_ERR(resp)) {
1180*4882a593Smuzhiyun rc = PTR_ERR(resp);
1181*4882a593Smuzhiyun resp = NULL;
1182*4882a593Smuzhiyun goto exit;
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun
1185*4882a593Smuzhiyun if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) {
1186*4882a593Smuzhiyun rc = digital_skb_check_crc_f(resp);
1187*4882a593Smuzhiyun if (rc) {
1188*4882a593Smuzhiyun PROTOCOL_ERR("6.4.1.8");
1189*4882a593Smuzhiyun goto exit;
1190*4882a593Smuzhiyun }
1191*4882a593Smuzhiyun }
1192*4882a593Smuzhiyun
1193*4882a593Smuzhiyun if (resp->len != sizeof(struct digital_sensf_req) + 1) {
1194*4882a593Smuzhiyun rc = -EINVAL;
1195*4882a593Smuzhiyun goto exit;
1196*4882a593Smuzhiyun }
1197*4882a593Smuzhiyun
1198*4882a593Smuzhiyun skb_pull(resp, 1);
1199*4882a593Smuzhiyun sensf_req = (struct digital_sensf_req *)resp->data;
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun if (sensf_req->cmd != DIGITAL_CMD_SENSF_REQ) {
1202*4882a593Smuzhiyun rc = -EINVAL;
1203*4882a593Smuzhiyun goto exit;
1204*4882a593Smuzhiyun }
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun rc = digital_tg_send_sensf_res(ddev, sensf_req);
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun exit:
1209*4882a593Smuzhiyun if (rc)
1210*4882a593Smuzhiyun digital_poll_next_tech(ddev);
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun dev_kfree_skb(resp);
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun
digital_tg_config_nfca(struct nfc_digital_dev * ddev)1215*4882a593Smuzhiyun static int digital_tg_config_nfca(struct nfc_digital_dev *ddev)
1216*4882a593Smuzhiyun {
1217*4882a593Smuzhiyun int rc;
1218*4882a593Smuzhiyun
1219*4882a593Smuzhiyun rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
1220*4882a593Smuzhiyun NFC_DIGITAL_RF_TECH_106A);
1221*4882a593Smuzhiyun if (rc)
1222*4882a593Smuzhiyun return rc;
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun return digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
1225*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_NFCA_NFC_DEP);
1226*4882a593Smuzhiyun }
1227*4882a593Smuzhiyun
digital_tg_listen_nfca(struct nfc_digital_dev * ddev,u8 rf_tech)1228*4882a593Smuzhiyun int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech)
1229*4882a593Smuzhiyun {
1230*4882a593Smuzhiyun int rc;
1231*4882a593Smuzhiyun
1232*4882a593Smuzhiyun rc = digital_tg_config_nfca(ddev);
1233*4882a593Smuzhiyun if (rc)
1234*4882a593Smuzhiyun return rc;
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun return digital_tg_listen(ddev, 300, digital_tg_recv_sens_req, NULL);
1237*4882a593Smuzhiyun }
1238*4882a593Smuzhiyun
digital_tg_config_nfcf(struct nfc_digital_dev * ddev,u8 rf_tech)1239*4882a593Smuzhiyun static int digital_tg_config_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech)
1240*4882a593Smuzhiyun {
1241*4882a593Smuzhiyun int rc;
1242*4882a593Smuzhiyun
1243*4882a593Smuzhiyun rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
1244*4882a593Smuzhiyun if (rc)
1245*4882a593Smuzhiyun return rc;
1246*4882a593Smuzhiyun
1247*4882a593Smuzhiyun return digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
1248*4882a593Smuzhiyun NFC_DIGITAL_FRAMING_NFCF_NFC_DEP);
1249*4882a593Smuzhiyun }
1250*4882a593Smuzhiyun
digital_tg_listen_nfcf(struct nfc_digital_dev * ddev,u8 rf_tech)1251*4882a593Smuzhiyun int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech)
1252*4882a593Smuzhiyun {
1253*4882a593Smuzhiyun int rc;
1254*4882a593Smuzhiyun
1255*4882a593Smuzhiyun rc = digital_tg_config_nfcf(ddev, rf_tech);
1256*4882a593Smuzhiyun if (rc)
1257*4882a593Smuzhiyun return rc;
1258*4882a593Smuzhiyun
1259*4882a593Smuzhiyun return digital_tg_listen(ddev, 300, digital_tg_recv_sensf_req, NULL);
1260*4882a593Smuzhiyun }
1261*4882a593Smuzhiyun
digital_tg_recv_md_req(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)1262*4882a593Smuzhiyun void digital_tg_recv_md_req(struct nfc_digital_dev *ddev, void *arg,
1263*4882a593Smuzhiyun struct sk_buff *resp)
1264*4882a593Smuzhiyun {
1265*4882a593Smuzhiyun u8 rf_tech;
1266*4882a593Smuzhiyun int rc;
1267*4882a593Smuzhiyun
1268*4882a593Smuzhiyun if (IS_ERR(resp)) {
1269*4882a593Smuzhiyun resp = NULL;
1270*4882a593Smuzhiyun goto exit_free_skb;
1271*4882a593Smuzhiyun }
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun rc = ddev->ops->tg_get_rf_tech(ddev, &rf_tech);
1274*4882a593Smuzhiyun if (rc)
1275*4882a593Smuzhiyun goto exit_free_skb;
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun switch (rf_tech) {
1278*4882a593Smuzhiyun case NFC_DIGITAL_RF_TECH_106A:
1279*4882a593Smuzhiyun rc = digital_tg_config_nfca(ddev);
1280*4882a593Smuzhiyun if (rc)
1281*4882a593Smuzhiyun goto exit_free_skb;
1282*4882a593Smuzhiyun digital_tg_recv_sens_req(ddev, arg, resp);
1283*4882a593Smuzhiyun break;
1284*4882a593Smuzhiyun case NFC_DIGITAL_RF_TECH_212F:
1285*4882a593Smuzhiyun case NFC_DIGITAL_RF_TECH_424F:
1286*4882a593Smuzhiyun rc = digital_tg_config_nfcf(ddev, rf_tech);
1287*4882a593Smuzhiyun if (rc)
1288*4882a593Smuzhiyun goto exit_free_skb;
1289*4882a593Smuzhiyun digital_tg_recv_sensf_req(ddev, arg, resp);
1290*4882a593Smuzhiyun break;
1291*4882a593Smuzhiyun default:
1292*4882a593Smuzhiyun goto exit_free_skb;
1293*4882a593Smuzhiyun }
1294*4882a593Smuzhiyun
1295*4882a593Smuzhiyun return;
1296*4882a593Smuzhiyun
1297*4882a593Smuzhiyun exit_free_skb:
1298*4882a593Smuzhiyun digital_poll_next_tech(ddev);
1299*4882a593Smuzhiyun dev_kfree_skb(resp);
1300*4882a593Smuzhiyun }
1301