Blame view

net/nfc/digital_dep.c 34.2 KB
2025cf9e1   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
7d0911c02   Thierry Escande   NFC Digital: Add ...
2
3
4
  /*
   * NFC Digital Protocol stack
   * Copyright (c) 2013, Intel Corporation.
7d0911c02   Thierry Escande   NFC Digital: Add ...
5
   */
c5da0e4a3   Samuel Ortiz   NFC: digital: Rem...
6
  #define pr_fmt(fmt) "digital: %s: " fmt, __func__
7d0911c02   Thierry Escande   NFC Digital: Add ...
7
  #include "digital.h"
a80509c76   Mark A. Greer   NFC: digital: Add...
8
  #define DIGITAL_NFC_DEP_N_RETRY_NACK	2
384ab1d17   Mark A. Greer   NFC: digital: Add...
9
  #define DIGITAL_NFC_DEP_N_RETRY_ATN	2
a80509c76   Mark A. Greer   NFC: digital: Add...
10

7d0911c02   Thierry Escande   NFC Digital: Add ...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  #define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4
  #define DIGITAL_NFC_DEP_FRAME_DIR_IN  0xD5
  
  #define DIGITAL_NFC_DEP_NFCA_SOD_SB   0xF0
  
  #define DIGITAL_CMD_ATR_REQ 0x00
  #define DIGITAL_CMD_ATR_RES 0x01
  #define DIGITAL_CMD_PSL_REQ 0x04
  #define DIGITAL_CMD_PSL_RES 0x05
  #define DIGITAL_CMD_DEP_REQ 0x06
  #define DIGITAL_CMD_DEP_RES 0x07
  
  #define DIGITAL_ATR_REQ_MIN_SIZE 16
  #define DIGITAL_ATR_REQ_MAX_SIZE 64
1a09c56f5   Thierry Escande   NFC: digital: Add...
25
  #define DIGITAL_ATR_RES_TO_WT(s)	((s) & 0xF)
05afedcb8   Mark A. Greer   NFC: digital: Add...
26
  #define DIGITAL_DID_MAX	14
b08147cbc   Mark A. Greer   NFC: digital: Imp...
27
28
29
30
31
  #define DIGITAL_PAYLOAD_SIZE_MAX	254
  #define DIGITAL_PAYLOAD_BITS_TO_PP(s)	(((s) & 0x3) << 4)
  #define DIGITAL_PAYLOAD_PP_TO_BITS(s)	(((s) >> 4) & 0x3)
  #define DIGITAL_PAYLOAD_BITS_TO_FSL(s)	((s) & 0x3)
  #define DIGITAL_PAYLOAD_FSL_TO_BITS(s)	((s) & 0x3)
7d0911c02   Thierry Escande   NFC Digital: Add ...
32
33
34
35
36
  #define DIGITAL_GB_BIT	0x02
  
  #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
  
  #define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
37
38
  #define DIGITAL_NFC_DEP_PFB_MI_BIT	0x10
  #define DIGITAL_NFC_DEP_PFB_NACK_BIT	0x10
05afedcb8   Mark A. Greer   NFC: digital: Add...
39
  #define DIGITAL_NFC_DEP_PFB_DID_BIT	0x04
7d0911c02   Thierry Escande   NFC Digital: Add ...
40
41
42
  
  #define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
  				((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT)
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
43
44
  #define DIGITAL_NFC_DEP_MI_BIT_SET(pfb)  ((pfb) & DIGITAL_NFC_DEP_PFB_MI_BIT)
  #define DIGITAL_NFC_DEP_NACK_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_NACK_BIT)
7d0911c02   Thierry Escande   NFC Digital: Add ...
45
  #define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
05afedcb8   Mark A. Greer   NFC: digital: Add...
46
  #define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT)
7d0911c02   Thierry Escande   NFC Digital: Add ...
47
  #define DIGITAL_NFC_DEP_PFB_PNI(pfb)     ((pfb) & 0x03)
d85a301c2   Thierry Escande   NFC: digital: Fix...
48
49
  #define DIGITAL_NFC_DEP_RTOX_VALUE(data) ((data) & 0x3F)
  #define DIGITAL_NFC_DEP_RTOX_MAX	 59
7d0911c02   Thierry Escande   NFC Digital: Add ...
50
51
52
53
54
55
56
57
58
59
60
61
  #define DIGITAL_NFC_DEP_PFB_I_PDU          0x00
  #define DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU   0x40
  #define DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU 0x80
  
  struct digital_atr_req {
  	u8 dir;
  	u8 cmd;
  	u8 nfcid3[10];
  	u8 did;
  	u8 bs;
  	u8 br;
  	u8 pp;
9814428a4   Gustavo A. R. Silva   NFC: digital: Rep...
62
  	u8 gb[];
7d0911c02   Thierry Escande   NFC Digital: Add ...
63
64
65
66
67
68
69
70
71
72
73
  } __packed;
  
  struct digital_atr_res {
  	u8 dir;
  	u8 cmd;
  	u8 nfcid3[10];
  	u8 did;
  	u8 bs;
  	u8 br;
  	u8 to;
  	u8 pp;
9814428a4   Gustavo A. R. Silva   NFC: digital: Rep...
74
  	u8 gb[];
7d0911c02   Thierry Escande   NFC Digital: Add ...
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  } __packed;
  
  struct digital_psl_req {
  	u8 dir;
  	u8 cmd;
  	u8 did;
  	u8 brs;
  	u8 fsl;
  } __packed;
  
  struct digital_psl_res {
  	u8 dir;
  	u8 cmd;
  	u8 did;
  } __packed;
  
  struct digital_dep_req_res {
  	u8 dir;
  	u8 cmd;
  	u8 pfb;
  } __packed;
  
  static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
  				    struct sk_buff *resp);
c12715ab3   Mark A. Greer   NFC: digital: Add...
99
100
  static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
  				    struct sk_buff *resp);
7d0911c02   Thierry Escande   NFC Digital: Add ...
101

b08147cbc   Mark A. Greer   NFC: digital: Imp...
102
103
104
105
106
107
  static const u8 digital_payload_bits_map[4] = {
  	[0] = 64,
  	[1] = 128,
  	[2] = 192,
  	[3] = 254
  };
1a09c56f5   Thierry Escande   NFC: digital: Add...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  /* Response Waiting Time for ATR_RES PDU in ms
   *
   * RWT(ATR_RES) = RWT(nfcdep,activation) + dRWT(nfcdep) + dT(nfcdep,initiator)
   *
   * with:
   *  RWT(nfcdep,activation) = 4096 * 2^12 / f(c) s
   *  dRWT(nfcdep) = 16 / f(c) s
   *  dT(nfcdep,initiator) = 100 ms
   *  f(c) = 13560000 Hz
   */
  #define DIGITAL_ATR_RES_RWT 1337
  
  /* Response Waiting Time for other DEP PDUs in ms
   *
   * max_rwt = rwt + dRWT(nfcdep) + dT(nfcdep,initiator)
   *
   * with:
   *  rwt = (256 * 16 / f(c)) * 2^wt s
   *  dRWT(nfcdep) = 16 / f(c) s
   *  dT(nfcdep,initiator) = 100 ms
   *  f(c) = 13560000 Hz
   *  0 <= wt <= 14 (given by the target by the TO field of ATR_RES response)
   */
  #define DIGITAL_NFC_DEP_IN_MAX_WT 14
1b609e438   Mark Greer   NFC: digital: NFC...
132
  #define DIGITAL_NFC_DEP_TG_MAX_WT 14
1a09c56f5   Thierry Escande   NFC: digital: Add...
133
134
135
136
137
  static const u16 digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT + 1] = {
  	100,  101,  101,  102,  105,
  	110,  119,  139,  177,  255,
  	409,  719, 1337, 2575, 5049,
  };
b08147cbc   Mark A. Greer   NFC: digital: Imp...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  static u8 digital_payload_bits_to_size(u8 payload_bits)
  {
  	if (payload_bits >= ARRAY_SIZE(digital_payload_bits_map))
  		return 0;
  
  	return digital_payload_bits_map[payload_bits];
  }
  
  static u8 digital_payload_size_to_bits(u8 payload_size)
  {
  	int i;
  
  	for (i = 0; i < ARRAY_SIZE(digital_payload_bits_map); i++)
  		if (digital_payload_bits_map[i] == payload_size)
  			return i;
  
  	return 0xff;
  }
