xref: /openbmc/linux/net/nfc/digital_dep.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
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