12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27d0911c0SThierry Escande /*
37d0911c0SThierry Escande * NFC Digital Protocol stack
47d0911c0SThierry Escande * Copyright (c) 2013, Intel Corporation.
57d0911c0SThierry Escande */
67d0911c0SThierry Escande
7c5da0e4aSSamuel Ortiz #define pr_fmt(fmt) "digital: %s: " fmt, __func__
8c5da0e4aSSamuel Ortiz
97d0911c0SThierry Escande #include "digital.h"
107d0911c0SThierry Escande
11a80509c7SMark A. Greer #define DIGITAL_NFC_DEP_N_RETRY_NACK 2
12384ab1d1SMark A. Greer #define DIGITAL_NFC_DEP_N_RETRY_ATN 2
13a80509c7SMark A. Greer
147d0911c0SThierry Escande #define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4
157d0911c0SThierry Escande #define DIGITAL_NFC_DEP_FRAME_DIR_IN 0xD5
167d0911c0SThierry Escande
177d0911c0SThierry Escande #define DIGITAL_NFC_DEP_NFCA_SOD_SB 0xF0
187d0911c0SThierry Escande
197d0911c0SThierry Escande #define DIGITAL_CMD_ATR_REQ 0x00
207d0911c0SThierry Escande #define DIGITAL_CMD_ATR_RES 0x01
217d0911c0SThierry Escande #define DIGITAL_CMD_PSL_REQ 0x04
227d0911c0SThierry Escande #define DIGITAL_CMD_PSL_RES 0x05
237d0911c0SThierry Escande #define DIGITAL_CMD_DEP_REQ 0x06
247d0911c0SThierry Escande #define DIGITAL_CMD_DEP_RES 0x07
257d0911c0SThierry Escande
267d0911c0SThierry Escande #define DIGITAL_ATR_REQ_MIN_SIZE 16
277d0911c0SThierry Escande #define DIGITAL_ATR_REQ_MAX_SIZE 64
287d0911c0SThierry Escande
291a09c56fSThierry Escande #define DIGITAL_ATR_RES_TO_WT(s) ((s) & 0xF)
301a09c56fSThierry Escande
3105afedcbSMark A. Greer #define DIGITAL_DID_MAX 14
3205afedcbSMark A. Greer
33b08147cbSMark A. Greer #define DIGITAL_PAYLOAD_SIZE_MAX 254
34b08147cbSMark A. Greer #define DIGITAL_PAYLOAD_BITS_TO_PP(s) (((s) & 0x3) << 4)
35b08147cbSMark A. Greer #define DIGITAL_PAYLOAD_PP_TO_BITS(s) (((s) >> 4) & 0x3)
36b08147cbSMark A. Greer #define DIGITAL_PAYLOAD_BITS_TO_FSL(s) ((s) & 0x3)
37b08147cbSMark A. Greer #define DIGITAL_PAYLOAD_FSL_TO_BITS(s) ((s) & 0x3)
38b08147cbSMark A. Greer
397d0911c0SThierry Escande #define DIGITAL_GB_BIT 0x02
407d0911c0SThierry Escande
417d0911c0SThierry Escande #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
427d0911c0SThierry Escande
437d0911c0SThierry Escande #define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10
443bd2a5bcSMark A. Greer #define DIGITAL_NFC_DEP_PFB_MI_BIT 0x10
453bd2a5bcSMark A. Greer #define DIGITAL_NFC_DEP_PFB_NACK_BIT 0x10
4605afedcbSMark A. Greer #define DIGITAL_NFC_DEP_PFB_DID_BIT 0x04
477d0911c0SThierry Escande
487d0911c0SThierry Escande #define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
497d0911c0SThierry Escande ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT)
503bd2a5bcSMark A. Greer #define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_MI_BIT)
513bd2a5bcSMark A. Greer #define DIGITAL_NFC_DEP_NACK_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_NACK_BIT)
527d0911c0SThierry Escande #define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
5305afedcbSMark A. Greer #define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT)
547d0911c0SThierry Escande #define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03)
557d0911c0SThierry Escande
56d85a301cSThierry Escande #define DIGITAL_NFC_DEP_RTOX_VALUE(data) ((data) & 0x3F)
57d85a301cSThierry Escande #define DIGITAL_NFC_DEP_RTOX_MAX 59
58d85a301cSThierry Escande
597d0911c0SThierry Escande #define DIGITAL_NFC_DEP_PFB_I_PDU 0x00
607d0911c0SThierry Escande #define DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU 0x40
617d0911c0SThierry Escande #define DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU 0x80
627d0911c0SThierry Escande
637d0911c0SThierry Escande struct digital_atr_req {
647d0911c0SThierry Escande u8 dir;
657d0911c0SThierry Escande u8 cmd;
667d0911c0SThierry Escande u8 nfcid3[10];
677d0911c0SThierry Escande u8 did;
687d0911c0SThierry Escande u8 bs;
697d0911c0SThierry Escande u8 br;
707d0911c0SThierry Escande u8 pp;
719814428aSGustavo A. R. Silva u8 gb[];
727d0911c0SThierry Escande } __packed;
737d0911c0SThierry Escande
747d0911c0SThierry Escande struct digital_atr_res {
757d0911c0SThierry Escande u8 dir;
767d0911c0SThierry Escande u8 cmd;
777d0911c0SThierry Escande u8 nfcid3[10];
787d0911c0SThierry Escande u8 did;
797d0911c0SThierry Escande u8 bs;
807d0911c0SThierry Escande u8 br;
817d0911c0SThierry Escande u8 to;
827d0911c0SThierry Escande u8 pp;
839814428aSGustavo A. R. Silva u8 gb[];
847d0911c0SThierry Escande } __packed;
857d0911c0SThierry Escande
867d0911c0SThierry Escande struct digital_psl_req {
877d0911c0SThierry Escande u8 dir;
887d0911c0SThierry Escande u8 cmd;
897d0911c0SThierry Escande u8 did;
907d0911c0SThierry Escande u8 brs;
917d0911c0SThierry Escande u8 fsl;
927d0911c0SThierry Escande } __packed;
937d0911c0SThierry Escande
947d0911c0SThierry Escande struct digital_psl_res {
957d0911c0SThierry Escande u8 dir;
967d0911c0SThierry Escande u8 cmd;
977d0911c0SThierry Escande u8 did;
987d0911c0SThierry Escande } __packed;
997d0911c0SThierry Escande
1007d0911c0SThierry Escande struct digital_dep_req_res {
1017d0911c0SThierry Escande u8 dir;
1027d0911c0SThierry Escande u8 cmd;
1037d0911c0SThierry Escande u8 pfb;
1047d0911c0SThierry Escande } __packed;
1057d0911c0SThierry Escande
1067d0911c0SThierry Escande static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
1077d0911c0SThierry Escande struct sk_buff *resp);
108c12715abSMark A. Greer static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
109c12715abSMark A. Greer struct sk_buff *resp);
1107d0911c0SThierry Escande
111b08147cbSMark A. Greer static const u8 digital_payload_bits_map[4] = {
112b08147cbSMark A. Greer [0] = 64,
113b08147cbSMark A. Greer [1] = 128,
114b08147cbSMark A. Greer [2] = 192,
115b08147cbSMark A. Greer [3] = 254
116b08147cbSMark A. Greer };
117b08147cbSMark A. Greer
1181a09c56fSThierry Escande /* Response Waiting Time for ATR_RES PDU in ms
1191a09c56fSThierry Escande *
1201a09c56fSThierry Escande * RWT(ATR_RES) = RWT(nfcdep,activation) + dRWT(nfcdep) + dT(nfcdep,initiator)
1211a09c56fSThierry Escande *
1221a09c56fSThierry Escande * with:
1231a09c56fSThierry Escande * RWT(nfcdep,activation) = 4096 * 2^12 / f(c) s
1241a09c56fSThierry Escande * dRWT(nfcdep) = 16 / f(c) s
1251a09c56fSThierry Escande * dT(nfcdep,initiator) = 100 ms
1261a09c56fSThierry Escande * f(c) = 13560000 Hz
1271a09c56fSThierry Escande */
1281a09c56fSThierry Escande #define DIGITAL_ATR_RES_RWT 1337
1291a09c56fSThierry Escande
1301a09c56fSThierry Escande /* Response Waiting Time for other DEP PDUs in ms
1311a09c56fSThierry Escande *
1321a09c56fSThierry Escande * max_rwt = rwt + dRWT(nfcdep) + dT(nfcdep,initiator)
1331a09c56fSThierry Escande *
1341a09c56fSThierry Escande * with:
1351a09c56fSThierry Escande * rwt = (256 * 16 / f(c)) * 2^wt s
1361a09c56fSThierry Escande * dRWT(nfcdep) = 16 / f(c) s
1371a09c56fSThierry Escande * dT(nfcdep,initiator) = 100 ms
1381a09c56fSThierry Escande * f(c) = 13560000 Hz
1391a09c56fSThierry Escande * 0 <= wt <= 14 (given by the target by the TO field of ATR_RES response)
1401a09c56fSThierry Escande */
1411a09c56fSThierry Escande #define DIGITAL_NFC_DEP_IN_MAX_WT 14
1421b609e43SMark Greer #define DIGITAL_NFC_DEP_TG_MAX_WT 14
1431a09c56fSThierry Escande static const u16 digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT + 1] = {
1441a09c56fSThierry Escande 100, 101, 101, 102, 105,
1451a09c56fSThierry Escande 110, 119, 139, 177, 255,
1461a09c56fSThierry Escande 409, 719, 1337, 2575, 5049,
1471a09c56fSThierry Escande };
1481a09c56fSThierry Escande
digital_payload_bits_to_size(u8 payload_bits)149b08147cbSMark A. Greer static u8 digital_payload_bits_to_size(u8 payload_bits)
150b08147cbSMark A. Greer {
151b08147cbSMark A. Greer if (payload_bits >= ARRAY_SIZE(digital_payload_bits_map))
152b08147cbSMark A. Greer return 0;
153b08147cbSMark A. Greer
154b08147cbSMark A. Greer return digital_payload_bits_map[payload_bits];
155b08147cbSMark A. Greer }
156b08147cbSMark A. Greer
digital_payload_size_to_bits(u8 payload_size)157b08147cbSMark A. Greer static u8 digital_payload_size_to_bits(u8 payload_size)
158b08147cbSMark A. Greer {
159b08147cbSMark A. Greer int i;
160b08147cbSMark A. Greer
161b08147cbSMark A. Greer for (i = 0; i < ARRAY_SIZE(digital_payload_bits_map); i++)
162b08147cbSMark A. Greer if (digital_payload_bits_map[i] == payload_size)
163b08147cbSMark A. Greer return i;
164b08147cbSMark A. Greer
165b08147cbSMark A. Greer return 0xff;
166b08147cbSMark A. Greer }
167b08147cbSMark A. Greer
digital_skb_push_dep_sod(struct nfc_digital_dev * ddev,struct sk_buff * skb)1687d0911c0SThierry Escande static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev,
1697d0911c0SThierry Escande struct sk_buff *skb)
1707d0911c0SThierry Escande {
1717d0911c0SThierry Escande skb_push(skb, sizeof(u8));
1727d0911c0SThierry Escande
1737d0911c0SThierry Escande skb->data[0] = skb->len;
1747d0911c0SThierry Escande
1757d0911c0SThierry Escande if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
176d58ff351SJohannes Berg *(u8 *)skb_push(skb, sizeof(u8)) = DIGITAL_NFC_DEP_NFCA_SOD_SB;
1777d0911c0SThierry Escande }
1787d0911c0SThierry Escande
digital_skb_pull_dep_sod(struct nfc_digital_dev * ddev,struct sk_buff * skb)1797d0911c0SThierry Escande static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev,
1807d0911c0SThierry Escande struct sk_buff *skb)
1817d0911c0SThierry Escande {
1827d0911c0SThierry Escande u8 size;
1837d0911c0SThierry Escande
1847d0911c0SThierry Escande if (skb->len < 2)
1857d0911c0SThierry Escande return -EIO;
1867d0911c0SThierry Escande
1877d0911c0SThierry Escande if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
1887d0911c0SThierry Escande skb_pull(skb, sizeof(u8));
1897d0911c0SThierry Escande
1907d0911c0SThierry Escande size = skb->data[0];
1917d0911c0SThierry Escande if (size != skb->len)
1927d0911c0SThierry Escande return -EIO;
1937d0911c0SThierry Escande
1947d0911c0SThierry Escande skb_pull(skb, sizeof(u8));
1957d0911c0SThierry Escande
1967d0911c0SThierry Escande return 0;
1977d0911c0SThierry Escande }
1987d0911c0SThierry Escande
1993bd2a5bcSMark A. Greer static struct sk_buff *
digital_send_dep_data_prep(struct nfc_digital_dev * ddev,struct sk_buff * skb,struct digital_dep_req_res * dep_req_res,struct digital_data_exch * data_exch)2003bd2a5bcSMark A. Greer digital_send_dep_data_prep(struct nfc_digital_dev *ddev, struct sk_buff *skb,
2013bd2a5bcSMark A. Greer struct digital_dep_req_res *dep_req_res,
2023bd2a5bcSMark A. Greer struct digital_data_exch *data_exch)
2033bd2a5bcSMark A. Greer {
2043bd2a5bcSMark A. Greer struct sk_buff *new_skb;
2053bd2a5bcSMark A. Greer
2063bd2a5bcSMark A. Greer if (skb->len > ddev->remote_payload_max) {
2073bd2a5bcSMark A. Greer dep_req_res->pfb |= DIGITAL_NFC_DEP_PFB_MI_BIT;
2083bd2a5bcSMark A. Greer
2093bd2a5bcSMark A. Greer new_skb = digital_skb_alloc(ddev, ddev->remote_payload_max);
2103bd2a5bcSMark A. Greer if (!new_skb) {
2113bd2a5bcSMark A. Greer kfree_skb(ddev->chaining_skb);
2123bd2a5bcSMark A. Greer ddev->chaining_skb = NULL;
2133bd2a5bcSMark A. Greer
2143bd2a5bcSMark A. Greer return ERR_PTR(-ENOMEM);
2153bd2a5bcSMark A. Greer }
2163bd2a5bcSMark A. Greer
21759ae1d12SJohannes Berg skb_put_data(new_skb, skb->data, ddev->remote_payload_max);
2183bd2a5bcSMark A. Greer skb_pull(skb, ddev->remote_payload_max);
2193bd2a5bcSMark A. Greer
2203bd2a5bcSMark A. Greer ddev->chaining_skb = skb;
2213bd2a5bcSMark A. Greer ddev->data_exch = data_exch;
2223bd2a5bcSMark A. Greer } else {
2233bd2a5bcSMark A. Greer ddev->chaining_skb = NULL;
2243bd2a5bcSMark A. Greer new_skb = skb;
2253bd2a5bcSMark A. Greer }
2263bd2a5bcSMark A. Greer
2273bd2a5bcSMark A. Greer return new_skb;
2283bd2a5bcSMark A. Greer }
2293bd2a5bcSMark A. Greer
230c12715abSMark A. Greer static struct sk_buff *
digital_recv_dep_data_gather(struct nfc_digital_dev * ddev,u8 pfb,struct sk_buff * resp,int (* send_ack)(struct nfc_digital_dev * ddev,struct digital_data_exch * data_exch),struct digital_data_exch * data_exch)231c12715abSMark A. Greer digital_recv_dep_data_gather(struct nfc_digital_dev *ddev, u8 pfb,
232c12715abSMark A. Greer struct sk_buff *resp,
233c12715abSMark A. Greer int (*send_ack)(struct nfc_digital_dev *ddev,
234c12715abSMark A. Greer struct digital_data_exch
235c12715abSMark A. Greer *data_exch),
236c12715abSMark A. Greer struct digital_data_exch *data_exch)
237c12715abSMark A. Greer {
238c12715abSMark A. Greer struct sk_buff *new_skb;
239c12715abSMark A. Greer int rc;
240c12715abSMark A. Greer
241c12715abSMark A. Greer if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb) && (!ddev->chaining_skb)) {
242c12715abSMark A. Greer ddev->chaining_skb =
243c12715abSMark A. Greer nfc_alloc_recv_skb(8 * ddev->local_payload_max,
244c12715abSMark A. Greer GFP_KERNEL);
245c12715abSMark A. Greer if (!ddev->chaining_skb) {
246c12715abSMark A. Greer rc = -ENOMEM;
247c12715abSMark A. Greer goto error;
248c12715abSMark A. Greer }
249c12715abSMark A. Greer }
250c12715abSMark A. Greer
251c12715abSMark A. Greer if (ddev->chaining_skb) {
252c12715abSMark A. Greer if (resp->len > skb_tailroom(ddev->chaining_skb)) {
253c12715abSMark A. Greer new_skb = skb_copy_expand(ddev->chaining_skb,
254c12715abSMark A. Greer skb_headroom(
255c12715abSMark A. Greer ddev->chaining_skb),
256c12715abSMark A. Greer 8 * ddev->local_payload_max,
257c12715abSMark A. Greer GFP_KERNEL);
258c12715abSMark A. Greer if (!new_skb) {
259c12715abSMark A. Greer rc = -ENOMEM;
260c12715abSMark A. Greer goto error;
261c12715abSMark A. Greer }
262c12715abSMark A. Greer
263c12715abSMark A. Greer kfree_skb(ddev->chaining_skb);
264c12715abSMark A. Greer ddev->chaining_skb = new_skb;
265c12715abSMark A. Greer }
266c12715abSMark A. Greer
26759ae1d12SJohannes Berg skb_put_data(ddev->chaining_skb, resp->data, resp->len);
268c12715abSMark A. Greer
269c12715abSMark A. Greer kfree_skb(resp);
270c12715abSMark A. Greer resp = NULL;
271c12715abSMark A. Greer
272c12715abSMark A. Greer if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
273c12715abSMark A. Greer rc = send_ack(ddev, data_exch);
274c12715abSMark A. Greer if (rc)
275c12715abSMark A. Greer goto error;
276c12715abSMark A. Greer
277c12715abSMark A. Greer return NULL;
278c12715abSMark A. Greer }
279c12715abSMark A. Greer
280c12715abSMark A. Greer resp = ddev->chaining_skb;
281c12715abSMark A. Greer ddev->chaining_skb = NULL;
282c12715abSMark A. Greer }
283c12715abSMark A. Greer
284c12715abSMark A. Greer return resp;
285c12715abSMark A. Greer
286c12715abSMark A. Greer error:
287c12715abSMark A. Greer kfree_skb(resp);
288c12715abSMark A. Greer
289c12715abSMark A. Greer kfree_skb(ddev->chaining_skb);
290c12715abSMark A. Greer ddev->chaining_skb = NULL;
291c12715abSMark A. Greer
292c12715abSMark A. Greer return ERR_PTR(rc);
293c12715abSMark A. Greer }
294c12715abSMark A. Greer
digital_in_recv_psl_res(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)295dddb3da0SMark A. Greer static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg,
296dddb3da0SMark A. Greer struct sk_buff *resp)
297dddb3da0SMark A. Greer {
298dddb3da0SMark A. Greer struct nfc_target *target = arg;
299dddb3da0SMark A. Greer struct digital_psl_res *psl_res;
300dddb3da0SMark A. Greer int rc;
301dddb3da0SMark A. Greer
302dddb3da0SMark A. Greer if (IS_ERR(resp)) {
303dddb3da0SMark A. Greer rc = PTR_ERR(resp);
304dddb3da0SMark A. Greer resp = NULL;
305dddb3da0SMark A. Greer goto exit;
306dddb3da0SMark A. Greer }
307dddb3da0SMark A. Greer
308dddb3da0SMark A. Greer rc = ddev->skb_check_crc(resp);
309dddb3da0SMark A. Greer if (rc) {
310dddb3da0SMark A. Greer PROTOCOL_ERR("14.4.1.6");
311dddb3da0SMark A. Greer goto exit;
312dddb3da0SMark A. Greer }
313dddb3da0SMark A. Greer
314dddb3da0SMark A. Greer rc = digital_skb_pull_dep_sod(ddev, resp);
315dddb3da0SMark A. Greer if (rc) {
316dddb3da0SMark A. Greer PROTOCOL_ERR("14.4.1.2");
317dddb3da0SMark A. Greer goto exit;
318dddb3da0SMark A. Greer }
319dddb3da0SMark A. Greer
320dddb3da0SMark A. Greer psl_res = (struct digital_psl_res *)resp->data;
321dddb3da0SMark A. Greer
322dddb3da0SMark A. Greer if ((resp->len != sizeof(*psl_res)) ||
323dddb3da0SMark A. Greer (psl_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN) ||
324dddb3da0SMark A. Greer (psl_res->cmd != DIGITAL_CMD_PSL_RES)) {
325dddb3da0SMark A. Greer rc = -EIO;
326dddb3da0SMark A. Greer goto exit;
327dddb3da0SMark A. Greer }
328dddb3da0SMark A. Greer
329dddb3da0SMark A. Greer rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
330dddb3da0SMark A. Greer NFC_DIGITAL_RF_TECH_424F);
331dddb3da0SMark A. Greer if (rc)
332dddb3da0SMark A. Greer goto exit;
333dddb3da0SMark A. Greer
334dddb3da0SMark A. Greer rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
335dddb3da0SMark A. Greer NFC_DIGITAL_FRAMING_NFCF_NFC_DEP);
336dddb3da0SMark A. Greer if (rc)
337dddb3da0SMark A. Greer goto exit;
338dddb3da0SMark A. Greer
339dddb3da0SMark A. Greer if (!DIGITAL_DRV_CAPS_IN_CRC(ddev) &&
340dddb3da0SMark A. Greer (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)) {
341dddb3da0SMark A. Greer ddev->skb_add_crc = digital_skb_add_crc_f;
342dddb3da0SMark A. Greer ddev->skb_check_crc = digital_skb_check_crc_f;
343dddb3da0SMark A. Greer }
344dddb3da0SMark A. Greer
345dddb3da0SMark A. Greer ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_424F;
346dddb3da0SMark A. Greer
347dddb3da0SMark A. Greer nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
348dddb3da0SMark A. Greer NFC_RF_INITIATOR);
349dddb3da0SMark A. Greer
350dddb3da0SMark A. Greer ddev->curr_nfc_dep_pni = 0;
351dddb3da0SMark A. Greer
352dddb3da0SMark A. Greer exit:
353dddb3da0SMark A. Greer dev_kfree_skb(resp);
354dddb3da0SMark A. Greer
355dddb3da0SMark A. Greer if (rc)
356dddb3da0SMark A. Greer ddev->curr_protocol = 0;
357dddb3da0SMark A. Greer }
358dddb3da0SMark A. Greer
digital_in_send_psl_req(struct nfc_digital_dev * ddev,struct nfc_target * target)359dddb3da0SMark A. Greer static int digital_in_send_psl_req(struct nfc_digital_dev *ddev,
360dddb3da0SMark A. Greer struct nfc_target *target)
361dddb3da0SMark A. Greer {
362dddb3da0SMark A. Greer struct sk_buff *skb;
363dddb3da0SMark A. Greer struct digital_psl_req *psl_req;
364b15829baSMark A. Greer int rc;
365b08147cbSMark A. Greer u8 payload_size, payload_bits;
366dddb3da0SMark A. Greer
367dddb3da0SMark A. Greer skb = digital_skb_alloc(ddev, sizeof(*psl_req));
368dddb3da0SMark A. Greer if (!skb)
369dddb3da0SMark A. Greer return -ENOMEM;
370dddb3da0SMark A. Greer
371dddb3da0SMark A. Greer skb_put(skb, sizeof(*psl_req));
372dddb3da0SMark A. Greer
373dddb3da0SMark A. Greer psl_req = (struct digital_psl_req *)skb->data;
374dddb3da0SMark A. Greer
375dddb3da0SMark A. Greer psl_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
376dddb3da0SMark A. Greer psl_req->cmd = DIGITAL_CMD_PSL_REQ;
377dddb3da0SMark A. Greer psl_req->did = 0;
378dddb3da0SMark A. Greer psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */
379b08147cbSMark A. Greer
380b08147cbSMark A. Greer payload_size = min(ddev->local_payload_max, ddev->remote_payload_max);
381b08147cbSMark A. Greer payload_bits = digital_payload_size_to_bits(payload_size);
382b08147cbSMark A. Greer psl_req->fsl = DIGITAL_PAYLOAD_BITS_TO_FSL(payload_bits);
383b08147cbSMark A. Greer
384b08147cbSMark A. Greer ddev->local_payload_max = payload_size;
385b08147cbSMark A. Greer ddev->remote_payload_max = payload_size;
386dddb3da0SMark A. Greer
387dddb3da0SMark A. Greer digital_skb_push_dep_sod(ddev, skb);
388dddb3da0SMark A. Greer
389dddb3da0SMark A. Greer ddev->skb_add_crc(skb);
390dddb3da0SMark A. Greer
3911a09c56fSThierry Escande rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
3921a09c56fSThierry Escande digital_in_recv_psl_res, target);
393b15829baSMark A. Greer if (rc)
394b15829baSMark A. Greer kfree_skb(skb);
395b15829baSMark A. Greer
396b15829baSMark A. Greer return rc;
397dddb3da0SMark A. Greer }
398dddb3da0SMark A. Greer
digital_in_recv_atr_res(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)3997d0911c0SThierry Escande static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
4007d0911c0SThierry Escande struct sk_buff *resp)
4017d0911c0SThierry Escande {
4027d0911c0SThierry Escande struct nfc_target *target = arg;
4037d0911c0SThierry Escande struct digital_atr_res *atr_res;
404b08147cbSMark A. Greer u8 gb_len, payload_bits;
4051a09c56fSThierry Escande u8 wt;
4067d0911c0SThierry Escande int rc;
4077d0911c0SThierry Escande
4087d0911c0SThierry Escande if (IS_ERR(resp)) {
4097d0911c0SThierry Escande rc = PTR_ERR(resp);
4107d0911c0SThierry Escande resp = NULL;
4117d0911c0SThierry Escande goto exit;
4127d0911c0SThierry Escande }
4137d0911c0SThierry Escande
4147d0911c0SThierry Escande rc = ddev->skb_check_crc(resp);
4157d0911c0SThierry Escande if (rc) {
4167d0911c0SThierry Escande PROTOCOL_ERR("14.4.1.6");
4177d0911c0SThierry Escande goto exit;
4187d0911c0SThierry Escande }
4197d0911c0SThierry Escande
4207d0911c0SThierry Escande rc = digital_skb_pull_dep_sod(ddev, resp);
4217d0911c0SThierry Escande if (rc) {
4227d0911c0SThierry Escande PROTOCOL_ERR("14.4.1.2");
4237d0911c0SThierry Escande goto exit;
4247d0911c0SThierry Escande }
4257d0911c0SThierry Escande
4267d0911c0SThierry Escande if (resp->len < sizeof(struct digital_atr_res)) {
4277d0911c0SThierry Escande rc = -EIO;
4287d0911c0SThierry Escande goto exit;
4297d0911c0SThierry Escande }
4307d0911c0SThierry Escande
4317d0911c0SThierry Escande gb_len = resp->len - sizeof(struct digital_atr_res);
4327d0911c0SThierry Escande
4337d0911c0SThierry Escande atr_res = (struct digital_atr_res *)resp->data;
4347d0911c0SThierry Escande
4351a09c56fSThierry Escande wt = DIGITAL_ATR_RES_TO_WT(atr_res->to);
4361a09c56fSThierry Escande if (wt > DIGITAL_NFC_DEP_IN_MAX_WT)
4371a09c56fSThierry Escande wt = DIGITAL_NFC_DEP_IN_MAX_WT;
4381a09c56fSThierry Escande ddev->dep_rwt = digital_rwt_map[wt];
4391a09c56fSThierry Escande
440b08147cbSMark A. Greer payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_res->pp);
441b08147cbSMark A. Greer ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
442b08147cbSMark A. Greer
443b08147cbSMark A. Greer if (!ddev->remote_payload_max) {
444b08147cbSMark A. Greer rc = -EINVAL;
445b08147cbSMark A. Greer goto exit;
446b08147cbSMark A. Greer }
447b08147cbSMark A. Greer
4487d0911c0SThierry Escande rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len);
4497d0911c0SThierry Escande if (rc)
4507d0911c0SThierry Escande goto exit;
4517d0911c0SThierry Escande
452dddb3da0SMark A. Greer if ((ddev->protocols & NFC_PROTO_FELICA_MASK) &&
453dddb3da0SMark A. Greer (ddev->curr_rf_tech != NFC_DIGITAL_RF_TECH_424F)) {
454dddb3da0SMark A. Greer rc = digital_in_send_psl_req(ddev, target);
455dddb3da0SMark A. Greer if (!rc)
456dddb3da0SMark A. Greer goto exit;
457dddb3da0SMark A. Greer }
458dddb3da0SMark A. Greer
4597d0911c0SThierry Escande rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
4607d0911c0SThierry Escande NFC_RF_INITIATOR);
4617d0911c0SThierry Escande
4627d0911c0SThierry Escande ddev->curr_nfc_dep_pni = 0;
4637d0911c0SThierry Escande
4647d0911c0SThierry Escande exit:
4657d0911c0SThierry Escande dev_kfree_skb(resp);
4667d0911c0SThierry Escande
4677d0911c0SThierry Escande if (rc)
4687d0911c0SThierry Escande ddev->curr_protocol = 0;
4697d0911c0SThierry Escande }
4707d0911c0SThierry Escande
digital_in_send_atr_req(struct nfc_digital_dev * ddev,struct nfc_target * target,__u8 comm_mode,__u8 * gb,size_t gb_len)4717d0911c0SThierry Escande int digital_in_send_atr_req(struct nfc_digital_dev *ddev,
4727d0911c0SThierry Escande struct nfc_target *target, __u8 comm_mode, __u8 *gb,
4737d0911c0SThierry Escande size_t gb_len)
4747d0911c0SThierry Escande {
4757d0911c0SThierry Escande struct sk_buff *skb;
4767d0911c0SThierry Escande struct digital_atr_req *atr_req;
4777d0911c0SThierry Escande uint size;
478b15829baSMark A. Greer int rc;
479b08147cbSMark A. Greer u8 payload_bits;
4807d0911c0SThierry Escande
4817d0911c0SThierry Escande size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len;
4827d0911c0SThierry Escande
4837d0911c0SThierry Escande if (size > DIGITAL_ATR_REQ_MAX_SIZE) {
4847d0911c0SThierry Escande PROTOCOL_ERR("14.6.1.1");
4857d0911c0SThierry Escande return -EINVAL;
4867d0911c0SThierry Escande }
4877d0911c0SThierry Escande
4887d0911c0SThierry Escande skb = digital_skb_alloc(ddev, size);
4897d0911c0SThierry Escande if (!skb)
4907d0911c0SThierry Escande return -ENOMEM;
4917d0911c0SThierry Escande
4927d0911c0SThierry Escande skb_put(skb, sizeof(struct digital_atr_req));
4937d0911c0SThierry Escande
4947d0911c0SThierry Escande atr_req = (struct digital_atr_req *)skb->data;
4957d0911c0SThierry Escande memset(atr_req, 0, sizeof(struct digital_atr_req));
4967d0911c0SThierry Escande
4977d0911c0SThierry Escande atr_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
4987d0911c0SThierry Escande atr_req->cmd = DIGITAL_CMD_ATR_REQ;
4997d0911c0SThierry Escande if (target->nfcid2_len)
5004f319e32SThierry Escande memcpy(atr_req->nfcid3, target->nfcid2, NFC_NFCID2_MAXSIZE);
5017d0911c0SThierry Escande else
5024f319e32SThierry Escande get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE);
5037d0911c0SThierry Escande
5047d0911c0SThierry Escande atr_req->did = 0;
5057d0911c0SThierry Escande atr_req->bs = 0;
5067d0911c0SThierry Escande atr_req->br = 0;
5077d0911c0SThierry Escande
508b08147cbSMark A. Greer ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
509b08147cbSMark A. Greer payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
510b08147cbSMark A. Greer atr_req->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
5117d0911c0SThierry Escande
5127d0911c0SThierry Escande if (gb_len) {
5137d0911c0SThierry Escande atr_req->pp |= DIGITAL_GB_BIT;
51459ae1d12SJohannes Berg skb_put_data(skb, gb, gb_len);
5157d0911c0SThierry Escande }
5167d0911c0SThierry Escande
5177d0911c0SThierry Escande digital_skb_push_dep_sod(ddev, skb);
5187d0911c0SThierry Escande
5197d0911c0SThierry Escande ddev->skb_add_crc(skb);
5207d0911c0SThierry Escande
5211a09c56fSThierry Escande rc = digital_in_send_cmd(ddev, skb, DIGITAL_ATR_RES_RWT,
5221a09c56fSThierry Escande digital_in_recv_atr_res, target);
523b15829baSMark A. Greer if (rc)
524b15829baSMark A. Greer kfree_skb(skb);
525b15829baSMark A. Greer
526b15829baSMark A. Greer return rc;
5277d0911c0SThierry Escande }
5287d0911c0SThierry Escande
digital_in_send_ack(struct nfc_digital_dev * ddev,struct digital_data_exch * data_exch)529c12715abSMark A. Greer static int digital_in_send_ack(struct nfc_digital_dev *ddev,
530c12715abSMark A. Greer struct digital_data_exch *data_exch)
531c12715abSMark A. Greer {
532c12715abSMark A. Greer struct digital_dep_req_res *dep_req;
533c12715abSMark A. Greer struct sk_buff *skb;
534c12715abSMark A. Greer int rc;
535c12715abSMark A. Greer
536c12715abSMark A. Greer skb = digital_skb_alloc(ddev, 1);
537c12715abSMark A. Greer if (!skb)
538c12715abSMark A. Greer return -ENOMEM;
539c12715abSMark A. Greer
540c12715abSMark A. Greer skb_push(skb, sizeof(struct digital_dep_req_res));
541c12715abSMark A. Greer
542c12715abSMark A. Greer dep_req = (struct digital_dep_req_res *)skb->data;
543c12715abSMark A. Greer
544c12715abSMark A. Greer dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
545c12715abSMark A. Greer dep_req->cmd = DIGITAL_CMD_DEP_REQ;
546c12715abSMark A. Greer dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
547c12715abSMark A. Greer ddev->curr_nfc_dep_pni;
548c12715abSMark A. Greer
549c12715abSMark A. Greer digital_skb_push_dep_sod(ddev, skb);
550c12715abSMark A. Greer
551c12715abSMark A. Greer ddev->skb_add_crc(skb);
552c12715abSMark A. Greer
5531d984c2eSThierry Escande ddev->saved_skb = pskb_copy(skb, GFP_KERNEL);
554384ab1d1SMark A. Greer
5551a09c56fSThierry Escande rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
5561a09c56fSThierry Escande digital_in_recv_dep_res, data_exch);
557384ab1d1SMark A. Greer if (rc) {
558c12715abSMark A. Greer kfree_skb(skb);
559384ab1d1SMark A. Greer kfree_skb(ddev->saved_skb);
560384ab1d1SMark A. Greer ddev->saved_skb = NULL;
561384ab1d1SMark A. Greer }
562c12715abSMark A. Greer
563c12715abSMark A. Greer return rc;
564c12715abSMark A. Greer }
565c12715abSMark A. Greer
digital_in_send_nack(struct nfc_digital_dev * ddev,struct digital_data_exch * data_exch)566a80509c7SMark A. Greer static int digital_in_send_nack(struct nfc_digital_dev *ddev,
567a80509c7SMark A. Greer struct digital_data_exch *data_exch)
568a80509c7SMark A. Greer {
569a80509c7SMark A. Greer struct digital_dep_req_res *dep_req;
570a80509c7SMark A. Greer struct sk_buff *skb;
571a80509c7SMark A. Greer int rc;
572a80509c7SMark A. Greer
573a80509c7SMark A. Greer skb = digital_skb_alloc(ddev, 1);
574a80509c7SMark A. Greer if (!skb)
575a80509c7SMark A. Greer return -ENOMEM;
576a80509c7SMark A. Greer
577a80509c7SMark A. Greer skb_push(skb, sizeof(struct digital_dep_req_res));
578a80509c7SMark A. Greer
579a80509c7SMark A. Greer dep_req = (struct digital_dep_req_res *)skb->data;
580a80509c7SMark A. Greer
581a80509c7SMark A. Greer dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
582a80509c7SMark A. Greer dep_req->cmd = DIGITAL_CMD_DEP_REQ;
583a80509c7SMark A. Greer dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
584a80509c7SMark A. Greer DIGITAL_NFC_DEP_PFB_NACK_BIT | ddev->curr_nfc_dep_pni;
585a80509c7SMark A. Greer
586a80509c7SMark A. Greer digital_skb_push_dep_sod(ddev, skb);
587a80509c7SMark A. Greer
588a80509c7SMark A. Greer ddev->skb_add_crc(skb);
589a80509c7SMark A. Greer
5901a09c56fSThierry Escande rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
5911a09c56fSThierry Escande digital_in_recv_dep_res, data_exch);
592a80509c7SMark A. Greer if (rc)
593a80509c7SMark A. Greer kfree_skb(skb);
594a80509c7SMark A. Greer
595a80509c7SMark A. Greer return rc;
596a80509c7SMark A. Greer }
597a80509c7SMark A. Greer
digital_in_send_atn(struct nfc_digital_dev * ddev,struct digital_data_exch * data_exch)598384ab1d1SMark A. Greer static int digital_in_send_atn(struct nfc_digital_dev *ddev,
599384ab1d1SMark A. Greer struct digital_data_exch *data_exch)
600384ab1d1SMark A. Greer {
601384ab1d1SMark A. Greer struct digital_dep_req_res *dep_req;
602384ab1d1SMark A. Greer struct sk_buff *skb;
603384ab1d1SMark A. Greer int rc;
604384ab1d1SMark A. Greer
605384ab1d1SMark A. Greer skb = digital_skb_alloc(ddev, 1);
606384ab1d1SMark A. Greer if (!skb)
607384ab1d1SMark A. Greer return -ENOMEM;
608384ab1d1SMark A. Greer
609384ab1d1SMark A. Greer skb_push(skb, sizeof(struct digital_dep_req_res));
610384ab1d1SMark A. Greer
611384ab1d1SMark A. Greer dep_req = (struct digital_dep_req_res *)skb->data;
612384ab1d1SMark A. Greer
613384ab1d1SMark A. Greer dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
614384ab1d1SMark A. Greer dep_req->cmd = DIGITAL_CMD_DEP_REQ;
615384ab1d1SMark A. Greer dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
616384ab1d1SMark A. Greer
617384ab1d1SMark A. Greer digital_skb_push_dep_sod(ddev, skb);
618384ab1d1SMark A. Greer
619384ab1d1SMark A. Greer ddev->skb_add_crc(skb);
620384ab1d1SMark A. Greer
6211a09c56fSThierry Escande rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
6221a09c56fSThierry Escande digital_in_recv_dep_res, data_exch);
623384ab1d1SMark A. Greer if (rc)
624384ab1d1SMark A. Greer kfree_skb(skb);
625384ab1d1SMark A. Greer
626384ab1d1SMark A. Greer return rc;
627384ab1d1SMark A. Greer }
628384ab1d1SMark A. Greer
digital_in_send_rtox(struct nfc_digital_dev * ddev,struct digital_data_exch * data_exch,u8 rtox)6297d0911c0SThierry Escande static int digital_in_send_rtox(struct nfc_digital_dev *ddev,
6307d0911c0SThierry Escande struct digital_data_exch *data_exch, u8 rtox)
6317d0911c0SThierry Escande {
6327d0911c0SThierry Escande struct digital_dep_req_res *dep_req;
6337d0911c0SThierry Escande struct sk_buff *skb;
6347d0911c0SThierry Escande int rc;
635d85a301cSThierry Escande u16 rwt_int;
636d85a301cSThierry Escande
637d85a301cSThierry Escande rwt_int = ddev->dep_rwt * rtox;
638d85a301cSThierry Escande if (rwt_int > digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT])
639d85a301cSThierry Escande rwt_int = digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT];
6407d0911c0SThierry Escande
6417d0911c0SThierry Escande skb = digital_skb_alloc(ddev, 1);
6427d0911c0SThierry Escande if (!skb)
6437d0911c0SThierry Escande return -ENOMEM;
6447d0911c0SThierry Escande
645634fef61SJohannes Berg skb_put_u8(skb, rtox);
6467d0911c0SThierry Escande
6477d0911c0SThierry Escande skb_push(skb, sizeof(struct digital_dep_req_res));
6487d0911c0SThierry Escande
6497d0911c0SThierry Escande dep_req = (struct digital_dep_req_res *)skb->data;
6507d0911c0SThierry Escande
6517d0911c0SThierry Escande dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
6527d0911c0SThierry Escande dep_req->cmd = DIGITAL_CMD_DEP_REQ;
6537d0911c0SThierry Escande dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU |
6547d0911c0SThierry Escande DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT;
6557d0911c0SThierry Escande
6567d0911c0SThierry Escande digital_skb_push_dep_sod(ddev, skb);
6577d0911c0SThierry Escande
6587d0911c0SThierry Escande ddev->skb_add_crc(skb);
6597d0911c0SThierry Escande
660d85a301cSThierry Escande rc = digital_in_send_cmd(ddev, skb, rwt_int,
6611a09c56fSThierry Escande digital_in_recv_dep_res, data_exch);
6621d984c2eSThierry Escande if (rc)
663b15829baSMark A. Greer kfree_skb(skb);
6647d0911c0SThierry Escande
6657d0911c0SThierry Escande return rc;
6667d0911c0SThierry Escande }
6677d0911c0SThierry Escande
digital_in_send_saved_skb(struct nfc_digital_dev * ddev,struct digital_data_exch * data_exch)668384ab1d1SMark A. Greer static int digital_in_send_saved_skb(struct nfc_digital_dev *ddev,
669384ab1d1SMark A. Greer struct digital_data_exch *data_exch)
670384ab1d1SMark A. Greer {
6711d984c2eSThierry Escande int rc;
672384ab1d1SMark A. Greer
6731d984c2eSThierry Escande if (!ddev->saved_skb)
6741d984c2eSThierry Escande return -EINVAL;
6751d984c2eSThierry Escande
6761d984c2eSThierry Escande skb_get(ddev->saved_skb);
6771d984c2eSThierry Escande
6781a09c56fSThierry Escande rc = digital_in_send_cmd(ddev, ddev->saved_skb, ddev->dep_rwt,
679384ab1d1SMark A. Greer digital_in_recv_dep_res, data_exch);
6801d984c2eSThierry Escande if (rc)
6811d984c2eSThierry Escande kfree_skb(ddev->saved_skb);
6821d984c2eSThierry Escande
6831d984c2eSThierry Escande return rc;
684384ab1d1SMark A. Greer }
685384ab1d1SMark A. Greer
digital_in_recv_dep_res(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)6867d0911c0SThierry Escande static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
6877d0911c0SThierry Escande struct sk_buff *resp)
6887d0911c0SThierry Escande {
6897d0911c0SThierry Escande struct digital_data_exch *data_exch = arg;
6907d0911c0SThierry Escande struct digital_dep_req_res *dep_res;
6917d0911c0SThierry Escande u8 pfb;
6927d0911c0SThierry Escande uint size;
6937d0911c0SThierry Escande int rc;
694d85a301cSThierry Escande u8 rtox;
6957d0911c0SThierry Escande
6967d0911c0SThierry Escande if (IS_ERR(resp)) {
6977d0911c0SThierry Escande rc = PTR_ERR(resp);
6987d0911c0SThierry Escande resp = NULL;
699a80509c7SMark A. Greer
7003f89fea3SThierry Escande if ((rc == -EIO || (rc == -ETIMEDOUT && ddev->nack_count)) &&
701a80509c7SMark A. Greer (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
702384ab1d1SMark A. Greer ddev->atn_count = 0;
703384ab1d1SMark A. Greer
704a80509c7SMark A. Greer rc = digital_in_send_nack(ddev, data_exch);
705a80509c7SMark A. Greer if (rc)
706a80509c7SMark A. Greer goto error;
707a80509c7SMark A. Greer
708a80509c7SMark A. Greer return;
709384ab1d1SMark A. Greer } else if ((rc == -ETIMEDOUT) &&
710384ab1d1SMark A. Greer (ddev->atn_count++ < DIGITAL_NFC_DEP_N_RETRY_ATN)) {
711384ab1d1SMark A. Greer ddev->nack_count = 0;
712384ab1d1SMark A. Greer
713384ab1d1SMark A. Greer rc = digital_in_send_atn(ddev, data_exch);
714384ab1d1SMark A. Greer if (rc)
715384ab1d1SMark A. Greer goto error;
716384ab1d1SMark A. Greer
717384ab1d1SMark A. Greer return;
7187d0911c0SThierry Escande }
7197d0911c0SThierry Escande
720a80509c7SMark A. Greer goto exit;
7217d0911c0SThierry Escande }
7227d0911c0SThierry Escande
7237d0911c0SThierry Escande rc = digital_skb_pull_dep_sod(ddev, resp);
7247d0911c0SThierry Escande if (rc) {
7257d0911c0SThierry Escande PROTOCOL_ERR("14.4.1.2");
7267d0911c0SThierry Escande goto exit;
7277d0911c0SThierry Escande }
7287d0911c0SThierry Escande
729a80509c7SMark A. Greer rc = ddev->skb_check_crc(resp);
730a80509c7SMark A. Greer if (rc) {
731a80509c7SMark A. Greer if ((resp->len >= 4) &&
732a80509c7SMark A. Greer (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
733384ab1d1SMark A. Greer ddev->atn_count = 0;
734384ab1d1SMark A. Greer
735a80509c7SMark A. Greer rc = digital_in_send_nack(ddev, data_exch);
736a80509c7SMark A. Greer if (rc)
737a80509c7SMark A. Greer goto error;
738a80509c7SMark A. Greer
739a80509c7SMark A. Greer kfree_skb(resp);
740a80509c7SMark A. Greer
741a80509c7SMark A. Greer return;
742a80509c7SMark A. Greer }
743a80509c7SMark A. Greer
744a80509c7SMark A. Greer PROTOCOL_ERR("14.4.1.6");
745a80509c7SMark A. Greer goto error;
746a80509c7SMark A. Greer }
747a80509c7SMark A. Greer
748384ab1d1SMark A. Greer ddev->atn_count = 0;
749a80509c7SMark A. Greer ddev->nack_count = 0;
750a80509c7SMark A. Greer
751b08147cbSMark A. Greer if (resp->len > ddev->local_payload_max) {
752b08147cbSMark A. Greer rc = -EMSGSIZE;
753b08147cbSMark A. Greer goto exit;
754b08147cbSMark A. Greer }
755b08147cbSMark A. Greer
7566ce30668SMark A. Greer size = sizeof(struct digital_dep_req_res);
7577d0911c0SThierry Escande dep_res = (struct digital_dep_req_res *)resp->data;
7587d0911c0SThierry Escande
7596ce30668SMark A. Greer if (resp->len < size || dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN ||
7607d0911c0SThierry Escande dep_res->cmd != DIGITAL_CMD_DEP_RES) {
7617d0911c0SThierry Escande rc = -EIO;
7627d0911c0SThierry Escande goto error;
7637d0911c0SThierry Escande }
7647d0911c0SThierry Escande
7657d0911c0SThierry Escande pfb = dep_res->pfb;
7667d0911c0SThierry Escande
7673bc3f88aSMark A. Greer if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
7683bc3f88aSMark A. Greer PROTOCOL_ERR("14.8.2.1");
7693bc3f88aSMark A. Greer rc = -EIO;
7703bc3f88aSMark A. Greer goto error;
7713bc3f88aSMark A. Greer }
7726ce30668SMark A. Greer
7733e6b0de8SMark A. Greer if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
7743e6b0de8SMark A. Greer rc = -EIO;
7753e6b0de8SMark A. Greer goto exit;
7763e6b0de8SMark A. Greer }
7773e6b0de8SMark A. Greer
7786ce30668SMark A. Greer if (size > resp->len) {
7796ce30668SMark A. Greer rc = -EIO;
7806ce30668SMark A. Greer goto error;
7816ce30668SMark A. Greer }
7826ce30668SMark A. Greer
7836ce30668SMark A. Greer skb_pull(resp, size);
7846ce30668SMark A. Greer
7857d0911c0SThierry Escande switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
7867d0911c0SThierry Escande case DIGITAL_NFC_DEP_PFB_I_PDU:
7877d0911c0SThierry Escande if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
7887d0911c0SThierry Escande PROTOCOL_ERR("14.12.3.3");
7897d0911c0SThierry Escande rc = -EIO;
7907d0911c0SThierry Escande goto error;
7917d0911c0SThierry Escande }
7927d0911c0SThierry Escande
7937d0911c0SThierry Escande ddev->curr_nfc_dep_pni =
7947d0911c0SThierry Escande DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
795c12715abSMark A. Greer
796384ab1d1SMark A. Greer kfree_skb(ddev->saved_skb);
797384ab1d1SMark A. Greer ddev->saved_skb = NULL;
798384ab1d1SMark A. Greer
799c12715abSMark A. Greer resp = digital_recv_dep_data_gather(ddev, pfb, resp,
800c12715abSMark A. Greer digital_in_send_ack,
801c12715abSMark A. Greer data_exch);
802c12715abSMark A. Greer if (IS_ERR(resp)) {
803c12715abSMark A. Greer rc = PTR_ERR(resp);
804c12715abSMark A. Greer resp = NULL;
805c12715abSMark A. Greer goto error;
806c12715abSMark A. Greer }
807c12715abSMark A. Greer
808c12715abSMark A. Greer /* If resp is NULL then we're still chaining so return and
809c12715abSMark A. Greer * wait for the next part of the PDU. Else, the PDU is
810c12715abSMark A. Greer * complete so pass it up.
811c12715abSMark A. Greer */
812c12715abSMark A. Greer if (!resp)
813c12715abSMark A. Greer return;
814c12715abSMark A. Greer
8157d0911c0SThierry Escande rc = 0;
8167d0911c0SThierry Escande break;
8177d0911c0SThierry Escande
8187d0911c0SThierry Escande case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
819e073eb67SThierry Escande if (DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) {
820e073eb67SThierry Escande PROTOCOL_ERR("14.12.4.5");
821e073eb67SThierry Escande rc = -EIO;
822e073eb67SThierry Escande goto exit;
823e073eb67SThierry Escande }
824e073eb67SThierry Escande
825485fdc9bSMark A. Greer if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
826485fdc9bSMark A. Greer PROTOCOL_ERR("14.12.3.3");
8277d0911c0SThierry Escande rc = -EIO;
828485fdc9bSMark A. Greer goto exit;
829485fdc9bSMark A. Greer }
830485fdc9bSMark A. Greer
831485fdc9bSMark A. Greer ddev->curr_nfc_dep_pni =
832485fdc9bSMark A. Greer DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
833485fdc9bSMark A. Greer
834e073eb67SThierry Escande if (!ddev->chaining_skb) {
835e073eb67SThierry Escande PROTOCOL_ERR("14.12.4.3");
836e073eb67SThierry Escande rc = -EIO;
837e073eb67SThierry Escande goto exit;
838e073eb67SThierry Escande }
839e073eb67SThierry Escande
840e073eb67SThierry Escande /* The initiator has received a valid ACK. Free the last sent
841e073eb67SThierry Escande * PDU and keep on sending chained skb.
842e073eb67SThierry Escande */
843384ab1d1SMark A. Greer kfree_skb(ddev->saved_skb);
844384ab1d1SMark A. Greer ddev->saved_skb = NULL;
845384ab1d1SMark A. Greer
8463bd2a5bcSMark A. Greer rc = digital_in_send_dep_req(ddev, NULL,
8473bd2a5bcSMark A. Greer ddev->chaining_skb,
8483bd2a5bcSMark A. Greer ddev->data_exch);
8493bd2a5bcSMark A. Greer if (rc)
8503bd2a5bcSMark A. Greer goto error;
8513bd2a5bcSMark A. Greer
852e073eb67SThierry Escande goto free_resp;
8537d0911c0SThierry Escande
8547d0911c0SThierry Escande case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
855384ab1d1SMark A. Greer if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { /* ATN */
856384ab1d1SMark A. Greer rc = digital_in_send_saved_skb(ddev, data_exch);
8571d984c2eSThierry Escande if (rc)
8587d0911c0SThierry Escande goto error;
8597d0911c0SThierry Escande
860e200f008SThierry Escande goto free_resp;
861384ab1d1SMark A. Greer }
862384ab1d1SMark A. Greer
863d85a301cSThierry Escande if (ddev->atn_count || ddev->nack_count) {
864d85a301cSThierry Escande PROTOCOL_ERR("14.12.4.4");
865d85a301cSThierry Escande rc = -EIO;
866d85a301cSThierry Escande goto error;
867d85a301cSThierry Escande }
868d85a301cSThierry Escande
869d85a301cSThierry Escande rtox = DIGITAL_NFC_DEP_RTOX_VALUE(resp->data[0]);
870d85a301cSThierry Escande if (!rtox || rtox > DIGITAL_NFC_DEP_RTOX_MAX) {
871d85a301cSThierry Escande PROTOCOL_ERR("14.8.4.1");
872d85a301cSThierry Escande rc = -EIO;
873d85a301cSThierry Escande goto error;
874d85a301cSThierry Escande }
875d85a301cSThierry Escande
876d85a301cSThierry Escande rc = digital_in_send_rtox(ddev, data_exch, rtox);
8777d0911c0SThierry Escande if (rc)
8787d0911c0SThierry Escande goto error;
8797d0911c0SThierry Escande
880e200f008SThierry Escande goto free_resp;
8817d0911c0SThierry Escande }
8827d0911c0SThierry Escande
8837d0911c0SThierry Escande exit:
8847d0911c0SThierry Escande data_exch->cb(data_exch->cb_context, resp, rc);
8857d0911c0SThierry Escande
8867d0911c0SThierry Escande error:
8877d0911c0SThierry Escande kfree(data_exch);
8887d0911c0SThierry Escande
8893bd2a5bcSMark A. Greer kfree_skb(ddev->chaining_skb);
8903bd2a5bcSMark A. Greer ddev->chaining_skb = NULL;
8913bd2a5bcSMark A. Greer
892384ab1d1SMark A. Greer kfree_skb(ddev->saved_skb);
893384ab1d1SMark A. Greer ddev->saved_skb = NULL;
894384ab1d1SMark A. Greer
8957d0911c0SThierry Escande if (rc)
8967d0911c0SThierry Escande kfree_skb(resp);
897e073eb67SThierry Escande
898e073eb67SThierry Escande return;
899e073eb67SThierry Escande
900e073eb67SThierry Escande free_resp:
901e073eb67SThierry Escande dev_kfree_skb(resp);
9027d0911c0SThierry Escande }
9037d0911c0SThierry Escande
digital_in_send_dep_req(struct nfc_digital_dev * ddev,struct nfc_target * target,struct sk_buff * skb,struct digital_data_exch * data_exch)9047d0911c0SThierry Escande int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
9057d0911c0SThierry Escande struct nfc_target *target, struct sk_buff *skb,
9067d0911c0SThierry Escande struct digital_data_exch *data_exch)
9077d0911c0SThierry Escande {
9087d0911c0SThierry Escande struct digital_dep_req_res *dep_req;
9093bd2a5bcSMark A. Greer struct sk_buff *chaining_skb, *tmp_skb;
9103bd2a5bcSMark A. Greer int rc;
9117d0911c0SThierry Escande
9127d0911c0SThierry Escande skb_push(skb, sizeof(struct digital_dep_req_res));
9137d0911c0SThierry Escande
9147d0911c0SThierry Escande dep_req = (struct digital_dep_req_res *)skb->data;
9153bd2a5bcSMark A. Greer
9167d0911c0SThierry Escande dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
9177d0911c0SThierry Escande dep_req->cmd = DIGITAL_CMD_DEP_REQ;
9187d0911c0SThierry Escande dep_req->pfb = ddev->curr_nfc_dep_pni;
9197d0911c0SThierry Escande
920384ab1d1SMark A. Greer ddev->atn_count = 0;
921a80509c7SMark A. Greer ddev->nack_count = 0;
922a80509c7SMark A. Greer
9233bd2a5bcSMark A. Greer chaining_skb = ddev->chaining_skb;
9247d0911c0SThierry Escande
9253bd2a5bcSMark A. Greer tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_req, data_exch);
9263bd2a5bcSMark A. Greer if (IS_ERR(tmp_skb))
9273bd2a5bcSMark A. Greer return PTR_ERR(tmp_skb);
9287d0911c0SThierry Escande
9293bd2a5bcSMark A. Greer digital_skb_push_dep_sod(ddev, tmp_skb);
9303bd2a5bcSMark A. Greer
9313bd2a5bcSMark A. Greer ddev->skb_add_crc(tmp_skb);
9323bd2a5bcSMark A. Greer
9331d984c2eSThierry Escande ddev->saved_skb = pskb_copy(tmp_skb, GFP_KERNEL);
934384ab1d1SMark A. Greer
9351a09c56fSThierry Escande rc = digital_in_send_cmd(ddev, tmp_skb, ddev->dep_rwt,
9361a09c56fSThierry Escande digital_in_recv_dep_res, data_exch);
9373bd2a5bcSMark A. Greer if (rc) {
9383bd2a5bcSMark A. Greer if (tmp_skb != skb)
9393bd2a5bcSMark A. Greer kfree_skb(tmp_skb);
9403bd2a5bcSMark A. Greer
9413bd2a5bcSMark A. Greer kfree_skb(chaining_skb);
9423bd2a5bcSMark A. Greer ddev->chaining_skb = NULL;
943384ab1d1SMark A. Greer
944384ab1d1SMark A. Greer kfree_skb(ddev->saved_skb);
945384ab1d1SMark A. Greer ddev->saved_skb = NULL;
9463bd2a5bcSMark A. Greer }
9473bd2a5bcSMark A. Greer
9483bd2a5bcSMark A. Greer return rc;
9497d0911c0SThierry Escande }
9501c7a4c24SThierry Escande
digital_tg_set_rf_tech(struct nfc_digital_dev * ddev,u8 rf_tech)951b711ad52SThierry Escande static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech)
952b711ad52SThierry Escande {
953b711ad52SThierry Escande ddev->curr_rf_tech = rf_tech;
954b711ad52SThierry Escande
955b711ad52SThierry Escande ddev->skb_add_crc = digital_skb_add_crc_none;
956b711ad52SThierry Escande ddev->skb_check_crc = digital_skb_check_crc_none;
957b711ad52SThierry Escande
958b711ad52SThierry Escande if (DIGITAL_DRV_CAPS_TG_CRC(ddev))
959b711ad52SThierry Escande return;
960b711ad52SThierry Escande
961b711ad52SThierry Escande switch (ddev->curr_rf_tech) {
962b711ad52SThierry Escande case NFC_DIGITAL_RF_TECH_106A:
963b711ad52SThierry Escande ddev->skb_add_crc = digital_skb_add_crc_a;
964b711ad52SThierry Escande ddev->skb_check_crc = digital_skb_check_crc_a;
965b711ad52SThierry Escande break;
966b711ad52SThierry Escande
967b711ad52SThierry Escande case NFC_DIGITAL_RF_TECH_212F:
968b711ad52SThierry Escande case NFC_DIGITAL_RF_TECH_424F:
969b711ad52SThierry Escande ddev->skb_add_crc = digital_skb_add_crc_f;
970b711ad52SThierry Escande ddev->skb_check_crc = digital_skb_check_crc_f;
971b711ad52SThierry Escande break;
972b711ad52SThierry Escande
973b711ad52SThierry Escande default:
974b711ad52SThierry Escande break;
975b711ad52SThierry Escande }
976b711ad52SThierry Escande }
977b711ad52SThierry Escande
digital_tg_send_ack(struct nfc_digital_dev * ddev,struct digital_data_exch * data_exch)978c12715abSMark A. Greer static int digital_tg_send_ack(struct nfc_digital_dev *ddev,
979c12715abSMark A. Greer struct digital_data_exch *data_exch)
980c12715abSMark A. Greer {
981c12715abSMark A. Greer struct digital_dep_req_res *dep_res;
982c12715abSMark A. Greer struct sk_buff *skb;
983c12715abSMark A. Greer int rc;
984c12715abSMark A. Greer
985c12715abSMark A. Greer skb = digital_skb_alloc(ddev, 1);
986c12715abSMark A. Greer if (!skb)
987c12715abSMark A. Greer return -ENOMEM;
988c12715abSMark A. Greer
989c12715abSMark A. Greer skb_push(skb, sizeof(struct digital_dep_req_res));
990c12715abSMark A. Greer
991c12715abSMark A. Greer dep_res = (struct digital_dep_req_res *)skb->data;
992c12715abSMark A. Greer
993c12715abSMark A. Greer dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
994c12715abSMark A. Greer dep_res->cmd = DIGITAL_CMD_DEP_RES;
995c12715abSMark A. Greer dep_res->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
996c12715abSMark A. Greer ddev->curr_nfc_dep_pni;
997c12715abSMark A. Greer
998c12715abSMark A. Greer if (ddev->did) {
999c12715abSMark A. Greer dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
1000c12715abSMark A. Greer
100159ae1d12SJohannes Berg skb_put_data(skb, &ddev->did, sizeof(ddev->did));
1002c12715abSMark A. Greer }
1003c12715abSMark A. Greer
1004c12715abSMark A. Greer ddev->curr_nfc_dep_pni =
1005c12715abSMark A. Greer DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
1006c12715abSMark A. Greer
1007c12715abSMark A. Greer digital_skb_push_dep_sod(ddev, skb);
1008c12715abSMark A. Greer
1009c12715abSMark A. Greer ddev->skb_add_crc(skb);
1010c12715abSMark A. Greer
10111d984c2eSThierry Escande ddev->saved_skb = pskb_copy(skb, GFP_KERNEL);
101249dbb14eSMark A. Greer
1013c12715abSMark A. Greer rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
1014c12715abSMark A. Greer data_exch);
101549dbb14eSMark A. Greer if (rc) {
1016c12715abSMark A. Greer kfree_skb(skb);
101749dbb14eSMark A. Greer kfree_skb(ddev->saved_skb);
101849dbb14eSMark A. Greer ddev->saved_skb = NULL;
101949dbb14eSMark A. Greer }
1020c12715abSMark A. Greer
1021c12715abSMark A. Greer return rc;
1022c12715abSMark A. Greer }
1023c12715abSMark A. Greer
digital_tg_send_atn(struct nfc_digital_dev * ddev)10249b5ec0fdSMark A. Greer static int digital_tg_send_atn(struct nfc_digital_dev *ddev)
10259b5ec0fdSMark A. Greer {
10269b5ec0fdSMark A. Greer struct digital_dep_req_res *dep_res;
10279b5ec0fdSMark A. Greer struct sk_buff *skb;
10289b5ec0fdSMark A. Greer int rc;
10299b5ec0fdSMark A. Greer
10309b5ec0fdSMark A. Greer skb = digital_skb_alloc(ddev, 1);
10319b5ec0fdSMark A. Greer if (!skb)
10329b5ec0fdSMark A. Greer return -ENOMEM;
10339b5ec0fdSMark A. Greer
10349b5ec0fdSMark A. Greer skb_push(skb, sizeof(struct digital_dep_req_res));
10359b5ec0fdSMark A. Greer
10369b5ec0fdSMark A. Greer dep_res = (struct digital_dep_req_res *)skb->data;
10379b5ec0fdSMark A. Greer
10389b5ec0fdSMark A. Greer dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
10399b5ec0fdSMark A. Greer dep_res->cmd = DIGITAL_CMD_DEP_RES;
10409b5ec0fdSMark A. Greer dep_res->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
10419b5ec0fdSMark A. Greer
10429b5ec0fdSMark A. Greer if (ddev->did) {
10439b5ec0fdSMark A. Greer dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
10449b5ec0fdSMark A. Greer
104559ae1d12SJohannes Berg skb_put_data(skb, &ddev->did, sizeof(ddev->did));
10469b5ec0fdSMark A. Greer }
10479b5ec0fdSMark A. Greer
10489b5ec0fdSMark A. Greer digital_skb_push_dep_sod(ddev, skb);
10499b5ec0fdSMark A. Greer
10509b5ec0fdSMark A. Greer ddev->skb_add_crc(skb);
10519b5ec0fdSMark A. Greer
10529b5ec0fdSMark A. Greer rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
10539b5ec0fdSMark A. Greer NULL);
10549b5ec0fdSMark A. Greer if (rc)
10559b5ec0fdSMark A. Greer kfree_skb(skb);
10569b5ec0fdSMark A. Greer
10579b5ec0fdSMark A. Greer return rc;
10589b5ec0fdSMark A. Greer }
10599b5ec0fdSMark A. Greer
digital_tg_send_saved_skb(struct nfc_digital_dev * ddev)106049dbb14eSMark A. Greer static int digital_tg_send_saved_skb(struct nfc_digital_dev *ddev)
106149dbb14eSMark A. Greer {
10621d984c2eSThierry Escande int rc;
106349dbb14eSMark A. Greer
10641d984c2eSThierry Escande if (!ddev->saved_skb)
10651d984c2eSThierry Escande return -EINVAL;
10661d984c2eSThierry Escande
10671d984c2eSThierry Escande skb_get(ddev->saved_skb);
10681d984c2eSThierry Escande
10691d984c2eSThierry Escande rc = digital_tg_send_cmd(ddev, ddev->saved_skb, 1500,
107049dbb14eSMark A. Greer digital_tg_recv_dep_req, NULL);
10711d984c2eSThierry Escande if (rc)
10721d984c2eSThierry Escande kfree_skb(ddev->saved_skb);
10731d984c2eSThierry Escande
10741d984c2eSThierry Escande return rc;
107549dbb14eSMark A. Greer }
107649dbb14eSMark A. Greer
digital_tg_recv_dep_req(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)10771c7a4c24SThierry Escande static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
10781c7a4c24SThierry Escande struct sk_buff *resp)
10791c7a4c24SThierry Escande {
10801c7a4c24SThierry Escande int rc;
10811c7a4c24SThierry Escande struct digital_dep_req_res *dep_req;
10826ce30668SMark A. Greer u8 pfb;
10831c7a4c24SThierry Escande size_t size;
10841c7a4c24SThierry Escande
10851c7a4c24SThierry Escande if (IS_ERR(resp)) {
10861c7a4c24SThierry Escande rc = PTR_ERR(resp);
10871c7a4c24SThierry Escande resp = NULL;
10881c7a4c24SThierry Escande goto exit;
10891c7a4c24SThierry Escande }
10901c7a4c24SThierry Escande
10911c7a4c24SThierry Escande rc = ddev->skb_check_crc(resp);
10921c7a4c24SThierry Escande if (rc) {
10931c7a4c24SThierry Escande PROTOCOL_ERR("14.4.1.6");
10941c7a4c24SThierry Escande goto exit;
10951c7a4c24SThierry Escande }
10961c7a4c24SThierry Escande
10971c7a4c24SThierry Escande rc = digital_skb_pull_dep_sod(ddev, resp);
10981c7a4c24SThierry Escande if (rc) {
10991c7a4c24SThierry Escande PROTOCOL_ERR("14.4.1.2");
11001c7a4c24SThierry Escande goto exit;
11011c7a4c24SThierry Escande }
11021c7a4c24SThierry Escande
1103b08147cbSMark A. Greer if (resp->len > ddev->local_payload_max) {
1104b08147cbSMark A. Greer rc = -EMSGSIZE;
1105b08147cbSMark A. Greer goto exit;
1106b08147cbSMark A. Greer }
1107b08147cbSMark A. Greer
11081c7a4c24SThierry Escande size = sizeof(struct digital_dep_req_res);
11091c7a4c24SThierry Escande dep_req = (struct digital_dep_req_res *)resp->data;
11101c7a4c24SThierry Escande
11111c7a4c24SThierry Escande if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
11121c7a4c24SThierry Escande dep_req->cmd != DIGITAL_CMD_DEP_REQ) {
11131c7a4c24SThierry Escande rc = -EIO;
11141c7a4c24SThierry Escande goto exit;
11151c7a4c24SThierry Escande }
11161c7a4c24SThierry Escande
11176ce30668SMark A. Greer pfb = dep_req->pfb;
11186ce30668SMark A. Greer
111905afedcbSMark A. Greer if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
112005afedcbSMark A. Greer if (ddev->did && (ddev->did == resp->data[3])) {
11211c7a4c24SThierry Escande size++;
112205afedcbSMark A. Greer } else {
112305afedcbSMark A. Greer rc = -EIO;
112405afedcbSMark A. Greer goto exit;
112505afedcbSMark A. Greer }
112605afedcbSMark A. Greer } else if (ddev->did) {
112705afedcbSMark A. Greer rc = -EIO;
112805afedcbSMark A. Greer goto exit;
112905afedcbSMark A. Greer }
11301c7a4c24SThierry Escande
11313e6b0de8SMark A. Greer if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
11323e6b0de8SMark A. Greer rc = -EIO;
11333e6b0de8SMark A. Greer goto exit;
11343e6b0de8SMark A. Greer }
11353e6b0de8SMark A. Greer
11366ce30668SMark A. Greer if (size > resp->len) {
11371c7a4c24SThierry Escande rc = -EIO;
11381c7a4c24SThierry Escande goto exit;
11391c7a4c24SThierry Escande }
11401c7a4c24SThierry Escande
11416ce30668SMark A. Greer skb_pull(resp, size);
11426ce30668SMark A. Greer
11436ce30668SMark A. Greer switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
11441c7a4c24SThierry Escande case DIGITAL_NFC_DEP_PFB_I_PDU:
114526042530SSamuel Ortiz pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
1146485fdc9bSMark A. Greer
11479b5ec0fdSMark A. Greer if (ddev->atn_count) {
1148f23a9868SThierry Escande /* The target has received (and replied to) at least one
1149f23a9868SThierry Escande * ATN DEP_REQ.
1150f23a9868SThierry Escande */
11519b5ec0fdSMark A. Greer ddev->atn_count = 0;
11529b5ec0fdSMark A. Greer
1153f23a9868SThierry Escande /* pni of resp PDU equal to the target current pni - 1
1154f23a9868SThierry Escande * means resp is the previous DEP_REQ PDU received from
1155f23a9868SThierry Escande * the initiator so the target replies with saved_skb
1156f23a9868SThierry Escande * which is the previous DEP_RES saved in
1157f23a9868SThierry Escande * digital_tg_send_dep_res().
1158f23a9868SThierry Escande */
1159f23a9868SThierry Escande if (DIGITAL_NFC_DEP_PFB_PNI(pfb) ==
1160f23a9868SThierry Escande DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni - 1)) {
11619b5ec0fdSMark A. Greer rc = digital_tg_send_saved_skb(ddev);
11629b5ec0fdSMark A. Greer if (rc)
11639b5ec0fdSMark A. Greer goto exit;
11649b5ec0fdSMark A. Greer
1165f23a9868SThierry Escande goto free_resp;
1166f23a9868SThierry Escande }
1167f23a9868SThierry Escande
1168f23a9868SThierry Escande /* atn_count > 0 and PDU pni != curr_nfc_dep_pni - 1
1169f23a9868SThierry Escande * means the target probably did not received the last
1170f23a9868SThierry Escande * DEP_REQ PDU sent by the initiator. The target
1171f23a9868SThierry Escande * fallbacks to normal processing then.
1172f23a9868SThierry Escande */
1173f23a9868SThierry Escande }
1174f23a9868SThierry Escande
1175f23a9868SThierry Escande if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
1176f23a9868SThierry Escande PROTOCOL_ERR("14.12.3.4");
1177f23a9868SThierry Escande rc = -EIO;
1178f23a9868SThierry Escande goto exit;
11799b5ec0fdSMark A. Greer }
11809b5ec0fdSMark A. Greer
118149dbb14eSMark A. Greer kfree_skb(ddev->saved_skb);
118249dbb14eSMark A. Greer ddev->saved_skb = NULL;
118349dbb14eSMark A. Greer
1184c12715abSMark A. Greer resp = digital_recv_dep_data_gather(ddev, pfb, resp,
1185c12715abSMark A. Greer digital_tg_send_ack, NULL);
1186c12715abSMark A. Greer if (IS_ERR(resp)) {
1187c12715abSMark A. Greer rc = PTR_ERR(resp);
1188c12715abSMark A. Greer resp = NULL;
1189c12715abSMark A. Greer goto exit;
1190c12715abSMark A. Greer }
1191c12715abSMark A. Greer
1192c12715abSMark A. Greer /* If resp is NULL then we're still chaining so return and
1193c12715abSMark A. Greer * wait for the next part of the PDU. Else, the PDU is
1194c12715abSMark A. Greer * complete so pass it up.
1195c12715abSMark A. Greer */
1196c12715abSMark A. Greer if (!resp)
1197c12715abSMark A. Greer return;
1198c12715abSMark A. Greer
1199485fdc9bSMark A. Greer rc = 0;
12001c7a4c24SThierry Escande break;
12011c7a4c24SThierry Escande case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
1202482333b2SThierry Escande if (DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) { /* NACK */
1203482333b2SThierry Escande if (DIGITAL_NFC_DEP_PFB_PNI(pfb + 1) !=
1204482333b2SThierry Escande ddev->curr_nfc_dep_pni) {
1205485fdc9bSMark A. Greer rc = -EIO;
1206485fdc9bSMark A. Greer goto exit;
1207485fdc9bSMark A. Greer }
1208485fdc9bSMark A. Greer
12099b5ec0fdSMark A. Greer ddev->atn_count = 0;
12109b5ec0fdSMark A. Greer
12119b5ec0fdSMark A. Greer rc = digital_tg_send_saved_skb(ddev);
12129b5ec0fdSMark A. Greer if (rc)
12139b5ec0fdSMark A. Greer goto exit;
12149b5ec0fdSMark A. Greer
1215482333b2SThierry Escande goto free_resp;
1216482333b2SThierry Escande }
1217482333b2SThierry Escande
1218482333b2SThierry Escande /* ACK */
1219482333b2SThierry Escande if (ddev->atn_count) {
1220d3295869SZheng Yongjun /* The target has previously received one or more ATN
1221482333b2SThierry Escande * PDUs.
1222482333b2SThierry Escande */
1223482333b2SThierry Escande ddev->atn_count = 0;
1224482333b2SThierry Escande
1225482333b2SThierry Escande /* If the ACK PNI is equal to the target PNI - 1 means
1226482333b2SThierry Escande * that the initiator did not receive the previous PDU
1227482333b2SThierry Escande * sent by the target so re-send it.
1228482333b2SThierry Escande */
1229482333b2SThierry Escande if (DIGITAL_NFC_DEP_PFB_PNI(pfb + 1) ==
1230482333b2SThierry Escande ddev->curr_nfc_dep_pni) {
1231482333b2SThierry Escande rc = digital_tg_send_saved_skb(ddev);
1232482333b2SThierry Escande if (rc)
1233482333b2SThierry Escande goto exit;
1234482333b2SThierry Escande
1235482333b2SThierry Escande goto free_resp;
1236482333b2SThierry Escande }
1237482333b2SThierry Escande
1238482333b2SThierry Escande /* Otherwise, the target did not receive the previous
1239482333b2SThierry Escande * ACK PDU from the initiator. Fallback to normal
1240482333b2SThierry Escande * processing of chained PDU then.
1241482333b2SThierry Escande */
1242482333b2SThierry Escande }
1243482333b2SThierry Escande
1244482333b2SThierry Escande /* Keep on sending chained PDU */
1245482333b2SThierry Escande if (!ddev->chaining_skb ||
1246482333b2SThierry Escande DIGITAL_NFC_DEP_PFB_PNI(pfb) !=
1247482333b2SThierry Escande ddev->curr_nfc_dep_pni) {
1248482333b2SThierry Escande rc = -EIO;
1249482333b2SThierry Escande goto exit;
12509b5ec0fdSMark A. Greer }
12519b5ec0fdSMark A. Greer
125249dbb14eSMark A. Greer kfree_skb(ddev->saved_skb);
125349dbb14eSMark A. Greer ddev->saved_skb = NULL;
125449dbb14eSMark A. Greer
12553bd2a5bcSMark A. Greer rc = digital_tg_send_dep_res(ddev, ddev->chaining_skb);
12563bd2a5bcSMark A. Greer if (rc)
12573bd2a5bcSMark A. Greer goto exit;
12583bd2a5bcSMark A. Greer
1259482333b2SThierry Escande goto free_resp;
12601c7a4c24SThierry Escande case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
12619b5ec0fdSMark A. Greer if (DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
12621c7a4c24SThierry Escande rc = -EINVAL;
12631c7a4c24SThierry Escande goto exit;
12641c7a4c24SThierry Escande }
12651c7a4c24SThierry Escande
12669b5ec0fdSMark A. Greer rc = digital_tg_send_atn(ddev);
12679b5ec0fdSMark A. Greer if (rc)
12689b5ec0fdSMark A. Greer goto exit;
12699b5ec0fdSMark A. Greer
12709b5ec0fdSMark A. Greer ddev->atn_count++;
12719b5ec0fdSMark A. Greer
1272e200f008SThierry Escande goto free_resp;
12739b5ec0fdSMark A. Greer }
12749b5ec0fdSMark A. Greer
12751c7a4c24SThierry Escande rc = nfc_tm_data_received(ddev->nfc_dev, resp);
1276*75258586SLv Yunlong if (rc)
1277*75258586SLv Yunlong resp = NULL;
12781c7a4c24SThierry Escande
12791c7a4c24SThierry Escande exit:
12803bd2a5bcSMark A. Greer kfree_skb(ddev->chaining_skb);
12813bd2a5bcSMark A. Greer ddev->chaining_skb = NULL;
12823bd2a5bcSMark A. Greer
12839b5ec0fdSMark A. Greer ddev->atn_count = 0;
12849b5ec0fdSMark A. Greer
128549dbb14eSMark A. Greer kfree_skb(ddev->saved_skb);
128649dbb14eSMark A. Greer ddev->saved_skb = NULL;
128749dbb14eSMark A. Greer
12881c7a4c24SThierry Escande if (rc)
12891c7a4c24SThierry Escande kfree_skb(resp);
1290f23a9868SThierry Escande
1291f23a9868SThierry Escande return;
1292f23a9868SThierry Escande
1293f23a9868SThierry Escande free_resp:
1294f23a9868SThierry Escande dev_kfree_skb(resp);
12951c7a4c24SThierry Escande }
12961c7a4c24SThierry Escande
digital_tg_send_dep_res(struct nfc_digital_dev * ddev,struct sk_buff * skb)12971c7a4c24SThierry Escande int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
12981c7a4c24SThierry Escande {
12991c7a4c24SThierry Escande struct digital_dep_req_res *dep_res;
13003bd2a5bcSMark A. Greer struct sk_buff *chaining_skb, *tmp_skb;
13013bd2a5bcSMark A. Greer int rc;
13021c7a4c24SThierry Escande
13031c7a4c24SThierry Escande skb_push(skb, sizeof(struct digital_dep_req_res));
1304b08147cbSMark A. Greer
13051c7a4c24SThierry Escande dep_res = (struct digital_dep_req_res *)skb->data;
13061c7a4c24SThierry Escande
13071c7a4c24SThierry Escande dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
13081c7a4c24SThierry Escande dep_res->cmd = DIGITAL_CMD_DEP_RES;
13091c7a4c24SThierry Escande dep_res->pfb = ddev->curr_nfc_dep_pni;
13101c7a4c24SThierry Escande
131105afedcbSMark A. Greer if (ddev->did) {
131205afedcbSMark A. Greer dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
131305afedcbSMark A. Greer
131459ae1d12SJohannes Berg skb_put_data(skb, &ddev->did, sizeof(ddev->did));
131505afedcbSMark A. Greer }
131605afedcbSMark A. Greer
1317485fdc9bSMark A. Greer ddev->curr_nfc_dep_pni =
1318485fdc9bSMark A. Greer DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
1319485fdc9bSMark A. Greer
13203bd2a5bcSMark A. Greer chaining_skb = ddev->chaining_skb;
13211c7a4c24SThierry Escande
13223bd2a5bcSMark A. Greer tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_res, NULL);
13233bd2a5bcSMark A. Greer if (IS_ERR(tmp_skb))
13243bd2a5bcSMark A. Greer return PTR_ERR(tmp_skb);
13251c7a4c24SThierry Escande
13263bd2a5bcSMark A. Greer digital_skb_push_dep_sod(ddev, tmp_skb);
13273bd2a5bcSMark A. Greer
13283bd2a5bcSMark A. Greer ddev->skb_add_crc(tmp_skb);
13293bd2a5bcSMark A. Greer
13301d984c2eSThierry Escande ddev->saved_skb = pskb_copy(tmp_skb, GFP_KERNEL);
133149dbb14eSMark A. Greer
13323bd2a5bcSMark A. Greer rc = digital_tg_send_cmd(ddev, tmp_skb, 1500, digital_tg_recv_dep_req,
13331c7a4c24SThierry Escande NULL);
13343bd2a5bcSMark A. Greer if (rc) {
13353bd2a5bcSMark A. Greer if (tmp_skb != skb)
13363bd2a5bcSMark A. Greer kfree_skb(tmp_skb);
13373bd2a5bcSMark A. Greer
13383bd2a5bcSMark A. Greer kfree_skb(chaining_skb);
13393bd2a5bcSMark A. Greer ddev->chaining_skb = NULL;
134049dbb14eSMark A. Greer
134149dbb14eSMark A. Greer kfree_skb(ddev->saved_skb);
134249dbb14eSMark A. Greer ddev->saved_skb = NULL;
13433bd2a5bcSMark A. Greer }
13443bd2a5bcSMark A. Greer
13453bd2a5bcSMark A. Greer return rc;
13461c7a4c24SThierry Escande }
13471c7a4c24SThierry Escande
digital_tg_send_psl_res_complete(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)13481c7a4c24SThierry Escande static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,
13491c7a4c24SThierry Escande void *arg, struct sk_buff *resp)
13501c7a4c24SThierry Escande {
135167af1d7aSThierry Escande u8 rf_tech = (unsigned long)arg;
13521c7a4c24SThierry Escande
13531c7a4c24SThierry Escande if (IS_ERR(resp))
13541c7a4c24SThierry Escande return;
13551c7a4c24SThierry Escande
1356b711ad52SThierry Escande digital_tg_set_rf_tech(ddev, rf_tech);
1357b711ad52SThierry Escande
13581c7a4c24SThierry Escande digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
13591c7a4c24SThierry Escande
13601c7a4c24SThierry Escande digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL);
13611c7a4c24SThierry Escande
13621c7a4c24SThierry Escande dev_kfree_skb(resp);
13631c7a4c24SThierry Escande }
13641c7a4c24SThierry Escande
digital_tg_send_psl_res(struct nfc_digital_dev * ddev,u8 did,u8 rf_tech)13651c7a4c24SThierry Escande static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did,
13661c7a4c24SThierry Escande u8 rf_tech)
13671c7a4c24SThierry Escande {
13681c7a4c24SThierry Escande struct digital_psl_res *psl_res;
13691c7a4c24SThierry Escande struct sk_buff *skb;
13701c7a4c24SThierry Escande int rc;
13711c7a4c24SThierry Escande
13721c7a4c24SThierry Escande skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res));
13731c7a4c24SThierry Escande if (!skb)
13741c7a4c24SThierry Escande return -ENOMEM;
13751c7a4c24SThierry Escande
13761c7a4c24SThierry Escande skb_put(skb, sizeof(struct digital_psl_res));
13771c7a4c24SThierry Escande
13781c7a4c24SThierry Escande psl_res = (struct digital_psl_res *)skb->data;
13791c7a4c24SThierry Escande
13801c7a4c24SThierry Escande psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
13811c7a4c24SThierry Escande psl_res->cmd = DIGITAL_CMD_PSL_RES;
13821c7a4c24SThierry Escande psl_res->did = did;
13831c7a4c24SThierry Escande
13841c7a4c24SThierry Escande digital_skb_push_dep_sod(ddev, skb);
13851c7a4c24SThierry Escande
13861c7a4c24SThierry Escande ddev->skb_add_crc(skb);
13871c7a4c24SThierry Escande
1388485fdc9bSMark A. Greer ddev->curr_nfc_dep_pni = 0;
1389485fdc9bSMark A. Greer
13901c7a4c24SThierry Escande rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
139167af1d7aSThierry Escande (void *)(unsigned long)rf_tech);
13921c7a4c24SThierry Escande if (rc)
13931c7a4c24SThierry Escande kfree_skb(skb);
13941c7a4c24SThierry Escande
13951c7a4c24SThierry Escande return rc;
13961c7a4c24SThierry Escande }
13971c7a4c24SThierry Escande
digital_tg_recv_psl_req(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)13981c7a4c24SThierry Escande static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg,
13991c7a4c24SThierry Escande struct sk_buff *resp)
14001c7a4c24SThierry Escande {
14011c7a4c24SThierry Escande int rc;
14021c7a4c24SThierry Escande struct digital_psl_req *psl_req;
14031c7a4c24SThierry Escande u8 rf_tech;
1404b08147cbSMark A. Greer u8 dsi, payload_size, payload_bits;
14051c7a4c24SThierry Escande
14061c7a4c24SThierry Escande if (IS_ERR(resp)) {
14071c7a4c24SThierry Escande rc = PTR_ERR(resp);
14081c7a4c24SThierry Escande resp = NULL;
14091c7a4c24SThierry Escande goto exit;
14101c7a4c24SThierry Escande }
14111c7a4c24SThierry Escande
14121c7a4c24SThierry Escande rc = ddev->skb_check_crc(resp);
14131c7a4c24SThierry Escande if (rc) {
14141c7a4c24SThierry Escande PROTOCOL_ERR("14.4.1.6");
14151c7a4c24SThierry Escande goto exit;
14161c7a4c24SThierry Escande }
14171c7a4c24SThierry Escande
14181c7a4c24SThierry Escande rc = digital_skb_pull_dep_sod(ddev, resp);
14191c7a4c24SThierry Escande if (rc) {
14201c7a4c24SThierry Escande PROTOCOL_ERR("14.4.1.2");
14211c7a4c24SThierry Escande goto exit;
14221c7a4c24SThierry Escande }
14231c7a4c24SThierry Escande
14241c7a4c24SThierry Escande psl_req = (struct digital_psl_req *)resp->data;
14251c7a4c24SThierry Escande
14261c7a4c24SThierry Escande if (resp->len != sizeof(struct digital_psl_req) ||
14271c7a4c24SThierry Escande psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
14281c7a4c24SThierry Escande psl_req->cmd != DIGITAL_CMD_PSL_REQ) {
14291c7a4c24SThierry Escande rc = -EIO;
14301c7a4c24SThierry Escande goto exit;
14311c7a4c24SThierry Escande }
14321c7a4c24SThierry Escande
14331c7a4c24SThierry Escande dsi = (psl_req->brs >> 3) & 0x07;
14341c7a4c24SThierry Escande switch (dsi) {
14351c7a4c24SThierry Escande case 0:
14361c7a4c24SThierry Escande rf_tech = NFC_DIGITAL_RF_TECH_106A;
14371c7a4c24SThierry Escande break;
14381c7a4c24SThierry Escande case 1:
14391c7a4c24SThierry Escande rf_tech = NFC_DIGITAL_RF_TECH_212F;
14401c7a4c24SThierry Escande break;
14411c7a4c24SThierry Escande case 2:
14421c7a4c24SThierry Escande rf_tech = NFC_DIGITAL_RF_TECH_424F;
14431c7a4c24SThierry Escande break;
14441c7a4c24SThierry Escande default:
144577d84ff8SMasanari Iida pr_err("Unsupported dsi value %d\n", dsi);
14461c7a4c24SThierry Escande goto exit;
14471c7a4c24SThierry Escande }
14481c7a4c24SThierry Escande
1449b08147cbSMark A. Greer payload_bits = DIGITAL_PAYLOAD_FSL_TO_BITS(psl_req->fsl);
1450b08147cbSMark A. Greer payload_size = digital_payload_bits_to_size(payload_bits);
1451b08147cbSMark A. Greer
1452b08147cbSMark A. Greer if (!payload_size || (payload_size > min(ddev->local_payload_max,
1453b08147cbSMark A. Greer ddev->remote_payload_max))) {
1454b08147cbSMark A. Greer rc = -EINVAL;
1455b08147cbSMark A. Greer goto exit;
1456b08147cbSMark A. Greer }
1457b08147cbSMark A. Greer
1458b08147cbSMark A. Greer ddev->local_payload_max = payload_size;
1459b08147cbSMark A. Greer ddev->remote_payload_max = payload_size;
1460b08147cbSMark A. Greer
14611c7a4c24SThierry Escande rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
14621c7a4c24SThierry Escande
14631c7a4c24SThierry Escande exit:
14641c7a4c24SThierry Escande kfree_skb(resp);
14651c7a4c24SThierry Escande }
14661c7a4c24SThierry Escande
digital_tg_send_atr_res_complete(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)14671c7a4c24SThierry Escande static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev,
14681c7a4c24SThierry Escande void *arg, struct sk_buff *resp)
14691c7a4c24SThierry Escande {
14701c7a4c24SThierry Escande int offset;
14711c7a4c24SThierry Escande
14721c7a4c24SThierry Escande if (IS_ERR(resp)) {
14731c7a4c24SThierry Escande digital_poll_next_tech(ddev);
14741c7a4c24SThierry Escande return;
14751c7a4c24SThierry Escande }
14761c7a4c24SThierry Escande
14771c7a4c24SThierry Escande offset = 2;
14781c7a4c24SThierry Escande if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
14791c7a4c24SThierry Escande offset++;
14801c7a4c24SThierry Escande
14819b5ec0fdSMark A. Greer ddev->atn_count = 0;
14829b5ec0fdSMark A. Greer
14831c7a4c24SThierry Escande if (resp->data[offset] == DIGITAL_CMD_PSL_REQ)
14841c7a4c24SThierry Escande digital_tg_recv_psl_req(ddev, arg, resp);
14851c7a4c24SThierry Escande else
14861c7a4c24SThierry Escande digital_tg_recv_dep_req(ddev, arg, resp);
14871c7a4c24SThierry Escande }
14881c7a4c24SThierry Escande
digital_tg_send_atr_res(struct nfc_digital_dev * ddev,struct digital_atr_req * atr_req)14891c7a4c24SThierry Escande static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,
14901c7a4c24SThierry Escande struct digital_atr_req *atr_req)
14911c7a4c24SThierry Escande {
14921c7a4c24SThierry Escande struct digital_atr_res *atr_res;
14931c7a4c24SThierry Escande struct sk_buff *skb;
1494b08147cbSMark A. Greer u8 *gb, payload_bits;
14951c7a4c24SThierry Escande size_t gb_len;
14961c7a4c24SThierry Escande int rc;
14971c7a4c24SThierry Escande
14981c7a4c24SThierry Escande gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len);
14991c7a4c24SThierry Escande if (!gb)
15001c7a4c24SThierry Escande gb_len = 0;
15011c7a4c24SThierry Escande
15021c7a4c24SThierry Escande skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len);
15031c7a4c24SThierry Escande if (!skb)
15041c7a4c24SThierry Escande return -ENOMEM;
15051c7a4c24SThierry Escande
15061c7a4c24SThierry Escande skb_put(skb, sizeof(struct digital_atr_res));
15071c7a4c24SThierry Escande atr_res = (struct digital_atr_res *)skb->data;
15081c7a4c24SThierry Escande
15091c7a4c24SThierry Escande memset(atr_res, 0, sizeof(struct digital_atr_res));
15101c7a4c24SThierry Escande
15111c7a4c24SThierry Escande atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
15121c7a4c24SThierry Escande atr_res->cmd = DIGITAL_CMD_ATR_RES;
15131c7a4c24SThierry Escande memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
15141a09c56fSThierry Escande atr_res->to = DIGITAL_NFC_DEP_TG_MAX_WT;
1515b08147cbSMark A. Greer
1516b08147cbSMark A. Greer ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
1517b08147cbSMark A. Greer payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
1518b08147cbSMark A. Greer atr_res->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
1519b08147cbSMark A. Greer
15201c7a4c24SThierry Escande if (gb_len) {
15211c7a4c24SThierry Escande skb_put(skb, gb_len);
15221c7a4c24SThierry Escande
15231c7a4c24SThierry Escande atr_res->pp |= DIGITAL_GB_BIT;
15241c7a4c24SThierry Escande memcpy(atr_res->gb, gb, gb_len);
15251c7a4c24SThierry Escande }
15261c7a4c24SThierry Escande
15271c7a4c24SThierry Escande digital_skb_push_dep_sod(ddev, skb);
15281c7a4c24SThierry Escande
15291c7a4c24SThierry Escande ddev->skb_add_crc(skb);
15301c7a4c24SThierry Escande
1531485fdc9bSMark A. Greer ddev->curr_nfc_dep_pni = 0;
1532485fdc9bSMark A. Greer
15331c7a4c24SThierry Escande rc = digital_tg_send_cmd(ddev, skb, 999,
15341c7a4c24SThierry Escande digital_tg_send_atr_res_complete, NULL);
1535b15829baSMark A. Greer if (rc)
15361c7a4c24SThierry Escande kfree_skb(skb);
15371c7a4c24SThierry Escande
15381c7a4c24SThierry Escande return rc;
15391c7a4c24SThierry Escande }
15401c7a4c24SThierry Escande
digital_tg_recv_atr_req(struct nfc_digital_dev * ddev,void * arg,struct sk_buff * resp)15411c7a4c24SThierry Escande void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg,
15421c7a4c24SThierry Escande struct sk_buff *resp)
15431c7a4c24SThierry Escande {
15441c7a4c24SThierry Escande int rc;
15451c7a4c24SThierry Escande struct digital_atr_req *atr_req;
15461c7a4c24SThierry Escande size_t gb_len, min_size;
1547b08147cbSMark A. Greer u8 poll_tech_count, payload_bits;
15481c7a4c24SThierry Escande
15491c7a4c24SThierry Escande if (IS_ERR(resp)) {
15501c7a4c24SThierry Escande rc = PTR_ERR(resp);
15511c7a4c24SThierry Escande resp = NULL;
15521c7a4c24SThierry Escande goto exit;
15531c7a4c24SThierry Escande }
15541c7a4c24SThierry Escande
15551c7a4c24SThierry Escande if (!resp->len) {
15561c7a4c24SThierry Escande rc = -EIO;
15571c7a4c24SThierry Escande goto exit;
15581c7a4c24SThierry Escande }
15591c7a4c24SThierry Escande
15601c7a4c24SThierry Escande if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) {
15611c7a4c24SThierry Escande min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2;
1562b711ad52SThierry Escande digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_106A);
15631c7a4c24SThierry Escande } else {
15641c7a4c24SThierry Escande min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1;
1565b711ad52SThierry Escande digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_212F);
15661c7a4c24SThierry Escande }
15671c7a4c24SThierry Escande
15681c7a4c24SThierry Escande if (resp->len < min_size) {
15691c7a4c24SThierry Escande rc = -EIO;
15701c7a4c24SThierry Escande goto exit;
15711c7a4c24SThierry Escande }
15721c7a4c24SThierry Escande
157348e10445SThierry Escande ddev->curr_protocol = NFC_PROTO_NFC_DEP_MASK;
15741c7a4c24SThierry Escande
15751c7a4c24SThierry Escande rc = ddev->skb_check_crc(resp);
15761c7a4c24SThierry Escande if (rc) {
15771c7a4c24SThierry Escande PROTOCOL_ERR("14.4.1.6");
15781c7a4c24SThierry Escande goto exit;
15791c7a4c24SThierry Escande }
15801c7a4c24SThierry Escande
15811c7a4c24SThierry Escande rc = digital_skb_pull_dep_sod(ddev, resp);
15821c7a4c24SThierry Escande if (rc) {
15831c7a4c24SThierry Escande PROTOCOL_ERR("14.4.1.2");
15841c7a4c24SThierry Escande goto exit;
15851c7a4c24SThierry Escande }
15861c7a4c24SThierry Escande
15871c7a4c24SThierry Escande atr_req = (struct digital_atr_req *)resp->data;
15881c7a4c24SThierry Escande
15891c7a4c24SThierry Escande if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
159005afedcbSMark A. Greer atr_req->cmd != DIGITAL_CMD_ATR_REQ ||
159105afedcbSMark A. Greer atr_req->did > DIGITAL_DID_MAX) {
15921c7a4c24SThierry Escande rc = -EINVAL;
15931c7a4c24SThierry Escande goto exit;
15941c7a4c24SThierry Escande }
15951c7a4c24SThierry Escande
1596b08147cbSMark A. Greer payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_req->pp);
1597b08147cbSMark A. Greer ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
1598b08147cbSMark A. Greer
1599b08147cbSMark A. Greer if (!ddev->remote_payload_max) {
1600b08147cbSMark A. Greer rc = -EINVAL;
1601b08147cbSMark A. Greer goto exit;
1602b08147cbSMark A. Greer }
1603b08147cbSMark A. Greer
160405afedcbSMark A. Greer ddev->did = atr_req->did;
160505afedcbSMark A. Greer
16061c7a4c24SThierry Escande rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
16071c7a4c24SThierry Escande NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
16081c7a4c24SThierry Escande if (rc)
16091c7a4c24SThierry Escande goto exit;
16101c7a4c24SThierry Escande
16111c7a4c24SThierry Escande rc = digital_tg_send_atr_res(ddev, atr_req);
16121c7a4c24SThierry Escande if (rc)
16131c7a4c24SThierry Escande goto exit;
16141c7a4c24SThierry Escande
16151c7a4c24SThierry Escande gb_len = resp->len - sizeof(struct digital_atr_req);
16160529a7adSMark A. Greer
16170529a7adSMark A. Greer poll_tech_count = ddev->poll_tech_count;
16180529a7adSMark A. Greer ddev->poll_tech_count = 0;
16190529a7adSMark A. Greer
16201c7a4c24SThierry Escande rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
16211c7a4c24SThierry Escande NFC_COMM_PASSIVE, atr_req->gb, gb_len);
16220529a7adSMark A. Greer if (rc) {
16230529a7adSMark A. Greer ddev->poll_tech_count = poll_tech_count;
16241c7a4c24SThierry Escande goto exit;
16250529a7adSMark A. Greer }
16261c7a4c24SThierry Escande
16271c7a4c24SThierry Escande rc = 0;
16281c7a4c24SThierry Escande exit:
16291c7a4c24SThierry Escande if (rc)
16301c7a4c24SThierry Escande digital_poll_next_tech(ddev);
16311c7a4c24SThierry Escande
16321c7a4c24SThierry Escande dev_kfree_skb(resp);
16331c7a4c24SThierry Escande }
1634