7d0911c02   Thierry Escande   NFC Digital: Add ...
156
157
158
159
160
161
162
163
  static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev,
  				     struct sk_buff *skb)
  {
  	skb_push(skb, sizeof(u8));
  
  	skb->data[0] = skb->len;
  
  	if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
d58ff3512   Johannes Berg   networking: make ...
164
  		*(u8 *)skb_push(skb, sizeof(u8)) = DIGITAL_NFC_DEP_NFCA_SOD_SB;
7d0911c02   Thierry Escande   NFC Digital: Add ...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  }
  
  static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev,
  				    struct sk_buff *skb)
  {
  	u8 size;
  
  	if (skb->len < 2)
  		return -EIO;
  
  	if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
  		skb_pull(skb, sizeof(u8));
  
  	size = skb->data[0];
  	if (size != skb->len)
  		return -EIO;
  
  	skb_pull(skb, sizeof(u8));
  
  	return 0;
  }
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  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)
  {
  	struct sk_buff *new_skb;
  
  	if (skb->len > ddev->remote_payload_max) {
  		dep_req_res->pfb |= DIGITAL_NFC_DEP_PFB_MI_BIT;
  
  		new_skb = digital_skb_alloc(ddev, ddev->remote_payload_max);
  		if (!new_skb) {
  			kfree_skb(ddev->chaining_skb);
  			ddev->chaining_skb = NULL;
  
  			return ERR_PTR(-ENOMEM);
  		}
59ae1d127   Johannes Berg   networking: intro...
203
  		skb_put_data(new_skb, skb->data, ddev->remote_payload_max);
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
204
205
206
207
208
209
210
211
212
213
214
  		skb_pull(skb, ddev->remote_payload_max);
  
  		ddev->chaining_skb = skb;
  		ddev->data_exch = data_exch;
  	} else {
  		ddev->chaining_skb = NULL;
  		new_skb = skb;
  	}
  
  	return new_skb;
  }
c12715ab3   Mark A. Greer   NFC: digital: Add...
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  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)
  {
  	struct sk_buff *new_skb;
  	int rc;
  
  	if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb) && (!ddev->chaining_skb)) {
  		ddev->chaining_skb =
  			nfc_alloc_recv_skb(8 * ddev->local_payload_max,
  					   GFP_KERNEL);
  		if (!ddev->chaining_skb) {
  			rc = -ENOMEM;
  			goto error;
  		}
  	}
  
  	if (ddev->chaining_skb) {
  		if (resp->len > skb_tailroom(ddev->chaining_skb)) {
  			new_skb = skb_copy_expand(ddev->chaining_skb,
  						  skb_headroom(
  							  ddev->chaining_skb),
  						  8 * ddev->local_payload_max,
  						  GFP_KERNEL);
  			if (!new_skb) {
  				rc = -ENOMEM;
  				goto error;
  			}
  
  			kfree_skb(ddev->chaining_skb);
  			ddev->chaining_skb = new_skb;
  		}
59ae1d127   Johannes Berg   networking: intro...
251
  		skb_put_data(ddev->chaining_skb, resp->data, resp->len);
c12715ab3   Mark A. Greer   NFC: digital: Add...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  
  		kfree_skb(resp);
  		resp = NULL;
  
  		if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
  			rc = send_ack(ddev, data_exch);
  			if (rc)
  				goto error;
  
  			return NULL;
  		}
  
  		resp = ddev->chaining_skb;
  		ddev->chaining_skb = NULL;
  	}
  
  	return resp;
  
  error:
  	kfree_skb(resp);
  
  	kfree_skb(ddev->chaining_skb);
  	ddev->chaining_skb = NULL;
  
  	return ERR_PTR(rc);
  }
dddb3da04   Mark A. Greer   NFC: digital: Add...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg,
  				    struct sk_buff *resp)
  {
  	struct nfc_target *target = arg;
  	struct digital_psl_res *psl_res;
  	int rc;
  
  	if (IS_ERR(resp)) {
  		rc = PTR_ERR(resp);
  		resp = NULL;
  		goto exit;
  	}
  
  	rc = ddev->skb_check_crc(resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.6");
  		goto exit;
  	}
  
  	rc = digital_skb_pull_dep_sod(ddev, resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.2");
  		goto exit;
  	}
  
  	psl_res = (struct digital_psl_res *)resp->data;
  
  	if ((resp->len != sizeof(*psl_res)) ||
  	    (psl_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN) ||
  	    (psl_res->cmd != DIGITAL_CMD_PSL_RES)) {
  		rc = -EIO;
  		goto exit;
  	}
  
  	rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
  				     NFC_DIGITAL_RF_TECH_424F);
  	if (rc)
  		goto exit;
  
  	rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
  				     NFC_DIGITAL_FRAMING_NFCF_NFC_DEP);
  	if (rc)
  		goto exit;
  
  	if (!DIGITAL_DRV_CAPS_IN_CRC(ddev) &&
  	    (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)) {
  		ddev->skb_add_crc = digital_skb_add_crc_f;
  		ddev->skb_check_crc = digital_skb_check_crc_f;
  	}
  
  	ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_424F;
  
  	nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
  			   NFC_RF_INITIATOR);
  
  	ddev->curr_nfc_dep_pni = 0;
  
  exit:
  	dev_kfree_skb(resp);
  
  	if (rc)
  		ddev->curr_protocol = 0;
  }
  
  static int digital_in_send_psl_req(struct nfc_digital_dev *ddev,
  				   struct nfc_target *target)
  {
  	struct sk_buff *skb;
  	struct digital_psl_req *psl_req;
b15829ba5   Mark A. Greer   NFC: digital: Fix...
347
  	int rc;
b08147cbc   Mark A. Greer   NFC: digital: Imp...
348
  	u8 payload_size, payload_bits;
dddb3da04   Mark A. Greer   NFC: digital: Add...
349
350
351
352
353
354
355
356
357
358
359
360
361
  
  	skb = digital_skb_alloc(ddev, sizeof(*psl_req));
  	if (!skb)
  		return -ENOMEM;
  
  	skb_put(skb, sizeof(*psl_req));
  
  	psl_req = (struct digital_psl_req *)skb->data;
  
  	psl_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
  	psl_req->cmd = DIGITAL_CMD_PSL_REQ;
  	psl_req->did = 0;
  	psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */
b08147cbc   Mark A. Greer   NFC: digital: Imp...
362
363
364
365
366
367
368
  
  	payload_size = min(ddev->local_payload_max, ddev->remote_payload_max);
  	payload_bits = digital_payload_size_to_bits(payload_size);
  	psl_req->fsl = DIGITAL_PAYLOAD_BITS_TO_FSL(payload_bits);
  
  	ddev->local_payload_max = payload_size;
  	ddev->remote_payload_max = payload_size;
dddb3da04   Mark A. Greer   NFC: digital: Add...
369
370
371
372
  
  	digital_skb_push_dep_sod(ddev, skb);
  
  	ddev->skb_add_crc(skb);
1a09c56f5   Thierry Escande   NFC: digital: Add...
373
374
  	rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
  				 digital_in_recv_psl_res, target);
b15829ba5   Mark A. Greer   NFC: digital: Fix...
375
376
377
378
  	if (rc)
  		kfree_skb(skb);
  
  	return rc;
dddb3da04   Mark A. Greer   NFC: digital: Add...
379
  }
