1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. |
4 | */ |
5 | |
6 | #include <net/nfc/hci.h> |
7 | |
8 | #include "st21nfca.h" |
9 | |
10 | #define ST21NFCA_NFCIP1_INITIATOR 0x00 |
11 | #define ST21NFCA_NFCIP1_REQ 0xd4 |
12 | #define ST21NFCA_NFCIP1_RES 0xd5 |
13 | #define ST21NFCA_NFCIP1_ATR_REQ 0x00 |
14 | #define ST21NFCA_NFCIP1_ATR_RES 0x01 |
15 | #define ST21NFCA_NFCIP1_PSL_REQ 0x04 |
16 | #define ST21NFCA_NFCIP1_PSL_RES 0x05 |
17 | #define ST21NFCA_NFCIP1_DEP_REQ 0x06 |
18 | #define ST21NFCA_NFCIP1_DEP_RES 0x07 |
19 | |
20 | #define ST21NFCA_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03) |
21 | #define ST21NFCA_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) |
22 | #define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ |
23 | ((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT) |
24 | #define ST21NFCA_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04) |
25 | #define ST21NFCA_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08) |
26 | #define ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT 0x10 |
27 | |
28 | #define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ |
29 | ((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT) |
30 | |
31 | #define ST21NFCA_NFC_DEP_PFB_I_PDU 0x00 |
32 | #define ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU 0x40 |
33 | #define ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU 0x80 |
34 | |
35 | #define ST21NFCA_ATR_REQ_MIN_SIZE 17 |
36 | #define ST21NFCA_ATR_REQ_MAX_SIZE 65 |
37 | #define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30 |
38 | #define ST21NFCA_GB_BIT 0x02 |
39 | |
40 | #define ST21NFCA_EVT_SEND_DATA 0x10 |
41 | #define ST21NFCA_EVT_FIELD_ON 0x11 |
42 | #define ST21NFCA_EVT_CARD_DEACTIVATED 0x12 |
43 | #define ST21NFCA_EVT_CARD_ACTIVATED 0x13 |
44 | #define ST21NFCA_EVT_FIELD_OFF 0x14 |
45 | |
46 | #define ST21NFCA_EVT_CARD_F_BITRATE 0x16 |
47 | #define ST21NFCA_EVT_READER_F_BITRATE 0x13 |
48 | #define ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38) |
49 | #define ST21NFCA_PSL_REQ_RECV_SPEED(brs) (brs & 0x07) |
50 | #define ST21NFCA_PP2LRI(pp) ((pp & 0x30) >> 4) |
51 | #define ST21NFCA_CARD_BITRATE_212 0x01 |
52 | #define ST21NFCA_CARD_BITRATE_424 0x02 |
53 | |
54 | #define ST21NFCA_DEFAULT_TIMEOUT 0x0a |
55 | |
56 | |
57 | #define PROTOCOL_ERR(req) pr_err("%d: ST21NFCA Protocol error: %s\n", \ |
58 | __LINE__, req) |
59 | |
60 | struct st21nfca_atr_req { |
61 | u8 length; |
62 | u8 cmd0; |
63 | u8 cmd1; |
64 | u8 nfcid3[NFC_NFCID3_MAXSIZE]; |
65 | u8 did; |
66 | u8 bsi; |
67 | u8 bri; |
68 | u8 ppi; |
69 | u8 gbi[]; |
70 | } __packed; |
71 | |
72 | struct st21nfca_atr_res { |
73 | u8 length; |
74 | u8 cmd0; |
75 | u8 cmd1; |
76 | u8 nfcid3[NFC_NFCID3_MAXSIZE]; |
77 | u8 did; |
78 | u8 bsi; |
79 | u8 bri; |
80 | u8 to; |
81 | u8 ppi; |
82 | u8 gbi[]; |
83 | } __packed; |
84 | |
85 | struct st21nfca_psl_req { |
86 | u8 length; |
87 | u8 cmd0; |
88 | u8 cmd1; |
89 | u8 did; |
90 | u8 brs; |
91 | u8 fsl; |
92 | } __packed; |
93 | |
94 | struct st21nfca_psl_res { |
95 | u8 length; |
96 | u8 cmd0; |
97 | u8 cmd1; |
98 | u8 did; |
99 | } __packed; |
100 | |
101 | struct st21nfca_dep_req_res { |
102 | u8 length; |
103 | u8 cmd0; |
104 | u8 cmd1; |
105 | u8 pfb; |
106 | u8 did; |
107 | u8 nad; |
108 | } __packed; |
109 | |
110 | static void st21nfca_tx_work(struct work_struct *work) |
111 | { |
112 | struct st21nfca_hci_info *info = container_of(work, |
113 | struct st21nfca_hci_info, |
114 | dep_info.tx_work); |
115 | |
116 | struct nfc_dev *dev; |
117 | struct sk_buff *skb; |
118 | |
119 | if (info) { |
120 | dev = info->hdev->ndev; |
121 | skb = info->dep_info.tx_pending; |
122 | |
123 | device_lock(dev: &dev->dev); |
124 | |
125 | nfc_hci_send_cmd_async(hdev: info->hdev, ST21NFCA_RF_READER_F_GATE, |
126 | ST21NFCA_WR_XCHG_DATA, param: skb->data, param_len: skb->len, |
127 | cb: info->async_cb, cb_context: info); |
128 | device_unlock(dev: &dev->dev); |
129 | kfree_skb(skb); |
130 | } |
131 | } |
132 | |
133 | static void st21nfca_im_send_pdu(struct st21nfca_hci_info *info, |
134 | struct sk_buff *skb) |
135 | { |
136 | info->dep_info.tx_pending = skb; |
137 | schedule_work(work: &info->dep_info.tx_work); |
138 | } |
139 | |
140 | static int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev, |
141 | struct st21nfca_atr_req *atr_req) |
142 | { |
143 | struct st21nfca_atr_res *atr_res; |
144 | struct sk_buff *skb; |
145 | size_t gb_len; |
146 | int r; |
147 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
148 | |
149 | gb_len = atr_req->length - sizeof(struct st21nfca_atr_req); |
150 | skb = alloc_skb(size: atr_req->length + 1, GFP_KERNEL); |
151 | if (!skb) |
152 | return -ENOMEM; |
153 | |
154 | skb_put(skb, len: sizeof(struct st21nfca_atr_res)); |
155 | |
156 | atr_res = (struct st21nfca_atr_res *)skb->data; |
157 | memset(atr_res, 0, sizeof(struct st21nfca_atr_res)); |
158 | |
159 | atr_res->length = atr_req->length + 1; |
160 | atr_res->cmd0 = ST21NFCA_NFCIP1_RES; |
161 | atr_res->cmd1 = ST21NFCA_NFCIP1_ATR_RES; |
162 | |
163 | memcpy(atr_res->nfcid3, atr_req->nfcid3, 6); |
164 | atr_res->bsi = 0x00; |
165 | atr_res->bri = 0x00; |
166 | atr_res->to = ST21NFCA_DEFAULT_TIMEOUT; |
167 | atr_res->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B; |
168 | |
169 | if (gb_len) { |
170 | skb_put(skb, len: gb_len); |
171 | |
172 | atr_res->ppi |= ST21NFCA_GB_BIT; |
173 | memcpy(atr_res->gbi, atr_req->gbi, gb_len); |
174 | r = nfc_set_remote_general_bytes(dev: hdev->ndev, gt: atr_res->gbi, |
175 | gt_len: gb_len); |
176 | if (r < 0) { |
177 | kfree_skb(skb); |
178 | return r; |
179 | } |
180 | } |
181 | |
182 | info->dep_info.curr_nfc_dep_pni = 0; |
183 | |
184 | r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, |
185 | ST21NFCA_EVT_SEND_DATA, param: skb->data, param_len: skb->len); |
186 | kfree_skb(skb); |
187 | return r; |
188 | } |
189 | |
190 | static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev, |
191 | struct sk_buff *skb) |
192 | { |
193 | struct st21nfca_atr_req *atr_req; |
194 | size_t gb_len; |
195 | int r; |
196 | |
197 | skb_trim(skb, len: skb->len - 1); |
198 | |
199 | if (!skb->len) |
200 | return -EIO; |
201 | |
202 | if (skb->len < ST21NFCA_ATR_REQ_MIN_SIZE) |
203 | return -EPROTO; |
204 | |
205 | atr_req = (struct st21nfca_atr_req *)skb->data; |
206 | |
207 | if (atr_req->length < sizeof(struct st21nfca_atr_req)) |
208 | return -EPROTO; |
209 | |
210 | r = st21nfca_tm_send_atr_res(hdev, atr_req); |
211 | if (r) |
212 | return r; |
213 | |
214 | gb_len = skb->len - sizeof(struct st21nfca_atr_req); |
215 | |
216 | r = nfc_tm_activated(dev: hdev->ndev, NFC_PROTO_NFC_DEP_MASK, |
217 | NFC_COMM_PASSIVE, gb: atr_req->gbi, gb_len); |
218 | if (r) |
219 | return r; |
220 | |
221 | return 0; |
222 | } |
223 | |
224 | static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev, |
225 | struct st21nfca_psl_req *psl_req) |
226 | { |
227 | struct st21nfca_psl_res *psl_res; |
228 | struct sk_buff *skb; |
229 | u8 bitrate[2] = {0, 0}; |
230 | int r; |
231 | |
232 | skb = alloc_skb(size: sizeof(struct st21nfca_psl_res), GFP_KERNEL); |
233 | if (!skb) |
234 | return -ENOMEM; |
235 | skb_put(skb, len: sizeof(struct st21nfca_psl_res)); |
236 | |
237 | psl_res = (struct st21nfca_psl_res *)skb->data; |
238 | |
239 | psl_res->length = sizeof(struct st21nfca_psl_res); |
240 | psl_res->cmd0 = ST21NFCA_NFCIP1_RES; |
241 | psl_res->cmd1 = ST21NFCA_NFCIP1_PSL_RES; |
242 | psl_res->did = psl_req->did; |
243 | |
244 | r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, |
245 | ST21NFCA_EVT_SEND_DATA, param: skb->data, param_len: skb->len); |
246 | if (r < 0) |
247 | goto error; |
248 | |
249 | /* |
250 | * ST21NFCA only support P2P passive. |
251 | * PSL_REQ BRS value != 0 has only a meaning to |
252 | * change technology to type F. |
253 | * We change to BITRATE 424Kbits. |
254 | * In other case switch to BITRATE 106Kbits. |
255 | */ |
256 | if (ST21NFCA_PSL_REQ_SEND_SPEED(psl_req->brs) && |
257 | ST21NFCA_PSL_REQ_RECV_SPEED(psl_req->brs)) { |
258 | bitrate[0] = ST21NFCA_CARD_BITRATE_424; |
259 | bitrate[1] = ST21NFCA_CARD_BITRATE_424; |
260 | } |
261 | |
262 | /* Send an event to change bitrate change event to card f */ |
263 | r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, |
264 | ST21NFCA_EVT_CARD_F_BITRATE, param: bitrate, param_len: 2); |
265 | error: |
266 | kfree_skb(skb); |
267 | return r; |
268 | } |
269 | |
270 | static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev, |
271 | struct sk_buff *skb) |
272 | { |
273 | struct st21nfca_psl_req *psl_req; |
274 | |
275 | skb_trim(skb, len: skb->len - 1); |
276 | |
277 | if (!skb->len) |
278 | return -EIO; |
279 | |
280 | psl_req = (struct st21nfca_psl_req *)skb->data; |
281 | |
282 | if (skb->len < sizeof(struct st21nfca_psl_req)) |
283 | return -EIO; |
284 | |
285 | return st21nfca_tm_send_psl_res(hdev, psl_req); |
286 | } |
287 | |
288 | int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb) |
289 | { |
290 | int r; |
291 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
292 | |
293 | *(u8 *)skb_push(skb, len: 1) = info->dep_info.curr_nfc_dep_pni; |
294 | *(u8 *)skb_push(skb, len: 1) = ST21NFCA_NFCIP1_DEP_RES; |
295 | *(u8 *)skb_push(skb, len: 1) = ST21NFCA_NFCIP1_RES; |
296 | *(u8 *)skb_push(skb, len: 1) = skb->len; |
297 | |
298 | r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, |
299 | ST21NFCA_EVT_SEND_DATA, param: skb->data, param_len: skb->len); |
300 | kfree_skb(skb); |
301 | |
302 | return r; |
303 | } |
304 | EXPORT_SYMBOL(st21nfca_tm_send_dep_res); |
305 | |
306 | static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev, |
307 | struct sk_buff *skb) |
308 | { |
309 | struct st21nfca_dep_req_res *dep_req; |
310 | u8 size; |
311 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
312 | |
313 | skb_trim(skb, len: skb->len - 1); |
314 | |
315 | size = 4; |
316 | |
317 | dep_req = (struct st21nfca_dep_req_res *)skb->data; |
318 | if (skb->len < size) |
319 | return -EIO; |
320 | |
321 | if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_req->pfb)) |
322 | size++; |
323 | if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_req->pfb)) |
324 | size++; |
325 | |
326 | if (skb->len < size) |
327 | return -EIO; |
328 | |
329 | /* Receiving DEP_REQ - Decoding */ |
330 | switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_req->pfb)) { |
331 | case ST21NFCA_NFC_DEP_PFB_I_PDU: |
332 | info->dep_info.curr_nfc_dep_pni = |
333 | ST21NFCA_NFC_DEP_PFB_PNI(dep_req->pfb); |
334 | break; |
335 | case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU: |
336 | pr_err("Received a ACK/NACK PDU\n" ); |
337 | break; |
338 | case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU: |
339 | pr_err("Received a SUPERVISOR PDU\n" ); |
340 | break; |
341 | } |
342 | |
343 | skb_pull(skb, len: size); |
344 | |
345 | return nfc_tm_data_received(dev: hdev->ndev, skb); |
346 | } |
347 | |
348 | static int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, |
349 | struct sk_buff *skb) |
350 | { |
351 | u8 cmd0, cmd1; |
352 | int r; |
353 | |
354 | cmd0 = skb->data[1]; |
355 | switch (cmd0) { |
356 | case ST21NFCA_NFCIP1_REQ: |
357 | cmd1 = skb->data[2]; |
358 | switch (cmd1) { |
359 | case ST21NFCA_NFCIP1_ATR_REQ: |
360 | r = st21nfca_tm_recv_atr_req(hdev, skb); |
361 | break; |
362 | case ST21NFCA_NFCIP1_PSL_REQ: |
363 | r = st21nfca_tm_recv_psl_req(hdev, skb); |
364 | break; |
365 | case ST21NFCA_NFCIP1_DEP_REQ: |
366 | r = st21nfca_tm_recv_dep_req(hdev, skb); |
367 | break; |
368 | default: |
369 | return 1; |
370 | } |
371 | break; |
372 | default: |
373 | return 1; |
374 | } |
375 | return r; |
376 | } |
377 | |
378 | /* |
379 | * Returns: |
380 | * <= 0: driver handled the event, skb consumed |
381 | * 1: driver does not handle the event, please do standard processing |
382 | */ |
383 | int st21nfca_dep_event_received(struct nfc_hci_dev *hdev, |
384 | u8 event, struct sk_buff *skb) |
385 | { |
386 | int r = 0; |
387 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
388 | |
389 | pr_debug("dep event: %d\n" , event); |
390 | |
391 | switch (event) { |
392 | case ST21NFCA_EVT_CARD_ACTIVATED: |
393 | info->dep_info.curr_nfc_dep_pni = 0; |
394 | break; |
395 | case ST21NFCA_EVT_CARD_DEACTIVATED: |
396 | break; |
397 | case ST21NFCA_EVT_FIELD_ON: |
398 | break; |
399 | case ST21NFCA_EVT_FIELD_OFF: |
400 | break; |
401 | case ST21NFCA_EVT_SEND_DATA: |
402 | r = st21nfca_tm_event_send_data(hdev, skb); |
403 | if (r < 0) |
404 | return r; |
405 | return 0; |
406 | default: |
407 | nfc_err(&hdev->ndev->dev, "Unexpected event on card f gate\n" ); |
408 | return 1; |
409 | } |
410 | kfree_skb(skb); |
411 | return r; |
412 | } |
413 | EXPORT_SYMBOL(st21nfca_dep_event_received); |
414 | |
415 | static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi, |
416 | u8 bri, u8 lri) |
417 | { |
418 | struct sk_buff *skb; |
419 | struct st21nfca_psl_req *psl_req; |
420 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
421 | |
422 | skb = |
423 | alloc_skb(size: sizeof(struct st21nfca_psl_req) + 1, GFP_KERNEL); |
424 | if (!skb) |
425 | return; |
426 | skb_reserve(skb, len: 1); |
427 | |
428 | skb_put(skb, len: sizeof(struct st21nfca_psl_req)); |
429 | psl_req = (struct st21nfca_psl_req *) skb->data; |
430 | |
431 | psl_req->length = sizeof(struct st21nfca_psl_req); |
432 | psl_req->cmd0 = ST21NFCA_NFCIP1_REQ; |
433 | psl_req->cmd1 = ST21NFCA_NFCIP1_PSL_REQ; |
434 | psl_req->did = did; |
435 | psl_req->brs = (0x30 & bsi << 4) | (bri & 0x03); |
436 | psl_req->fsl = lri; |
437 | |
438 | *(u8 *)skb_push(skb, len: 1) = info->dep_info.to | 0x10; |
439 | |
440 | st21nfca_im_send_pdu(info, skb); |
441 | } |
442 | |
443 | #define ST21NFCA_CB_TYPE_READER_F 1 |
444 | static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb, |
445 | int err) |
446 | { |
447 | struct st21nfca_hci_info *info = context; |
448 | struct st21nfca_atr_res *atr_res; |
449 | int r; |
450 | |
451 | if (err != 0) |
452 | return; |
453 | |
454 | if (!skb) |
455 | return; |
456 | |
457 | switch (info->async_cb_type) { |
458 | case ST21NFCA_CB_TYPE_READER_F: |
459 | skb_trim(skb, len: skb->len - 1); |
460 | atr_res = (struct st21nfca_atr_res *)skb->data; |
461 | r = nfc_set_remote_general_bytes(dev: info->hdev->ndev, |
462 | gt: atr_res->gbi, |
463 | gt_len: skb->len - sizeof(struct st21nfca_atr_res)); |
464 | if (r < 0) |
465 | return; |
466 | |
467 | if (atr_res->to >= 0x0e) |
468 | info->dep_info.to = 0x0e; |
469 | else |
470 | info->dep_info.to = atr_res->to + 1; |
471 | |
472 | info->dep_info.to |= 0x10; |
473 | |
474 | r = nfc_dep_link_is_up(dev: info->hdev->ndev, target_idx: info->dep_info.idx, |
475 | NFC_COMM_PASSIVE, NFC_RF_INITIATOR); |
476 | if (r < 0) |
477 | return; |
478 | |
479 | info->dep_info.curr_nfc_dep_pni = 0; |
480 | if (ST21NFCA_PP2LRI(atr_res->ppi) != info->dep_info.lri) |
481 | st21nfca_im_send_psl_req(hdev: info->hdev, did: atr_res->did, |
482 | bsi: atr_res->bsi, bri: atr_res->bri, |
483 | ST21NFCA_PP2LRI(atr_res->ppi)); |
484 | break; |
485 | default: |
486 | kfree_skb(skb); |
487 | break; |
488 | } |
489 | } |
490 | |
491 | int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len) |
492 | { |
493 | struct sk_buff *skb; |
494 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
495 | struct st21nfca_atr_req *atr_req; |
496 | struct nfc_target *target; |
497 | uint size; |
498 | |
499 | info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT; |
500 | size = ST21NFCA_ATR_REQ_MIN_SIZE + gb_len; |
501 | if (size > ST21NFCA_ATR_REQ_MAX_SIZE) { |
502 | PROTOCOL_ERR("14.6.1.1" ); |
503 | return -EINVAL; |
504 | } |
505 | |
506 | skb = |
507 | alloc_skb(size: sizeof(struct st21nfca_atr_req) + gb_len + 1, GFP_KERNEL); |
508 | if (!skb) |
509 | return -ENOMEM; |
510 | |
511 | skb_reserve(skb, len: 1); |
512 | |
513 | skb_put(skb, len: sizeof(struct st21nfca_atr_req)); |
514 | |
515 | atr_req = (struct st21nfca_atr_req *)skb->data; |
516 | memset(atr_req, 0, sizeof(struct st21nfca_atr_req)); |
517 | |
518 | atr_req->cmd0 = ST21NFCA_NFCIP1_REQ; |
519 | atr_req->cmd1 = ST21NFCA_NFCIP1_ATR_REQ; |
520 | memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE); |
521 | target = hdev->ndev->targets; |
522 | |
523 | if (target->sensf_res_len > 0) |
524 | memcpy(atr_req->nfcid3, target->sensf_res, |
525 | target->sensf_res_len); |
526 | else |
527 | get_random_bytes(buf: atr_req->nfcid3, NFC_NFCID3_MAXSIZE); |
528 | |
529 | atr_req->did = 0x0; |
530 | |
531 | atr_req->bsi = 0x00; |
532 | atr_req->bri = 0x00; |
533 | atr_req->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B; |
534 | if (gb_len) { |
535 | atr_req->ppi |= ST21NFCA_GB_BIT; |
536 | skb_put_data(skb, data: gb, len: gb_len); |
537 | } |
538 | atr_req->length = sizeof(struct st21nfca_atr_req) + hdev->gb_len; |
539 | |
540 | *(u8 *)skb_push(skb, len: 1) = info->dep_info.to | 0x10; /* timeout */ |
541 | |
542 | info->async_cb_type = ST21NFCA_CB_TYPE_READER_F; |
543 | info->async_cb_context = info; |
544 | info->async_cb = st21nfca_im_recv_atr_res_cb; |
545 | info->dep_info.bri = atr_req->bri; |
546 | info->dep_info.bsi = atr_req->bsi; |
547 | info->dep_info.lri = ST21NFCA_PP2LRI(atr_req->ppi); |
548 | |
549 | return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE, |
550 | ST21NFCA_WR_XCHG_DATA, param: skb->data, |
551 | param_len: skb->len, cb: info->async_cb, cb_context: info); |
552 | } |
553 | EXPORT_SYMBOL(st21nfca_im_send_atr_req); |
554 | |
555 | static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb, |
556 | int err) |
557 | { |
558 | struct st21nfca_hci_info *info = context; |
559 | struct st21nfca_dep_req_res *dep_res; |
560 | |
561 | int size; |
562 | |
563 | if (err != 0) |
564 | return; |
565 | |
566 | if (!skb) |
567 | return; |
568 | |
569 | switch (info->async_cb_type) { |
570 | case ST21NFCA_CB_TYPE_READER_F: |
571 | dep_res = (struct st21nfca_dep_req_res *)skb->data; |
572 | |
573 | size = 3; |
574 | if (skb->len < size) |
575 | goto exit; |
576 | |
577 | if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_res->pfb)) |
578 | size++; |
579 | if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_res->pfb)) |
580 | size++; |
581 | |
582 | if (skb->len < size) |
583 | goto exit; |
584 | |
585 | skb_trim(skb, len: skb->len - 1); |
586 | |
587 | /* Receiving DEP_REQ - Decoding */ |
588 | switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_res->pfb)) { |
589 | case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU: |
590 | pr_err("Received a ACK/NACK PDU\n" ); |
591 | fallthrough; |
592 | case ST21NFCA_NFC_DEP_PFB_I_PDU: |
593 | info->dep_info.curr_nfc_dep_pni = |
594 | ST21NFCA_NFC_DEP_PFB_PNI(dep_res->pfb + 1); |
595 | size++; |
596 | skb_pull(skb, len: size); |
597 | nfc_tm_data_received(dev: info->hdev->ndev, skb); |
598 | break; |
599 | case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU: |
600 | pr_err("Received a SUPERVISOR PDU\n" ); |
601 | skb_pull(skb, len: size); |
602 | *(u8 *)skb_push(skb, len: 1) = ST21NFCA_NFCIP1_DEP_REQ; |
603 | *(u8 *)skb_push(skb, len: 1) = ST21NFCA_NFCIP1_REQ; |
604 | *(u8 *)skb_push(skb, len: 1) = skb->len; |
605 | *(u8 *)skb_push(skb, len: 1) = info->dep_info.to | 0x10; |
606 | |
607 | st21nfca_im_send_pdu(info, skb); |
608 | break; |
609 | } |
610 | |
611 | return; |
612 | default: |
613 | break; |
614 | } |
615 | |
616 | exit: |
617 | kfree_skb(skb); |
618 | } |
619 | |
620 | int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb) |
621 | { |
622 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
623 | |
624 | info->async_cb_type = ST21NFCA_CB_TYPE_READER_F; |
625 | info->async_cb_context = info; |
626 | info->async_cb = st21nfca_im_recv_dep_res_cb; |
627 | |
628 | *(u8 *)skb_push(skb, len: 1) = info->dep_info.curr_nfc_dep_pni; |
629 | *(u8 *)skb_push(skb, len: 1) = ST21NFCA_NFCIP1_DEP_REQ; |
630 | *(u8 *)skb_push(skb, len: 1) = ST21NFCA_NFCIP1_REQ; |
631 | *(u8 *)skb_push(skb, len: 1) = skb->len; |
632 | |
633 | *(u8 *)skb_push(skb, len: 1) = info->dep_info.to | 0x10; |
634 | |
635 | return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE, |
636 | ST21NFCA_WR_XCHG_DATA, |
637 | param: skb->data, param_len: skb->len, |
638 | cb: info->async_cb, cb_context: info); |
639 | } |
640 | EXPORT_SYMBOL(st21nfca_im_send_dep_req); |
641 | |
642 | void st21nfca_dep_init(struct nfc_hci_dev *hdev) |
643 | { |
644 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
645 | |
646 | INIT_WORK(&info->dep_info.tx_work, st21nfca_tx_work); |
647 | info->dep_info.curr_nfc_dep_pni = 0; |
648 | info->dep_info.idx = 0; |
649 | info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT; |
650 | } |
651 | EXPORT_SYMBOL(st21nfca_dep_init); |
652 | |
653 | void st21nfca_dep_deinit(struct nfc_hci_dev *hdev) |
654 | { |
655 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
656 | |
657 | cancel_work_sync(work: &info->dep_info.tx_work); |
658 | } |
659 | EXPORT_SYMBOL(st21nfca_dep_deinit); |
660 | |