7d0911c02   Thierry Escande   NFC Digital: Add ...
380
381
382
383
384
  static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
  				 struct sk_buff *resp)
  {
  	struct nfc_target *target = arg;
  	struct digital_atr_res *atr_res;
b08147cbc   Mark A. Greer   NFC: digital: Imp...
385
  	u8 gb_len, payload_bits;
1a09c56f5   Thierry Escande   NFC: digital: Add...
386
  	u8 wt;
7d0911c02   Thierry Escande   NFC Digital: Add ...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
  	int rc;
  
  	if (IS_ERR(resp)) {
  		rc = PTR_ERR(resp);
  		resp = NULL;
  		goto exit;
  	}
  
  	rc = ddev->skb_check_crc(resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.6");
  		goto exit;
  	}
  
  	rc = digital_skb_pull_dep_sod(ddev, resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.2");
  		goto exit;
  	}
  
  	if (resp->len < sizeof(struct digital_atr_res)) {
  		rc = -EIO;
  		goto exit;
  	}
  
  	gb_len = resp->len - sizeof(struct digital_atr_res);
  
  	atr_res = (struct digital_atr_res *)resp->data;
1a09c56f5   Thierry Escande   NFC: digital: Add...
415
416
417
418
  	wt = DIGITAL_ATR_RES_TO_WT(atr_res->to);
  	if (wt > DIGITAL_NFC_DEP_IN_MAX_WT)
  		wt = DIGITAL_NFC_DEP_IN_MAX_WT;
  	ddev->dep_rwt = digital_rwt_map[wt];
b08147cbc   Mark A. Greer   NFC: digital: Imp...
419
420
421
422
423
424
425
  	payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_res->pp);
  	ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
  
  	if (!ddev->remote_payload_max) {
  		rc = -EINVAL;
  		goto exit;
  	}
7d0911c02   Thierry Escande   NFC Digital: Add ...
426
427
428
  	rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len);
  	if (rc)
  		goto exit;
dddb3da04   Mark A. Greer   NFC: digital: Add...
429
430
431
432
433
434
  	if ((ddev->protocols & NFC_PROTO_FELICA_MASK) &&
  	    (ddev->curr_rf_tech != NFC_DIGITAL_RF_TECH_424F)) {
  		rc = digital_in_send_psl_req(ddev, target);
  		if (!rc)
  			goto exit;
  	}
7d0911c02   Thierry Escande   NFC Digital: Add ...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
  	rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
  				NFC_RF_INITIATOR);
  
  	ddev->curr_nfc_dep_pni = 0;
  
  exit:
  	dev_kfree_skb(resp);
  
  	if (rc)
  		ddev->curr_protocol = 0;
  }
  
  int digital_in_send_atr_req(struct nfc_digital_dev *ddev,
  			    struct nfc_target *target, __u8 comm_mode, __u8 *gb,
  			    size_t gb_len)
  {
  	struct sk_buff *skb;
  	struct digital_atr_req *atr_req;
  	uint size;
b15829ba5   Mark A. Greer   NFC: digital: Fix...
454
  	int rc;
b08147cbc   Mark A. Greer   NFC: digital: Imp...
455
  	u8 payload_bits;
7d0911c02   Thierry Escande   NFC Digital: Add ...
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
  
  	size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len;
  
  	if (size > DIGITAL_ATR_REQ_MAX_SIZE) {
  		PROTOCOL_ERR("14.6.1.1");
  		return -EINVAL;
  	}
  
  	skb = digital_skb_alloc(ddev, size);
  	if (!skb)
  		return -ENOMEM;
  
  	skb_put(skb, sizeof(struct digital_atr_req));
  
  	atr_req = (struct digital_atr_req *)skb->data;
  	memset(atr_req, 0, sizeof(struct digital_atr_req));
  
  	atr_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
  	atr_req->cmd = DIGITAL_CMD_ATR_REQ;
  	if (target->nfcid2_len)
4f319e325   Thierry Escande   NFC: digital: Use...
476
  		memcpy(atr_req->nfcid3, target->nfcid2, NFC_NFCID2_MAXSIZE);
7d0911c02   Thierry Escande   NFC Digital: Add ...
477
  	else
4f319e325   Thierry Escande   NFC: digital: Use...
478
  		get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE);
7d0911c02   Thierry Escande   NFC Digital: Add ...
479
480
481
482
  
  	atr_req->did = 0;
  	atr_req->bs = 0;
  	atr_req->br = 0;
b08147cbc   Mark A. Greer   NFC: digital: Imp...
483
484
485
  	ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
  	payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
  	atr_req->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
7d0911c02   Thierry Escande   NFC Digital: Add ...
486
487
488
  
  	if (gb_len) {
  		atr_req->pp |= DIGITAL_GB_BIT;
59ae1d127   Johannes Berg   networking: intro...
489
  		skb_put_data(skb, gb, gb_len);
7d0911c02   Thierry Escande   NFC Digital: Add ...
490
491
492
493
494
  	}
  
  	digital_skb_push_dep_sod(ddev, skb);
  
  	ddev->skb_add_crc(skb);
1a09c56f5   Thierry Escande   NFC: digital: Add...
495
496
  	rc = digital_in_send_cmd(ddev, skb, DIGITAL_ATR_RES_RWT,
  				 digital_in_recv_atr_res, target);
b15829ba5   Mark A. Greer   NFC: digital: Fix...
497
498
499
500
  	if (rc)
  		kfree_skb(skb);
  
  	return rc;
7d0911c02   Thierry Escande   NFC Digital: Add ...
501
  }
c12715ab3   Mark A. Greer   NFC: digital: Add...
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
  static int digital_in_send_ack(struct nfc_digital_dev *ddev,
  			       struct digital_data_exch *data_exch)
  {
  	struct digital_dep_req_res *dep_req;
  	struct sk_buff *skb;
  	int rc;
  
  	skb = digital_skb_alloc(ddev, 1);
  	if (!skb)
  		return -ENOMEM;
  
  	skb_push(skb, sizeof(struct digital_dep_req_res));
  
  	dep_req = (struct digital_dep_req_res *)skb->data;
  
  	dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
  	dep_req->cmd = DIGITAL_CMD_DEP_REQ;
  	dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
  		       ddev->curr_nfc_dep_pni;
  
  	digital_skb_push_dep_sod(ddev, skb);
  
  	ddev->skb_add_crc(skb);
1d984c2e0   Thierry Escande   NFC: digital: Fix...
525
  	ddev->saved_skb = pskb_copy(skb, GFP_KERNEL);
384ab1d17   Mark A. Greer   NFC: digital: Add...
526

1a09c56f5   Thierry Escande   NFC: digital: Add...
527
528
  	rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
  				 digital_in_recv_dep_res, data_exch);
384ab1d17   Mark A. Greer   NFC: digital: Add...
529
  	if (rc) {
c12715ab3   Mark A. Greer   NFC: digital: Add...
530
  		kfree_skb(skb);
384ab1d17   Mark A. Greer   NFC: digital: Add...
531
532
533
  		kfree_skb(ddev->saved_skb);
  		ddev->saved_skb = NULL;
  	}
c12715ab3   Mark A. Greer   NFC: digital: Add...
534
535
536
  
  	return rc;
  }
a80509c76   Mark A. Greer   NFC: digital: Add...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
  static int digital_in_send_nack(struct nfc_digital_dev *ddev,
  				struct digital_data_exch *data_exch)
  {
  	struct digital_dep_req_res *dep_req;
  	struct sk_buff *skb;
  	int rc;
  
  	skb = digital_skb_alloc(ddev, 1);
  	if (!skb)
  		return -ENOMEM;
  
  	skb_push(skb, sizeof(struct digital_dep_req_res));
  
  	dep_req = (struct digital_dep_req_res *)skb->data;
  
  	dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
  	dep_req->cmd = DIGITAL_CMD_DEP_REQ;
  	dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
  		       DIGITAL_NFC_DEP_PFB_NACK_BIT | ddev->curr_nfc_dep_pni;
  
  	digital_skb_push_dep_sod(ddev, skb);
  
  	ddev->skb_add_crc(skb);
1a09c56f5   Thierry Escande   NFC: digital: Add...
560
561
  	rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
  				 digital_in_recv_dep_res, data_exch);
a80509c76   Mark A. Greer   NFC: digital: Add...
562
563
564
565
566
  	if (rc)
  		kfree_skb(skb);
  
  	return rc;
  }
384ab1d17   Mark A. Greer   NFC: digital: Add...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
  static int digital_in_send_atn(struct nfc_digital_dev *ddev,
  			       struct digital_data_exch *data_exch)
  {
  	struct digital_dep_req_res *dep_req;
  	struct sk_buff *skb;
  	int rc;
  
  	skb = digital_skb_alloc(ddev, 1);
  	if (!skb)
  		return -ENOMEM;
  
  	skb_push(skb, sizeof(struct digital_dep_req_res));
  
  	dep_req = (struct digital_dep_req_res *)skb->data;
  
  	dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
  	dep_req->cmd = DIGITAL_CMD_DEP_REQ;
  	dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
  
  	digital_skb_push_dep_sod(ddev, skb);
  
  	ddev->skb_add_crc(skb);
1a09c56f5   Thierry Escande   NFC: digital: Add...
589
590
  	rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
  				 digital_in_recv_dep_res, data_exch);
384ab1d17   Mark A. Greer   NFC: digital: Add...
591
592
593
594
595
  	if (rc)
  		kfree_skb(skb);
  
  	return rc;
  }
7d0911c02   Thierry Escande   NFC Digital: Add ...
596
597
598
599
600
601
  static int digital_in_send_rtox(struct nfc_digital_dev *ddev,
  				struct digital_data_exch *data_exch, u8 rtox)
  {
  	struct digital_dep_req_res *dep_req;
  	struct sk_buff *skb;
  	int rc;
d85a301c2   Thierry Escande   NFC: digital: Fix...
602
603
604
605
606
  	u16 rwt_int;
  
  	rwt_int = ddev->dep_rwt * rtox;
  	if (rwt_int > digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT])
  		rwt_int = digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT];
7d0911c02   Thierry Escande   NFC Digital: Add ...
607
608
609
610
  
  	skb = digital_skb_alloc(ddev, 1);
  	if (!skb)
  		return -ENOMEM;
634fef610   Johannes Berg   networking: add a...
611
  	skb_put_u8(skb, rtox);
7d0911c02   Thierry Escande   NFC Digital: Add ...
612
613
614
615
616
617
618
619
620
621
622
623
624
  
  	skb_push(skb, sizeof(struct digital_dep_req_res));
  
  	dep_req = (struct digital_dep_req_res *)skb->data;
  
  	dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
  	dep_req->cmd = DIGITAL_CMD_DEP_REQ;
  	dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU |
  		       DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT;
  
  	digital_skb_push_dep_sod(ddev, skb);
  
  	ddev->skb_add_crc(skb);
d85a301c2   Thierry Escande   NFC: digital: Fix...
625
  	rc = digital_in_send_cmd(ddev, skb, rwt_int,
1a09c56f5   Thierry Escande   NFC: digital: Add...
626
  				 digital_in_recv_dep_res, data_exch);
1d984c2e0   Thierry Escande   NFC: digital: Fix...
627
  	if (rc)
b15829ba5   Mark A. Greer   NFC: digital: Fix...
628
  		kfree_skb(skb);
7d0911c02   Thierry Escande   NFC Digital: Add ...
629
630
631
  
  	return rc;
  }
384ab1d17   Mark A. Greer   NFC: digital: Add...
632
633
634
  static int digital_in_send_saved_skb(struct nfc_digital_dev *ddev,
  				     struct digital_data_exch *data_exch)
  {
1d984c2e0   Thierry Escande   NFC: digital: Fix...
635
636
637
638
  	int rc;
  
  	if (!ddev->saved_skb)
  		return -EINVAL;
384ab1d17   Mark A. Greer   NFC: digital: Add...
639
  	skb_get(ddev->saved_skb);
384ab1d17   Mark A. Greer   NFC: digital: Add...
640

1a09c56f5   Thierry Escande   NFC: digital: Add...
641
  	rc = digital_in_send_cmd(ddev, ddev->saved_skb, ddev->dep_rwt,
1d984c2e0   Thierry Escande   NFC: digital: Fix...
642
643
644
645
646
  				 digital_in_recv_dep_res, data_exch);
  	if (rc)
  		kfree_skb(ddev->saved_skb);
  
  	return rc;
384ab1d17   Mark A. Greer   NFC: digital: Add...
647
  }
7d0911c02   Thierry Escande   NFC Digital: Add ...
648
649
650
651
652
653
654
655
  static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
  				    struct sk_buff *resp)
  {
  	struct digital_data_exch *data_exch = arg;
  	struct digital_dep_req_res *dep_res;
  	u8 pfb;
  	uint size;
  	int rc;
d85a301c2   Thierry Escande   NFC: digital: Fix...
656
  	u8 rtox;
7d0911c02   Thierry Escande   NFC Digital: Add ...
657
658
659
660
  
  	if (IS_ERR(resp)) {
  		rc = PTR_ERR(resp);
  		resp = NULL;
a80509c76   Mark A. Greer   NFC: digital: Add...
661

3f89fea35   Thierry Escande   NFC: digital: Rew...
662
  		if ((rc == -EIO || (rc == -ETIMEDOUT && ddev->nack_count)) &&
a80509c76   Mark A. Greer   NFC: digital: Add...
663
  		    (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
384ab1d17   Mark A. Greer   NFC: digital: Add...
664
  			ddev->atn_count = 0;
a80509c76   Mark A. Greer   NFC: digital: Add...
665
666
667
668
669
  			rc = digital_in_send_nack(ddev, data_exch);
  			if (rc)
  				goto error;
  
  			return;
384ab1d17   Mark A. Greer   NFC: digital: Add...
670
671
672
673
674
675
676
677
678
  		} else if ((rc == -ETIMEDOUT) &&
  			   (ddev->atn_count++ < DIGITAL_NFC_DEP_N_RETRY_ATN)) {
  			ddev->nack_count = 0;
  
  			rc = digital_in_send_atn(ddev, data_exch);
  			if (rc)
  				goto error;
  
  			return;
a80509c76   Mark A. Greer   NFC: digital: Add...
679
680
681
682
683
684
685
686
  		}
  
  		goto exit;
  	}
  
  	rc = digital_skb_pull_dep_sod(ddev, resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.2");
7d0911c02   Thierry Escande   NFC Digital: Add ...
687
688
689
690
691
  		goto exit;
  	}
  
  	rc = ddev->skb_check_crc(resp);
  	if (rc) {
a80509c76   Mark A. Greer   NFC: digital: Add...
692
693
  		if ((resp->len >= 4) &&
  		    (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
384ab1d17   Mark A. Greer   NFC: digital: Add...
694
  			ddev->atn_count = 0;
a80509c76   Mark A. Greer   NFC: digital: Add...
695
696
697
698
699
700
701
702
  			rc = digital_in_send_nack(ddev, data_exch);
  			if (rc)
  				goto error;
  
  			kfree_skb(resp);
  
  			return;
  		}
7d0911c02   Thierry Escande   NFC Digital: Add ...
703
704
705
  		PROTOCOL_ERR("14.4.1.6");
  		goto error;
  	}
384ab1d17   Mark A. Greer   NFC: digital: Add...
706
  	ddev->atn_count = 0;
a80509c76   Mark A. Greer   NFC: digital: Add...
707
  	ddev->nack_count = 0;
7d0911c02   Thierry Escande   NFC Digital: Add ...
708

b08147cbc   Mark A. Greer   NFC: digital: Imp...
709
710
711
712
  	if (resp->len > ddev->local_payload_max) {
  		rc = -EMSGSIZE;
  		goto exit;
  	}
6ce306682   Mark A. Greer   NFC: digital: Rea...
713
  	size = sizeof(struct digital_dep_req_res);
7d0911c02   Thierry Escande   NFC Digital: Add ...
714
  	dep_res = (struct digital_dep_req_res *)resp->data;
6ce306682   Mark A. Greer   NFC: digital: Rea...
715
  	if (resp->len < size || dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN ||
7d0911c02   Thierry Escande   NFC Digital: Add ...
716
717
718
719
720
721
  	    dep_res->cmd != DIGITAL_CMD_DEP_RES) {
  		rc = -EIO;
  		goto error;
  	}
  
  	pfb = dep_res->pfb;
3bc3f88af   Mark A. Greer   NFC: digital: Ens...
722
723
724
725
726
  	if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
  		PROTOCOL_ERR("14.8.2.1");
  		rc = -EIO;
  		goto error;
  	}
6ce306682   Mark A. Greer   NFC: digital: Rea...
727

3e6b0de80   Mark A. Greer   NFC: digital: Ens...
728
729
730
731
  	if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
  		rc = -EIO;
  		goto exit;
  	}
6ce306682   Mark A. Greer   NFC: digital: Rea...
732
733
734
735
736
737
  	if (size > resp->len) {
  		rc = -EIO;
  		goto error;
  	}
  
  	skb_pull(resp, size);
7d0911c02   Thierry Escande   NFC Digital: Add ...
738
739
740
741
742
743
744
745
746
747
  	switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
  	case DIGITAL_NFC_DEP_PFB_I_PDU:
  		if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
  			PROTOCOL_ERR("14.12.3.3");
  			rc = -EIO;
  			goto error;
  		}
  
  		ddev->curr_nfc_dep_pni =
  			DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
c12715ab3   Mark A. Greer   NFC: digital: Add...
748

384ab1d17   Mark A. Greer   NFC: digital: Add...
749
750
  		kfree_skb(ddev->saved_skb);
  		ddev->saved_skb = NULL;
c12715ab3   Mark A. Greer   NFC: digital: Add...
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
  		resp = digital_recv_dep_data_gather(ddev, pfb, resp,
  						    digital_in_send_ack,
  						    data_exch);
  		if (IS_ERR(resp)) {
  			rc = PTR_ERR(resp);
  			resp = NULL;
  			goto error;
  		}
  
  		/* If resp is NULL then we're still chaining so return and
  		 * wait for the next part of the PDU.  Else, the PDU is
  		 * complete so pass it up.
  		 */
  		if (!resp)
  			return;
7d0911c02   Thierry Escande   NFC Digital: Add ...
766
767
768
769
  		rc = 0;
  		break;
  
  	case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
e073eb679   Thierry Escande   NFC: digital: Rew...
770
771
772
773
774
  		if (DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) {
  			PROTOCOL_ERR("14.12.4.5");
  			rc = -EIO;
  			goto exit;
  		}
485fdc9bb   Mark A. Greer   NFC: digital: Enf...
775
776
777
778
779
780
781
782
  		if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
  			PROTOCOL_ERR("14.12.3.3");
  			rc = -EIO;
  			goto exit;
  		}
  
  		ddev->curr_nfc_dep_pni =
  			DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
e073eb679   Thierry Escande   NFC: digital: Rew...
783
784
785
786
787
  		if (!ddev->chaining_skb) {
  			PROTOCOL_ERR("14.12.4.3");
  			rc = -EIO;
  			goto exit;
  		}
384ab1d17   Mark A. Greer   NFC: digital: Add...
788

e073eb679   Thierry Escande   NFC: digital: Rew...
789
790
791
792
793
  		/* The initiator has received a valid ACK. Free the last sent
  		 * PDU and keep on sending chained skb.
  		 */
  		kfree_skb(ddev->saved_skb);
  		ddev->saved_skb = NULL;
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
794

e073eb679   Thierry Escande   NFC: digital: Rew...
795
796
797
798
799
  		rc = digital_in_send_dep_req(ddev, NULL,
  					     ddev->chaining_skb,
  					     ddev->data_exch);
  		if (rc)
  			goto error;
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
800

e073eb679   Thierry Escande   NFC: digital: Rew...
801
  		goto free_resp;
7d0911c02   Thierry Escande   NFC Digital: Add ...
802
803
  
  	case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
384ab1d17   Mark A. Greer   NFC: digital: Add...
804
805
  		if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { /* ATN */
  			rc = digital_in_send_saved_skb(ddev, data_exch);
1d984c2e0   Thierry Escande   NFC: digital: Fix...
806
  			if (rc)
384ab1d17   Mark A. Greer   NFC: digital: Add...
807
  				goto error;
384ab1d17   Mark A. Greer   NFC: digital: Add...
808

e200f008a   Thierry Escande   NFC: digital: Fre...
809
  			goto free_resp;
7d0911c02   Thierry Escande   NFC Digital: Add ...
810
  		}
d85a301c2   Thierry Escande   NFC: digital: Fix...
811
812
813
814
815
816
817
818
819
820
821
822
823
824
  		if (ddev->atn_count || ddev->nack_count) {
  			PROTOCOL_ERR("14.12.4.4");
  			rc = -EIO;
  			goto error;
  		}
  
  		rtox = DIGITAL_NFC_DEP_RTOX_VALUE(resp->data[0]);
  		if (!rtox || rtox > DIGITAL_NFC_DEP_RTOX_MAX) {
  			PROTOCOL_ERR("14.8.4.1");
  			rc = -EIO;
  			goto error;
  		}
  
  		rc = digital_in_send_rtox(ddev, data_exch, rtox);
7d0911c02   Thierry Escande   NFC Digital: Add ...
825
826
  		if (rc)
  			goto error;
e200f008a   Thierry Escande   NFC: digital: Fre...
827
  		goto free_resp;
7d0911c02   Thierry Escande   NFC Digital: Add ...
828
  	}
7d0911c02   Thierry Escande   NFC Digital: Add ...
829
830
831
832
833
  exit:
  	data_exch->cb(data_exch->cb_context, resp, rc);
  
  error:
  	kfree(data_exch);
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
834
835
  	kfree_skb(ddev->chaining_skb);
  	ddev->chaining_skb = NULL;
384ab1d17   Mark A. Greer   NFC: digital: Add...
836
837
  	kfree_skb(ddev->saved_skb);
  	ddev->saved_skb = NULL;
7d0911c02   Thierry Escande   NFC Digital: Add ...
838
839
  	if (rc)
  		kfree_skb(resp);
e073eb679   Thierry Escande   NFC: digital: Rew...
840
841
842
843
844
  
  	return;
  
  free_resp:
  	dev_kfree_skb(resp);
7d0911c02   Thierry Escande   NFC Digital: Add ...
845
846
847
848
849
850
851
  }
  
  int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
  			    struct nfc_target *target, struct sk_buff *skb,
  			    struct digital_data_exch *data_exch)
  {
  	struct digital_dep_req_res *dep_req;
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
852
853
  	struct sk_buff *chaining_skb, *tmp_skb;
  	int rc;
7d0911c02   Thierry Escande   NFC Digital: Add ...
854
855
856
857
  
  	skb_push(skb, sizeof(struct digital_dep_req_res));
  
  	dep_req = (struct digital_dep_req_res *)skb->data;
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
858

7d0911c02   Thierry Escande   NFC Digital: Add ...
859
860
861
  	dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
  	dep_req->cmd = DIGITAL_CMD_DEP_REQ;
  	dep_req->pfb = ddev->curr_nfc_dep_pni;
384ab1d17   Mark A. Greer   NFC: digital: Add...
862
  	ddev->atn_count = 0;
a80509c76   Mark A. Greer   NFC: digital: Add...
863
  	ddev->nack_count = 0;
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
864
  	chaining_skb = ddev->chaining_skb;
7d0911c02   Thierry Escande   NFC Digital: Add ...
865

3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
866
867
868
  	tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_req, data_exch);
  	if (IS_ERR(tmp_skb))
  		return PTR_ERR(tmp_skb);
7d0911c02   Thierry Escande   NFC Digital: Add ...
869

3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
870
871
872
  	digital_skb_push_dep_sod(ddev, tmp_skb);
  
  	ddev->skb_add_crc(tmp_skb);
1d984c2e0   Thierry Escande   NFC: digital: Fix...
873
  	ddev->saved_skb = pskb_copy(tmp_skb, GFP_KERNEL);
384ab1d17   Mark A. Greer   NFC: digital: Add...
874

1a09c56f5   Thierry Escande   NFC: digital: Add...
875
876
  	rc = digital_in_send_cmd(ddev, tmp_skb, ddev->dep_rwt,
  				 digital_in_recv_dep_res, data_exch);
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
877
878
879
880
881
882
  	if (rc) {
  		if (tmp_skb != skb)
  			kfree_skb(tmp_skb);
  
  		kfree_skb(chaining_skb);
  		ddev->chaining_skb = NULL;
384ab1d17   Mark A. Greer   NFC: digital: Add...
883
884
885
  
  		kfree_skb(ddev->saved_skb);
  		ddev->saved_skb = NULL;
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
886
887
888
  	}
  
  	return rc;
7d0911c02   Thierry Escande   NFC Digital: Add ...
889
  }
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
890

b711ad524   Thierry Escande   NFC: digital: Set...
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
  static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech)
  {
  	ddev->curr_rf_tech = rf_tech;
  
  	ddev->skb_add_crc = digital_skb_add_crc_none;
  	ddev->skb_check_crc = digital_skb_check_crc_none;
  
  	if (DIGITAL_DRV_CAPS_TG_CRC(ddev))
  		return;
  
  	switch (ddev->curr_rf_tech) {
  	case NFC_DIGITAL_RF_TECH_106A:
  		ddev->skb_add_crc = digital_skb_add_crc_a;
  		ddev->skb_check_crc = digital_skb_check_crc_a;
  		break;
  
  	case NFC_DIGITAL_RF_TECH_212F:
  	case NFC_DIGITAL_RF_TECH_424F:
  		ddev->skb_add_crc = digital_skb_add_crc_f;
  		ddev->skb_check_crc = digital_skb_check_crc_f;
  		break;
  
  	default:
  		break;
  	}
  }
c12715ab3   Mark A. Greer   NFC: digital: Add...
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
  static int digital_tg_send_ack(struct nfc_digital_dev *ddev,
  			       struct digital_data_exch *data_exch)
  {
  	struct digital_dep_req_res *dep_res;
  	struct sk_buff *skb;
  	int rc;
  
  	skb = digital_skb_alloc(ddev, 1);
  	if (!skb)
  		return -ENOMEM;
  
  	skb_push(skb, sizeof(struct digital_dep_req_res));
  
  	dep_res = (struct digital_dep_req_res *)skb->data;
  
  	dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
  	dep_res->cmd = DIGITAL_CMD_DEP_RES;
  	dep_res->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
  		       ddev->curr_nfc_dep_pni;
  
  	if (ddev->did) {
  		dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
59ae1d127   Johannes Berg   networking: intro...
939
  		skb_put_data(skb, &ddev->did, sizeof(ddev->did));
c12715ab3   Mark A. Greer   NFC: digital: Add...
940
941
942
943
944
945
946
947
  	}
  
  	ddev->curr_nfc_dep_pni =
  		DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
  
  	digital_skb_push_dep_sod(ddev, skb);
  
  	ddev->skb_add_crc(skb);
1d984c2e0   Thierry Escande   NFC: digital: Fix...
948
  	ddev->saved_skb = pskb_copy(skb, GFP_KERNEL);
49dbb14e3   Mark A. Greer   NFC: digital: Add...
949

c12715ab3   Mark A. Greer   NFC: digital: Add...
950
951
  	rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
  				 data_exch);
49dbb14e3   Mark A. Greer   NFC: digital: Add...
952
  	if (rc) {
c12715ab3   Mark A. Greer   NFC: digital: Add...
953
  		kfree_skb(skb);
49dbb14e3   Mark A. Greer   NFC: digital: Add...
954
955
956
  		kfree_skb(ddev->saved_skb);
  		ddev->saved_skb = NULL;
  	}
c12715ab3   Mark A. Greer   NFC: digital: Add...
957
958
959
  
  	return rc;
  }
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
  static int digital_tg_send_atn(struct nfc_digital_dev *ddev)
  {
  	struct digital_dep_req_res *dep_res;
  	struct sk_buff *skb;
  	int rc;
  
  	skb = digital_skb_alloc(ddev, 1);
  	if (!skb)
  		return -ENOMEM;
  
  	skb_push(skb, sizeof(struct digital_dep_req_res));
  
  	dep_res = (struct digital_dep_req_res *)skb->data;
  
  	dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
  	dep_res->cmd = DIGITAL_CMD_DEP_RES;
  	dep_res->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
  
  	if (ddev->did) {
  		dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
59ae1d127   Johannes Berg   networking: intro...
980
  		skb_put_data(skb, &ddev->did, sizeof(ddev->did));
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
981
982
983
984
985
986
987
988
989
990
991
992
993
  	}
  
  	digital_skb_push_dep_sod(ddev, skb);
  
  	ddev->skb_add_crc(skb);
  
  	rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
  				 NULL);
  	if (rc)
  		kfree_skb(skb);
  
  	return rc;
  }
49dbb14e3   Mark A. Greer   NFC: digital: Add...
994
995
  static int digital_tg_send_saved_skb(struct nfc_digital_dev *ddev)
  {
1d984c2e0   Thierry Escande   NFC: digital: Fix...
996
997
998
999
  	int rc;
  
  	if (!ddev->saved_skb)
  		return -EINVAL;
49dbb14e3   Mark A. Greer   NFC: digital: Add...
1000
  	skb_get(ddev->saved_skb);
49dbb14e3   Mark A. Greer   NFC: digital: Add...
1001

1d984c2e0   Thierry Escande   NFC: digital: Fix...
1002
1003
1004
1005
1006
1007
  	rc = digital_tg_send_cmd(ddev, ddev->saved_skb, 1500,
  				 digital_tg_recv_dep_req, NULL);
  	if (rc)
  		kfree_skb(ddev->saved_skb);
  
  	return rc;
49dbb14e3   Mark A. Greer   NFC: digital: Add...
1008
  }
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1009
1010
1011
1012
1013
  static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
  				    struct sk_buff *resp)
  {
  	int rc;
  	struct digital_dep_req_res *dep_req;
6ce306682   Mark A. Greer   NFC: digital: Rea...
1014
  	u8 pfb;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
  	size_t size;
  
  	if (IS_ERR(resp)) {
  		rc = PTR_ERR(resp);
  		resp = NULL;
  		goto exit;
  	}
  
  	rc = ddev->skb_check_crc(resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.6");
  		goto exit;
  	}
  
  	rc = digital_skb_pull_dep_sod(ddev, resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.2");
  		goto exit;
  	}
b08147cbc   Mark A. Greer   NFC: digital: Imp...
1034
1035
1036
1037
  	if (resp->len > ddev->local_payload_max) {
  		rc = -EMSGSIZE;
  		goto exit;
  	}
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1038
1039
1040
1041
1042
1043
1044
1045
  	size = sizeof(struct digital_dep_req_res);
  	dep_req = (struct digital_dep_req_res *)resp->data;
  
  	if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
  	    dep_req->cmd != DIGITAL_CMD_DEP_REQ) {
  		rc = -EIO;
  		goto exit;
  	}
6ce306682   Mark A. Greer   NFC: digital: Rea...
1046
  	pfb = dep_req->pfb;
05afedcb8   Mark A. Greer   NFC: digital: Add...
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
  	if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
  		if (ddev->did && (ddev->did == resp->data[3])) {
  			size++;
  		} else {
  			rc = -EIO;
  			goto exit;
  		}
  	} else if (ddev->did) {
  		rc = -EIO;
  		goto exit;
  	}
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1058

3e6b0de80   Mark A. Greer   NFC: digital: Ens...
1059
1060
1061
1062
  	if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
  		rc = -EIO;
  		goto exit;
  	}
6ce306682   Mark A. Greer   NFC: digital: Rea...
1063
  	if (size > resp->len) {
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1064
1065
1066
  		rc = -EIO;
  		goto exit;
  	}
6ce306682   Mark A. Greer   NFC: digital: Rea...
1067
1068
1069
  	skb_pull(resp, size);
  
  	switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1070
  	case DIGITAL_NFC_DEP_PFB_I_PDU:
260425308   Samuel Ortiz   NFC: digital: Add...
1071
1072
  		pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU
  ");
485fdc9bb   Mark A. Greer   NFC: digital: Enf...
1073

9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1074
  		if (ddev->atn_count) {
f23a9868b   Thierry Escande   NFC: digital: Fix...
1075
1076
1077
  			/* The target has received (and replied to) at least one
  			 * ATN DEP_REQ.
  			 */
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1078
  			ddev->atn_count = 0;
f23a9868b   Thierry Escande   NFC: digital: Fix...
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
  			/* pni of resp PDU equal to the target current pni - 1
  			 * means resp is the previous DEP_REQ PDU received from
  			 * the initiator so the target replies with saved_skb
  			 * which is the previous DEP_RES saved in
  			 * digital_tg_send_dep_res().
  			 */
  			if (DIGITAL_NFC_DEP_PFB_PNI(pfb) ==
  			  DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni - 1)) {
  				rc = digital_tg_send_saved_skb(ddev);
  				if (rc)
  					goto exit;
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1090

f23a9868b   Thierry Escande   NFC: digital: Fix...
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
  				goto free_resp;
  			}
  
  			/* atn_count > 0 and PDU pni != curr_nfc_dep_pni - 1
  			 * means the target probably did not received the last
  			 * DEP_REQ PDU sent by the initiator. The target
  			 * fallbacks to normal processing then.
  			 */
  		}
  
  		if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
  			PROTOCOL_ERR("14.12.3.4");
  			rc = -EIO;
  			goto exit;
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1105
  		}
49dbb14e3   Mark A. Greer   NFC: digital: Add...
1106
1107
  		kfree_skb(ddev->saved_skb);
  		ddev->saved_skb = NULL;
c12715ab3   Mark A. Greer   NFC: digital: Add...
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
  		resp = digital_recv_dep_data_gather(ddev, pfb, resp,
  						    digital_tg_send_ack, NULL);
  		if (IS_ERR(resp)) {
  			rc = PTR_ERR(resp);
  			resp = NULL;
  			goto exit;
  		}
  
  		/* If resp is NULL then we're still chaining so return and
  		 * wait for the next part of the PDU.  Else, the PDU is
  		 * complete so pass it up.
  		 */
  		if (!resp)
  			return;
485fdc9bb   Mark A. Greer   NFC: digital: Enf...
1122
  		rc = 0;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1123
1124
  		break;
  	case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
482333b27   Thierry Escande   NFC: digital: Fix...
1125
1126
1127
  		if (DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) { /* NACK */
  			if (DIGITAL_NFC_DEP_PFB_PNI(pfb + 1) !=
  						ddev->curr_nfc_dep_pni) {
49dbb14e3   Mark A. Greer   NFC: digital: Add...
1128
1129
1130
  				rc = -EIO;
  				goto exit;
  			}
482333b27   Thierry Escande   NFC: digital: Fix...
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
  			ddev->atn_count = 0;
  
  			rc = digital_tg_send_saved_skb(ddev);
  			if (rc)
  				goto exit;
  
  			goto free_resp;
  		}
  
  		/* ACK */
  		if (ddev->atn_count) {
  			/* The target has previously recevied one or more ATN
  			 * PDUs.
  			 */
  			ddev->atn_count = 0;
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1146

482333b27   Thierry Escande   NFC: digital: Fix...
1147
1148
1149
1150
1151
1152
  			/* If the ACK PNI is equal to the target PNI - 1 means
  			 * that the initiator did not receive the previous PDU
  			 * sent by the target so re-send it.
  			 */
  			if (DIGITAL_NFC_DEP_PFB_PNI(pfb + 1) ==
  						ddev->curr_nfc_dep_pni) {
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1153
1154
1155
  				rc = digital_tg_send_saved_skb(ddev);
  				if (rc)
  					goto exit;
482333b27   Thierry Escande   NFC: digital: Fix...
1156
  				goto free_resp;
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1157
  			}
482333b27   Thierry Escande   NFC: digital: Fix...
1158
1159
1160
1161
1162
  			/* Otherwise, the target did not receive the previous
  			 * ACK PDU from the initiator. Fallback to normal
  			 * processing of chained PDU then.
  			 */
  		}
485fdc9bb   Mark A. Greer   NFC: digital: Enf...
1163

482333b27   Thierry Escande   NFC: digital: Fix...
1164
1165
1166
1167
1168
1169
1170
  		/* Keep on sending chained PDU */
  		if (!ddev->chaining_skb ||
  		    DIGITAL_NFC_DEP_PFB_PNI(pfb) !=
  					ddev->curr_nfc_dep_pni) {
  			rc = -EIO;
  			goto exit;
  		}
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
1171

482333b27   Thierry Escande   NFC: digital: Fix...
1172
1173
  		kfree_skb(ddev->saved_skb);
  		ddev->saved_skb = NULL;
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1174

482333b27   Thierry Escande   NFC: digital: Fix...
1175
1176
1177
  		rc = digital_tg_send_dep_res(ddev, ddev->chaining_skb);
  		if (rc)
  			goto exit;
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
1178

482333b27   Thierry Escande   NFC: digital: Fix...
1179
  		goto free_resp;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1180
  	case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
  		if (DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
  			rc = -EINVAL;
  			goto exit;
  		}
  
  		rc = digital_tg_send_atn(ddev);
  		if (rc)
  			goto exit;
  
  		ddev->atn_count++;
e200f008a   Thierry Escande   NFC: digital: Fre...
1191
  		goto free_resp;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1192
  	}
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1193
1194
1195
  	rc = nfc_tm_data_received(ddev->nfc_dev, resp);
  
  exit:
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
1196
1197
  	kfree_skb(ddev->chaining_skb);
  	ddev->chaining_skb = NULL;
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1198
  	ddev->atn_count = 0;
49dbb14e3   Mark A. Greer   NFC: digital: Add...
1199
1200
  	kfree_skb(ddev->saved_skb);
  	ddev->saved_skb = NULL;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1201
1202
  	if (rc)
  		kfree_skb(resp);
f23a9868b   Thierry Escande   NFC: digital: Fix...
1203
1204
1205
1206
1207
  
  	return;
  
  free_resp:
  	dev_kfree_skb(resp);
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1208
1209
1210
1211
1212
  }
  
  int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
  {
  	struct digital_dep_req_res *dep_res;
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
1213
1214
  	struct sk_buff *chaining_skb, *tmp_skb;
  	int rc;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1215
1216
  
  	skb_push(skb, sizeof(struct digital_dep_req_res));
b08147cbc   Mark A. Greer   NFC: digital: Imp...
1217

1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1218
1219
1220
1221
1222
  	dep_res = (struct digital_dep_req_res *)skb->data;
  
  	dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
  	dep_res->cmd = DIGITAL_CMD_DEP_RES;
  	dep_res->pfb = ddev->curr_nfc_dep_pni;
05afedcb8   Mark A. Greer   NFC: digital: Add...
1223
1224
  	if (ddev->did) {
  		dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
59ae1d127   Johannes Berg   networking: intro...
1225
  		skb_put_data(skb, &ddev->did, sizeof(ddev->did));
05afedcb8   Mark A. Greer   NFC: digital: Add...
1226
  	}
485fdc9bb   Mark A. Greer   NFC: digital: Enf...
1227
1228
  	ddev->curr_nfc_dep_pni =
  		DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
1229
  	chaining_skb = ddev->chaining_skb;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1230

3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
1231
1232
1233
1234
1235
1236
1237
  	tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_res, NULL);
  	if (IS_ERR(tmp_skb))
  		return PTR_ERR(tmp_skb);
  
  	digital_skb_push_dep_sod(ddev, tmp_skb);
  
  	ddev->skb_add_crc(tmp_skb);
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1238

1d984c2e0   Thierry Escande   NFC: digital: Fix...
1239
  	ddev->saved_skb = pskb_copy(tmp_skb, GFP_KERNEL);
49dbb14e3   Mark A. Greer   NFC: digital: Add...
1240

3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
1241
1242
1243
1244
1245
1246
1247
1248
  	rc = digital_tg_send_cmd(ddev, tmp_skb, 1500, digital_tg_recv_dep_req,
  				 NULL);
  	if (rc) {
  		if (tmp_skb != skb)
  			kfree_skb(tmp_skb);
  
  		kfree_skb(chaining_skb);
  		ddev->chaining_skb = NULL;
49dbb14e3   Mark A. Greer   NFC: digital: Add...
1249
1250
1251
  
  		kfree_skb(ddev->saved_skb);
  		ddev->saved_skb = NULL;
3bd2a5bcc   Mark A. Greer   NFC: digital: Add...
1252
1253
1254
  	}
  
  	return rc;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1255
1256
1257
1258
1259
  }
  
  static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,
  					     void *arg, struct sk_buff *resp)
  {
67af1d7a0   Thierry Escande   NFC: digital: Fix...
1260
  	u8 rf_tech = (unsigned long)arg;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1261
1262
1263
  
  	if (IS_ERR(resp))
  		return;
b711ad524   Thierry Escande   NFC: digital: Set...
1264
  	digital_tg_set_rf_tech(ddev, rf_tech);
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
  	digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
  
  	digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL);
  
  	dev_kfree_skb(resp);
  }
  
  static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did,
  				   u8 rf_tech)
  {
  	struct digital_psl_res *psl_res;
  	struct sk_buff *skb;
  	int rc;
  
  	skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res));
  	if (!skb)
  		return -ENOMEM;
  
  	skb_put(skb, sizeof(struct digital_psl_res));
  
  	psl_res = (struct digital_psl_res *)skb->data;
  
  	psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
  	psl_res->cmd = DIGITAL_CMD_PSL_RES;
  	psl_res->did = did;
  
  	digital_skb_push_dep_sod(ddev, skb);
  
  	ddev->skb_add_crc(skb);
485fdc9bb   Mark A. Greer   NFC: digital: Enf...
1294
  	ddev->curr_nfc_dep_pni = 0;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1295
  	rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
67af1d7a0   Thierry Escande   NFC: digital: Fix...
1296
  				 (void *)(unsigned long)rf_tech);
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
  	if (rc)
  		kfree_skb(skb);
  
  	return rc;
  }
  
  static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg,
  				    struct sk_buff *resp)
  {
  	int rc;
  	struct digital_psl_req *psl_req;
  	u8 rf_tech;
b08147cbc   Mark A. Greer   NFC: digital: Imp...
1309
  	u8 dsi, payload_size, payload_bits;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
  
  	if (IS_ERR(resp)) {
  		rc = PTR_ERR(resp);
  		resp = NULL;
  		goto exit;
  	}
  
  	rc = ddev->skb_check_crc(resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.6");
  		goto exit;
  	}
  
  	rc = digital_skb_pull_dep_sod(ddev, resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.2");
  		goto exit;
  	}
  
  	psl_req = (struct digital_psl_req *)resp->data;
  
  	if (resp->len != sizeof(struct digital_psl_req) ||
  	    psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
  	    psl_req->cmd != DIGITAL_CMD_PSL_REQ) {
  		rc = -EIO;
  		goto exit;
  	}
  
  	dsi = (psl_req->brs >> 3) & 0x07;
  	switch (dsi) {
  	case 0:
  		rf_tech = NFC_DIGITAL_RF_TECH_106A;
  		break;
  	case 1:
  		rf_tech = NFC_DIGITAL_RF_TECH_212F;
  		break;
  	case 2:
  		rf_tech = NFC_DIGITAL_RF_TECH_424F;
  		break;
  	default:
77d84ff87   Masanari Iida   treewide: Fix typ...
1350
1351
  		pr_err("Unsupported dsi value %d
  ", dsi);
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1352
1353
  		goto exit;
  	}
b08147cbc   Mark A. Greer   NFC: digital: Imp...
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
  	payload_bits = DIGITAL_PAYLOAD_FSL_TO_BITS(psl_req->fsl);
  	payload_size = digital_payload_bits_to_size(payload_bits);
  
  	if (!payload_size || (payload_size > min(ddev->local_payload_max,
  						 ddev->remote_payload_max))) {
  		rc = -EINVAL;
  		goto exit;
  	}
  
  	ddev->local_payload_max = payload_size;
  	ddev->remote_payload_max = payload_size;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
  	rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
  
  exit:
  	kfree_skb(resp);
  }
  
  static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev,
  					     void *arg, struct sk_buff *resp)
  {
  	int offset;
  
  	if (IS_ERR(resp)) {
  		digital_poll_next_tech(ddev);
  		return;
  	}
  
  	offset = 2;
  	if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
  		offset++;
9b5ec0fd5   Mark A. Greer   NFC: digital: Add...
1384
  	ddev->atn_count = 0;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
  	if (resp->data[offset] == DIGITAL_CMD_PSL_REQ)
  		digital_tg_recv_psl_req(ddev, arg, resp);
  	else
  		digital_tg_recv_dep_req(ddev, arg, resp);
  }
  
  static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,
  				   struct digital_atr_req *atr_req)
  {
  	struct digital_atr_res *atr_res;
  	struct sk_buff *skb;
b08147cbc   Mark A. Greer   NFC: digital: Imp...
1396
  	u8 *gb, payload_bits;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
  	size_t gb_len;
  	int rc;
  
  	gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len);
  	if (!gb)
  		gb_len = 0;
  
  	skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len);
  	if (!skb)
  		return -ENOMEM;
  
  	skb_put(skb, sizeof(struct digital_atr_res));
  	atr_res = (struct digital_atr_res *)skb->data;
  
  	memset(atr_res, 0, sizeof(struct digital_atr_res));
  
  	atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
  	atr_res->cmd = DIGITAL_CMD_ATR_RES;
  	memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
1a09c56f5   Thierry Escande   NFC: digital: Add...
1416
  	atr_res->to = DIGITAL_NFC_DEP_TG_MAX_WT;
b08147cbc   Mark A. Greer   NFC: digital: Imp...
1417
1418
1419
1420
  
  	ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
  	payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
  	atr_res->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
  	if (gb_len) {
  		skb_put(skb, gb_len);
  
  		atr_res->pp |= DIGITAL_GB_BIT;
  		memcpy(atr_res->gb, gb, gb_len);
  	}
  
  	digital_skb_push_dep_sod(ddev, skb);
  
  	ddev->skb_add_crc(skb);
485fdc9bb   Mark A. Greer   NFC: digital: Enf...
1431
  	ddev->curr_nfc_dep_pni = 0;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1432
1433
  	rc = digital_tg_send_cmd(ddev, skb, 999,
  				 digital_tg_send_atr_res_complete, NULL);
b15829ba5   Mark A. Greer   NFC: digital: Fix...
1434
  	if (rc)
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1435
  		kfree_skb(skb);
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
  
  	return rc;
  }
  
  void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg,
  			     struct sk_buff *resp)
  {
  	int rc;
  	struct digital_atr_req *atr_req;
  	size_t gb_len, min_size;
b08147cbc   Mark A. Greer   NFC: digital: Imp...
1446
  	u8 poll_tech_count, payload_bits;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
  
  	if (IS_ERR(resp)) {
  		rc = PTR_ERR(resp);
  		resp = NULL;
  		goto exit;
  	}
  
  	if (!resp->len) {
  		rc = -EIO;
  		goto exit;
  	}
  
  	if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) {
  		min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2;
b711ad524   Thierry Escande   NFC: digital: Set...
1461
  		digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_106A);
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1462
1463
  	} else {
  		min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1;
b711ad524   Thierry Escande   NFC: digital: Set...
1464
  		digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_212F);
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1465
1466
1467
1468
1469
1470
  	}
  
  	if (resp->len < min_size) {
  		rc = -EIO;
  		goto exit;
  	}
48e104451   Thierry Escande   NFC: digital: Set...
1471
  	ddev->curr_protocol = NFC_PROTO_NFC_DEP_MASK;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
  
  	rc = ddev->skb_check_crc(resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.6");
  		goto exit;
  	}
  
  	rc = digital_skb_pull_dep_sod(ddev, resp);
  	if (rc) {
  		PROTOCOL_ERR("14.4.1.2");
  		goto exit;
  	}
  
  	atr_req = (struct digital_atr_req *)resp->data;
  
  	if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
05afedcb8   Mark A. Greer   NFC: digital: Add...
1488
1489
  	    atr_req->cmd != DIGITAL_CMD_ATR_REQ ||
  	    atr_req->did > DIGITAL_DID_MAX) {
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1490
1491
1492
  		rc = -EINVAL;
  		goto exit;
  	}
b08147cbc   Mark A. Greer   NFC: digital: Imp...
1493
1494
1495
1496
1497
1498
1499
  	payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_req->pp);
  	ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
  
  	if (!ddev->remote_payload_max) {
  		rc = -EINVAL;
  		goto exit;
  	}
05afedcb8   Mark A. Greer   NFC: digital: Add...
1500
  	ddev->did = atr_req->did;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
  	rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
  				     NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
  	if (rc)
  		goto exit;
  
  	rc = digital_tg_send_atr_res(ddev, atr_req);
  	if (rc)
  		goto exit;
  
  	gb_len = resp->len - sizeof(struct digital_atr_req);
0529a7adf   Mark A. Greer   NFC: digital: Cle...
1511
1512
1513
  
  	poll_tech_count = ddev->poll_tech_count;
  	ddev->poll_tech_count = 0;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1514
1515
  	rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
  			      NFC_COMM_PASSIVE, atr_req->gb, gb_len);
0529a7adf   Mark A. Greer   NFC: digital: Cle...
1516
1517
  	if (rc) {
  		ddev->poll_tech_count = poll_tech_count;
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1518
  		goto exit;
0529a7adf   Mark A. Greer   NFC: digital: Cle...
1519
  	}
1c7a4c24f   Thierry Escande   NFC Digital: Add ...
1520
1521
1522
1523
1524
1525
1526
1527
  
  	rc = 0;
  exit:
  	if (rc)
  		digital_poll_next_tech(ddev);
  
  	dev_kfree_skb(resp);
  }