1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * The NFC Controller Interface is the communication protocol between an |
4 | * NFC Controller (NFCC) and a Device Host (DH). |
5 | * |
6 | * Copyright (C) 2014 Marvell International Ltd. |
7 | * Copyright (C) 2011 Texas Instruments, Inc. |
8 | * |
9 | * Written by Ilan Elias <ilane@ti.com> |
10 | * |
11 | * Acknowledgements: |
12 | * This file is based on hci_event.c, which was written |
13 | * by Maxim Krasnyansky. |
14 | */ |
15 | |
16 | #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ |
17 | |
18 | #include <linux/types.h> |
19 | #include <linux/interrupt.h> |
20 | #include <linux/bitops.h> |
21 | #include <linux/skbuff.h> |
22 | |
23 | #include "../nfc.h" |
24 | #include <net/nfc/nci.h> |
25 | #include <net/nfc/nci_core.h> |
26 | #include <linux/nfc.h> |
27 | |
28 | /* Handle NCI Notification packets */ |
29 | |
30 | static void nci_core_reset_ntf_packet(struct nci_dev *ndev, |
31 | const struct sk_buff *skb) |
32 | { |
33 | /* Handle NCI 2.x core reset notification */ |
34 | const struct nci_core_reset_ntf *ntf = (void *)skb->data; |
35 | |
36 | ndev->nci_ver = ntf->nci_ver; |
37 | pr_debug("nci_ver 0x%x, config_status 0x%x\n" , |
38 | ntf->nci_ver, ntf->config_status); |
39 | |
40 | ndev->manufact_id = ntf->manufact_id; |
41 | ndev->manufact_specific_info = |
42 | __le32_to_cpu(ntf->manufact_specific_info); |
43 | |
44 | nci_req_complete(ndev, NCI_STATUS_OK); |
45 | } |
46 | |
47 | static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, |
48 | struct sk_buff *skb) |
49 | { |
50 | struct nci_core_conn_credit_ntf *ntf = (void *) skb->data; |
51 | struct nci_conn_info *conn_info; |
52 | int i; |
53 | |
54 | pr_debug("num_entries %d\n" , ntf->num_entries); |
55 | |
56 | if (ntf->num_entries > NCI_MAX_NUM_CONN) |
57 | ntf->num_entries = NCI_MAX_NUM_CONN; |
58 | |
59 | /* update the credits */ |
60 | for (i = 0; i < ntf->num_entries; i++) { |
61 | ntf->conn_entries[i].conn_id = |
62 | nci_conn_id(&ntf->conn_entries[i].conn_id); |
63 | |
64 | pr_debug("entry[%d]: conn_id %d, credits %d\n" , |
65 | i, ntf->conn_entries[i].conn_id, |
66 | ntf->conn_entries[i].credits); |
67 | |
68 | conn_info = nci_get_conn_info_by_conn_id(ndev, |
69 | conn_id: ntf->conn_entries[i].conn_id); |
70 | if (!conn_info) |
71 | return; |
72 | |
73 | atomic_add(i: ntf->conn_entries[i].credits, |
74 | v: &conn_info->credits_cnt); |
75 | } |
76 | |
77 | /* trigger the next tx */ |
78 | if (!skb_queue_empty(list: &ndev->tx_q)) |
79 | queue_work(wq: ndev->tx_wq, work: &ndev->tx_work); |
80 | } |
81 | |
82 | static void nci_core_generic_error_ntf_packet(struct nci_dev *ndev, |
83 | const struct sk_buff *skb) |
84 | { |
85 | __u8 status = skb->data[0]; |
86 | |
87 | pr_debug("status 0x%x\n" , status); |
88 | |
89 | if (atomic_read(v: &ndev->state) == NCI_W4_HOST_SELECT) { |
90 | /* Activation failed, so complete the request |
91 | (the state remains the same) */ |
92 | nci_req_complete(ndev, result: status); |
93 | } |
94 | } |
95 | |
96 | static void nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev, |
97 | struct sk_buff *skb) |
98 | { |
99 | struct nci_core_intf_error_ntf *ntf = (void *) skb->data; |
100 | |
101 | ntf->conn_id = nci_conn_id(&ntf->conn_id); |
102 | |
103 | pr_debug("status 0x%x, conn_id %d\n" , ntf->status, ntf->conn_id); |
104 | |
105 | /* complete the data exchange transaction, if exists */ |
106 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) |
107 | nci_data_exchange_complete(ndev, NULL, conn_id: ntf->conn_id, err: -EIO); |
108 | } |
109 | |
110 | static const __u8 * |
111 | (struct nci_dev *ndev, |
112 | struct rf_tech_specific_params_nfca_poll *nfca_poll, |
113 | const __u8 *data) |
114 | { |
115 | nfca_poll->sens_res = __le16_to_cpu(*((__le16 *)data)); |
116 | data += 2; |
117 | |
118 | nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE); |
119 | |
120 | pr_debug("sens_res 0x%x, nfcid1_len %d\n" , |
121 | nfca_poll->sens_res, nfca_poll->nfcid1_len); |
122 | |
123 | memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len); |
124 | data += nfca_poll->nfcid1_len; |
125 | |
126 | nfca_poll->sel_res_len = *data++; |
127 | |
128 | if (nfca_poll->sel_res_len != 0) |
129 | nfca_poll->sel_res = *data++; |
130 | |
131 | pr_debug("sel_res_len %d, sel_res 0x%x\n" , |
132 | nfca_poll->sel_res_len, |
133 | nfca_poll->sel_res); |
134 | |
135 | return data; |
136 | } |
137 | |
138 | static const __u8 * |
139 | (struct nci_dev *ndev, |
140 | struct rf_tech_specific_params_nfcb_poll *nfcb_poll, |
141 | const __u8 *data) |
142 | { |
143 | nfcb_poll->sensb_res_len = min_t(__u8, *data++, NFC_SENSB_RES_MAXSIZE); |
144 | |
145 | pr_debug("sensb_res_len %d\n" , nfcb_poll->sensb_res_len); |
146 | |
147 | memcpy(nfcb_poll->sensb_res, data, nfcb_poll->sensb_res_len); |
148 | data += nfcb_poll->sensb_res_len; |
149 | |
150 | return data; |
151 | } |
152 | |
153 | static const __u8 * |
154 | (struct nci_dev *ndev, |
155 | struct rf_tech_specific_params_nfcf_poll *nfcf_poll, |
156 | const __u8 *data) |
157 | { |
158 | nfcf_poll->bit_rate = *data++; |
159 | nfcf_poll->sensf_res_len = min_t(__u8, *data++, NFC_SENSF_RES_MAXSIZE); |
160 | |
161 | pr_debug("bit_rate %d, sensf_res_len %d\n" , |
162 | nfcf_poll->bit_rate, nfcf_poll->sensf_res_len); |
163 | |
164 | memcpy(nfcf_poll->sensf_res, data, nfcf_poll->sensf_res_len); |
165 | data += nfcf_poll->sensf_res_len; |
166 | |
167 | return data; |
168 | } |
169 | |
170 | static const __u8 * |
171 | (struct nci_dev *ndev, |
172 | struct rf_tech_specific_params_nfcv_poll *nfcv_poll, |
173 | const __u8 *data) |
174 | { |
175 | ++data; |
176 | nfcv_poll->dsfid = *data++; |
177 | memcpy(nfcv_poll->uid, data, NFC_ISO15693_UID_MAXSIZE); |
178 | data += NFC_ISO15693_UID_MAXSIZE; |
179 | return data; |
180 | } |
181 | |
182 | static const __u8 * |
183 | (struct nci_dev *ndev, |
184 | struct rf_tech_specific_params_nfcf_listen *nfcf_listen, |
185 | const __u8 *data) |
186 | { |
187 | nfcf_listen->local_nfcid2_len = min_t(__u8, *data++, |
188 | NFC_NFCID2_MAXSIZE); |
189 | memcpy(nfcf_listen->local_nfcid2, data, nfcf_listen->local_nfcid2_len); |
190 | data += nfcf_listen->local_nfcid2_len; |
191 | |
192 | return data; |
193 | } |
194 | |
195 | static __u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol) |
196 | { |
197 | if (ndev->ops->get_rfprotocol) |
198 | return ndev->ops->get_rfprotocol(ndev, rf_protocol); |
199 | return 0; |
200 | } |
201 | |
202 | static int nci_add_new_protocol(struct nci_dev *ndev, |
203 | struct nfc_target *target, |
204 | __u8 rf_protocol, |
205 | __u8 rf_tech_and_mode, |
206 | const void *params) |
207 | { |
208 | const struct rf_tech_specific_params_nfca_poll *nfca_poll; |
209 | const struct rf_tech_specific_params_nfcb_poll *nfcb_poll; |
210 | const struct rf_tech_specific_params_nfcf_poll *nfcf_poll; |
211 | const struct rf_tech_specific_params_nfcv_poll *nfcv_poll; |
212 | __u32 protocol; |
213 | |
214 | if (rf_protocol == NCI_RF_PROTOCOL_T1T) |
215 | protocol = NFC_PROTO_JEWEL_MASK; |
216 | else if (rf_protocol == NCI_RF_PROTOCOL_T2T) |
217 | protocol = NFC_PROTO_MIFARE_MASK; |
218 | else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) |
219 | if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE) |
220 | protocol = NFC_PROTO_ISO14443_MASK; |
221 | else |
222 | protocol = NFC_PROTO_ISO14443_B_MASK; |
223 | else if (rf_protocol == NCI_RF_PROTOCOL_T3T) |
224 | protocol = NFC_PROTO_FELICA_MASK; |
225 | else if (rf_protocol == NCI_RF_PROTOCOL_NFC_DEP) |
226 | protocol = NFC_PROTO_NFC_DEP_MASK; |
227 | else if (rf_protocol == NCI_RF_PROTOCOL_T5T) |
228 | protocol = NFC_PROTO_ISO15693_MASK; |
229 | else |
230 | protocol = nci_get_prop_rf_protocol(ndev, rf_protocol); |
231 | |
232 | if (!(protocol & ndev->poll_prots)) { |
233 | pr_err("the target found does not have the desired protocol\n" ); |
234 | return -EPROTO; |
235 | } |
236 | |
237 | if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE) { |
238 | nfca_poll = (struct rf_tech_specific_params_nfca_poll *)params; |
239 | |
240 | target->sens_res = nfca_poll->sens_res; |
241 | target->sel_res = nfca_poll->sel_res; |
242 | target->nfcid1_len = nfca_poll->nfcid1_len; |
243 | if (target->nfcid1_len > ARRAY_SIZE(target->nfcid1)) |
244 | return -EPROTO; |
245 | if (target->nfcid1_len > 0) { |
246 | memcpy(target->nfcid1, nfca_poll->nfcid1, |
247 | target->nfcid1_len); |
248 | } |
249 | } else if (rf_tech_and_mode == NCI_NFC_B_PASSIVE_POLL_MODE) { |
250 | nfcb_poll = (struct rf_tech_specific_params_nfcb_poll *)params; |
251 | |
252 | target->sensb_res_len = nfcb_poll->sensb_res_len; |
253 | if (target->sensb_res_len > ARRAY_SIZE(target->sensb_res)) |
254 | return -EPROTO; |
255 | if (target->sensb_res_len > 0) { |
256 | memcpy(target->sensb_res, nfcb_poll->sensb_res, |
257 | target->sensb_res_len); |
258 | } |
259 | } else if (rf_tech_and_mode == NCI_NFC_F_PASSIVE_POLL_MODE) { |
260 | nfcf_poll = (struct rf_tech_specific_params_nfcf_poll *)params; |
261 | |
262 | target->sensf_res_len = nfcf_poll->sensf_res_len; |
263 | if (target->sensf_res_len > ARRAY_SIZE(target->sensf_res)) |
264 | return -EPROTO; |
265 | if (target->sensf_res_len > 0) { |
266 | memcpy(target->sensf_res, nfcf_poll->sensf_res, |
267 | target->sensf_res_len); |
268 | } |
269 | } else if (rf_tech_and_mode == NCI_NFC_V_PASSIVE_POLL_MODE) { |
270 | nfcv_poll = (struct rf_tech_specific_params_nfcv_poll *)params; |
271 | |
272 | target->is_iso15693 = 1; |
273 | target->iso15693_dsfid = nfcv_poll->dsfid; |
274 | memcpy(target->iso15693_uid, nfcv_poll->uid, NFC_ISO15693_UID_MAXSIZE); |
275 | } else { |
276 | pr_err("unsupported rf_tech_and_mode 0x%x\n" , rf_tech_and_mode); |
277 | return -EPROTO; |
278 | } |
279 | |
280 | target->supported_protocols |= protocol; |
281 | |
282 | pr_debug("protocol 0x%x\n" , protocol); |
283 | |
284 | return 0; |
285 | } |
286 | |
287 | static void nci_add_new_target(struct nci_dev *ndev, |
288 | const struct nci_rf_discover_ntf *ntf) |
289 | { |
290 | struct nfc_target *target; |
291 | int i, rc; |
292 | |
293 | for (i = 0; i < ndev->n_targets; i++) { |
294 | target = &ndev->targets[i]; |
295 | if (target->logical_idx == ntf->rf_discovery_id) { |
296 | /* This target already exists, add the new protocol */ |
297 | nci_add_new_protocol(ndev, target, rf_protocol: ntf->rf_protocol, |
298 | rf_tech_and_mode: ntf->rf_tech_and_mode, |
299 | params: &ntf->rf_tech_specific_params); |
300 | return; |
301 | } |
302 | } |
303 | |
304 | /* This is a new target, check if we've enough room */ |
305 | if (ndev->n_targets == NCI_MAX_DISCOVERED_TARGETS) { |
306 | pr_debug("not enough room, ignoring new target...\n" ); |
307 | return; |
308 | } |
309 | |
310 | target = &ndev->targets[ndev->n_targets]; |
311 | |
312 | rc = nci_add_new_protocol(ndev, target, rf_protocol: ntf->rf_protocol, |
313 | rf_tech_and_mode: ntf->rf_tech_and_mode, |
314 | params: &ntf->rf_tech_specific_params); |
315 | if (!rc) { |
316 | target->logical_idx = ntf->rf_discovery_id; |
317 | ndev->n_targets++; |
318 | |
319 | pr_debug("logical idx %d, n_targets %d\n" , target->logical_idx, |
320 | ndev->n_targets); |
321 | } |
322 | } |
323 | |
324 | void nci_clear_target_list(struct nci_dev *ndev) |
325 | { |
326 | memset(ndev->targets, 0, |
327 | (sizeof(struct nfc_target)*NCI_MAX_DISCOVERED_TARGETS)); |
328 | |
329 | ndev->n_targets = 0; |
330 | } |
331 | |
332 | static void nci_rf_discover_ntf_packet(struct nci_dev *ndev, |
333 | const struct sk_buff *skb) |
334 | { |
335 | struct nci_rf_discover_ntf ntf; |
336 | const __u8 *data = skb->data; |
337 | bool add_target = true; |
338 | |
339 | ntf.rf_discovery_id = *data++; |
340 | ntf.rf_protocol = *data++; |
341 | ntf.rf_tech_and_mode = *data++; |
342 | ntf.rf_tech_specific_params_len = *data++; |
343 | |
344 | pr_debug("rf_discovery_id %d\n" , ntf.rf_discovery_id); |
345 | pr_debug("rf_protocol 0x%x\n" , ntf.rf_protocol); |
346 | pr_debug("rf_tech_and_mode 0x%x\n" , ntf.rf_tech_and_mode); |
347 | pr_debug("rf_tech_specific_params_len %d\n" , |
348 | ntf.rf_tech_specific_params_len); |
349 | |
350 | if (ntf.rf_tech_specific_params_len > 0) { |
351 | switch (ntf.rf_tech_and_mode) { |
352 | case NCI_NFC_A_PASSIVE_POLL_MODE: |
353 | data = nci_extract_rf_params_nfca_passive_poll(ndev, |
354 | nfca_poll: &(ntf.rf_tech_specific_params.nfca_poll), data); |
355 | break; |
356 | |
357 | case NCI_NFC_B_PASSIVE_POLL_MODE: |
358 | data = nci_extract_rf_params_nfcb_passive_poll(ndev, |
359 | nfcb_poll: &(ntf.rf_tech_specific_params.nfcb_poll), data); |
360 | break; |
361 | |
362 | case NCI_NFC_F_PASSIVE_POLL_MODE: |
363 | data = nci_extract_rf_params_nfcf_passive_poll(ndev, |
364 | nfcf_poll: &(ntf.rf_tech_specific_params.nfcf_poll), data); |
365 | break; |
366 | |
367 | case NCI_NFC_V_PASSIVE_POLL_MODE: |
368 | data = nci_extract_rf_params_nfcv_passive_poll(ndev, |
369 | nfcv_poll: &(ntf.rf_tech_specific_params.nfcv_poll), data); |
370 | break; |
371 | |
372 | default: |
373 | pr_err("unsupported rf_tech_and_mode 0x%x\n" , |
374 | ntf.rf_tech_and_mode); |
375 | data += ntf.rf_tech_specific_params_len; |
376 | add_target = false; |
377 | } |
378 | } |
379 | |
380 | ntf.ntf_type = *data++; |
381 | pr_debug("ntf_type %d\n" , ntf.ntf_type); |
382 | |
383 | if (add_target == true) |
384 | nci_add_new_target(ndev, ntf: &ntf); |
385 | |
386 | if (ntf.ntf_type == NCI_DISCOVER_NTF_TYPE_MORE) { |
387 | atomic_set(v: &ndev->state, i: NCI_W4_ALL_DISCOVERIES); |
388 | } else { |
389 | atomic_set(v: &ndev->state, i: NCI_W4_HOST_SELECT); |
390 | nfc_targets_found(dev: ndev->nfc_dev, targets: ndev->targets, |
391 | ntargets: ndev->n_targets); |
392 | } |
393 | } |
394 | |
395 | static int (struct nci_dev *ndev, |
396 | struct nci_rf_intf_activated_ntf *ntf, |
397 | const __u8 *data) |
398 | { |
399 | struct activation_params_nfca_poll_iso_dep *nfca_poll; |
400 | struct activation_params_nfcb_poll_iso_dep *nfcb_poll; |
401 | |
402 | switch (ntf->activation_rf_tech_and_mode) { |
403 | case NCI_NFC_A_PASSIVE_POLL_MODE: |
404 | nfca_poll = &ntf->activation_params.nfca_poll_iso_dep; |
405 | nfca_poll->rats_res_len = min_t(__u8, *data++, 20); |
406 | pr_debug("rats_res_len %d\n" , nfca_poll->rats_res_len); |
407 | if (nfca_poll->rats_res_len > 0) { |
408 | memcpy(nfca_poll->rats_res, |
409 | data, nfca_poll->rats_res_len); |
410 | } |
411 | break; |
412 | |
413 | case NCI_NFC_B_PASSIVE_POLL_MODE: |
414 | nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep; |
415 | nfcb_poll->attrib_res_len = min_t(__u8, *data++, 50); |
416 | pr_debug("attrib_res_len %d\n" , nfcb_poll->attrib_res_len); |
417 | if (nfcb_poll->attrib_res_len > 0) { |
418 | memcpy(nfcb_poll->attrib_res, |
419 | data, nfcb_poll->attrib_res_len); |
420 | } |
421 | break; |
422 | |
423 | default: |
424 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n" , |
425 | ntf->activation_rf_tech_and_mode); |
426 | return NCI_STATUS_RF_PROTOCOL_ERROR; |
427 | } |
428 | |
429 | return NCI_STATUS_OK; |
430 | } |
431 | |
432 | static int (struct nci_dev *ndev, |
433 | struct nci_rf_intf_activated_ntf *ntf, |
434 | const __u8 *data) |
435 | { |
436 | struct activation_params_poll_nfc_dep *poll; |
437 | struct activation_params_listen_nfc_dep *listen; |
438 | |
439 | switch (ntf->activation_rf_tech_and_mode) { |
440 | case NCI_NFC_A_PASSIVE_POLL_MODE: |
441 | case NCI_NFC_F_PASSIVE_POLL_MODE: |
442 | poll = &ntf->activation_params.poll_nfc_dep; |
443 | poll->atr_res_len = min_t(__u8, *data++, |
444 | NFC_ATR_RES_MAXSIZE - 2); |
445 | pr_debug("atr_res_len %d\n" , poll->atr_res_len); |
446 | if (poll->atr_res_len > 0) |
447 | memcpy(poll->atr_res, data, poll->atr_res_len); |
448 | break; |
449 | |
450 | case NCI_NFC_A_PASSIVE_LISTEN_MODE: |
451 | case NCI_NFC_F_PASSIVE_LISTEN_MODE: |
452 | listen = &ntf->activation_params.listen_nfc_dep; |
453 | listen->atr_req_len = min_t(__u8, *data++, |
454 | NFC_ATR_REQ_MAXSIZE - 2); |
455 | pr_debug("atr_req_len %d\n" , listen->atr_req_len); |
456 | if (listen->atr_req_len > 0) |
457 | memcpy(listen->atr_req, data, listen->atr_req_len); |
458 | break; |
459 | |
460 | default: |
461 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n" , |
462 | ntf->activation_rf_tech_and_mode); |
463 | return NCI_STATUS_RF_PROTOCOL_ERROR; |
464 | } |
465 | |
466 | return NCI_STATUS_OK; |
467 | } |
468 | |
469 | static void nci_target_auto_activated(struct nci_dev *ndev, |
470 | const struct nci_rf_intf_activated_ntf *ntf) |
471 | { |
472 | struct nfc_target *target; |
473 | int rc; |
474 | |
475 | target = &ndev->targets[ndev->n_targets]; |
476 | |
477 | rc = nci_add_new_protocol(ndev, target, rf_protocol: ntf->rf_protocol, |
478 | rf_tech_and_mode: ntf->activation_rf_tech_and_mode, |
479 | params: &ntf->rf_tech_specific_params); |
480 | if (rc) |
481 | return; |
482 | |
483 | target->logical_idx = ntf->rf_discovery_id; |
484 | ndev->n_targets++; |
485 | |
486 | pr_debug("logical idx %d, n_targets %d\n" , |
487 | target->logical_idx, ndev->n_targets); |
488 | |
489 | nfc_targets_found(dev: ndev->nfc_dev, targets: ndev->targets, ntargets: ndev->n_targets); |
490 | } |
491 | |
492 | static int nci_store_general_bytes_nfc_dep(struct nci_dev *ndev, |
493 | const struct nci_rf_intf_activated_ntf *ntf) |
494 | { |
495 | ndev->remote_gb_len = 0; |
496 | |
497 | if (ntf->activation_params_len <= 0) |
498 | return NCI_STATUS_OK; |
499 | |
500 | switch (ntf->activation_rf_tech_and_mode) { |
501 | case NCI_NFC_A_PASSIVE_POLL_MODE: |
502 | case NCI_NFC_F_PASSIVE_POLL_MODE: |
503 | ndev->remote_gb_len = min_t(__u8, |
504 | (ntf->activation_params.poll_nfc_dep.atr_res_len |
505 | - NFC_ATR_RES_GT_OFFSET), |
506 | NFC_ATR_RES_GB_MAXSIZE); |
507 | memcpy(ndev->remote_gb, |
508 | (ntf->activation_params.poll_nfc_dep.atr_res |
509 | + NFC_ATR_RES_GT_OFFSET), |
510 | ndev->remote_gb_len); |
511 | break; |
512 | |
513 | case NCI_NFC_A_PASSIVE_LISTEN_MODE: |
514 | case NCI_NFC_F_PASSIVE_LISTEN_MODE: |
515 | ndev->remote_gb_len = min_t(__u8, |
516 | (ntf->activation_params.listen_nfc_dep.atr_req_len |
517 | - NFC_ATR_REQ_GT_OFFSET), |
518 | NFC_ATR_REQ_GB_MAXSIZE); |
519 | memcpy(ndev->remote_gb, |
520 | (ntf->activation_params.listen_nfc_dep.atr_req |
521 | + NFC_ATR_REQ_GT_OFFSET), |
522 | ndev->remote_gb_len); |
523 | break; |
524 | |
525 | default: |
526 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n" , |
527 | ntf->activation_rf_tech_and_mode); |
528 | return NCI_STATUS_RF_PROTOCOL_ERROR; |
529 | } |
530 | |
531 | return NCI_STATUS_OK; |
532 | } |
533 | |
534 | static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, |
535 | const struct sk_buff *skb) |
536 | { |
537 | struct nci_conn_info *conn_info; |
538 | struct nci_rf_intf_activated_ntf ntf; |
539 | const __u8 *data = skb->data; |
540 | int err = NCI_STATUS_OK; |
541 | |
542 | ntf.rf_discovery_id = *data++; |
543 | ntf.rf_interface = *data++; |
544 | ntf.rf_protocol = *data++; |
545 | ntf.activation_rf_tech_and_mode = *data++; |
546 | ntf.max_data_pkt_payload_size = *data++; |
547 | ntf.initial_num_credits = *data++; |
548 | ntf.rf_tech_specific_params_len = *data++; |
549 | |
550 | pr_debug("rf_discovery_id %d\n" , ntf.rf_discovery_id); |
551 | pr_debug("rf_interface 0x%x\n" , ntf.rf_interface); |
552 | pr_debug("rf_protocol 0x%x\n" , ntf.rf_protocol); |
553 | pr_debug("activation_rf_tech_and_mode 0x%x\n" , |
554 | ntf.activation_rf_tech_and_mode); |
555 | pr_debug("max_data_pkt_payload_size 0x%x\n" , |
556 | ntf.max_data_pkt_payload_size); |
557 | pr_debug("initial_num_credits 0x%x\n" , |
558 | ntf.initial_num_credits); |
559 | pr_debug("rf_tech_specific_params_len %d\n" , |
560 | ntf.rf_tech_specific_params_len); |
561 | |
562 | /* If this contains a value of 0x00 (NFCEE Direct RF |
563 | * Interface) then all following parameters SHALL contain a |
564 | * value of 0 and SHALL be ignored. |
565 | */ |
566 | if (ntf.rf_interface == NCI_RF_INTERFACE_NFCEE_DIRECT) |
567 | goto listen; |
568 | |
569 | if (ntf.rf_tech_specific_params_len > 0) { |
570 | switch (ntf.activation_rf_tech_and_mode) { |
571 | case NCI_NFC_A_PASSIVE_POLL_MODE: |
572 | data = nci_extract_rf_params_nfca_passive_poll(ndev, |
573 | nfca_poll: &(ntf.rf_tech_specific_params.nfca_poll), data); |
574 | break; |
575 | |
576 | case NCI_NFC_B_PASSIVE_POLL_MODE: |
577 | data = nci_extract_rf_params_nfcb_passive_poll(ndev, |
578 | nfcb_poll: &(ntf.rf_tech_specific_params.nfcb_poll), data); |
579 | break; |
580 | |
581 | case NCI_NFC_F_PASSIVE_POLL_MODE: |
582 | data = nci_extract_rf_params_nfcf_passive_poll(ndev, |
583 | nfcf_poll: &(ntf.rf_tech_specific_params.nfcf_poll), data); |
584 | break; |
585 | |
586 | case NCI_NFC_V_PASSIVE_POLL_MODE: |
587 | data = nci_extract_rf_params_nfcv_passive_poll(ndev, |
588 | nfcv_poll: &(ntf.rf_tech_specific_params.nfcv_poll), data); |
589 | break; |
590 | |
591 | case NCI_NFC_A_PASSIVE_LISTEN_MODE: |
592 | /* no RF technology specific parameters */ |
593 | break; |
594 | |
595 | case NCI_NFC_F_PASSIVE_LISTEN_MODE: |
596 | data = nci_extract_rf_params_nfcf_passive_listen(ndev, |
597 | nfcf_listen: &(ntf.rf_tech_specific_params.nfcf_listen), |
598 | data); |
599 | break; |
600 | |
601 | default: |
602 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n" , |
603 | ntf.activation_rf_tech_and_mode); |
604 | err = NCI_STATUS_RF_PROTOCOL_ERROR; |
605 | goto exit; |
606 | } |
607 | } |
608 | |
609 | ntf.data_exch_rf_tech_and_mode = *data++; |
610 | ntf.data_exch_tx_bit_rate = *data++; |
611 | ntf.data_exch_rx_bit_rate = *data++; |
612 | ntf.activation_params_len = *data++; |
613 | |
614 | pr_debug("data_exch_rf_tech_and_mode 0x%x\n" , |
615 | ntf.data_exch_rf_tech_and_mode); |
616 | pr_debug("data_exch_tx_bit_rate 0x%x\n" , ntf.data_exch_tx_bit_rate); |
617 | pr_debug("data_exch_rx_bit_rate 0x%x\n" , ntf.data_exch_rx_bit_rate); |
618 | pr_debug("activation_params_len %d\n" , ntf.activation_params_len); |
619 | |
620 | if (ntf.activation_params_len > 0) { |
621 | switch (ntf.rf_interface) { |
622 | case NCI_RF_INTERFACE_ISO_DEP: |
623 | err = nci_extract_activation_params_iso_dep(ndev, |
624 | ntf: &ntf, data); |
625 | break; |
626 | |
627 | case NCI_RF_INTERFACE_NFC_DEP: |
628 | err = nci_extract_activation_params_nfc_dep(ndev, |
629 | ntf: &ntf, data); |
630 | break; |
631 | |
632 | case NCI_RF_INTERFACE_FRAME: |
633 | /* no activation params */ |
634 | break; |
635 | |
636 | default: |
637 | pr_err("unsupported rf_interface 0x%x\n" , |
638 | ntf.rf_interface); |
639 | err = NCI_STATUS_RF_PROTOCOL_ERROR; |
640 | break; |
641 | } |
642 | } |
643 | |
644 | exit: |
645 | if (err == NCI_STATUS_OK) { |
646 | conn_info = ndev->rf_conn_info; |
647 | if (!conn_info) |
648 | return; |
649 | |
650 | conn_info->max_pkt_payload_len = ntf.max_data_pkt_payload_size; |
651 | conn_info->initial_num_credits = ntf.initial_num_credits; |
652 | |
653 | /* set the available credits to initial value */ |
654 | atomic_set(v: &conn_info->credits_cnt, |
655 | i: conn_info->initial_num_credits); |
656 | |
657 | /* store general bytes to be reported later in dep_link_up */ |
658 | if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) { |
659 | err = nci_store_general_bytes_nfc_dep(ndev, ntf: &ntf); |
660 | if (err != NCI_STATUS_OK) |
661 | pr_err("unable to store general bytes\n" ); |
662 | } |
663 | } |
664 | |
665 | if (!(ntf.activation_rf_tech_and_mode & NCI_RF_TECH_MODE_LISTEN_MASK)) { |
666 | /* Poll mode */ |
667 | if (atomic_read(v: &ndev->state) == NCI_DISCOVERY) { |
668 | /* A single target was found and activated |
669 | * automatically */ |
670 | atomic_set(v: &ndev->state, i: NCI_POLL_ACTIVE); |
671 | if (err == NCI_STATUS_OK) |
672 | nci_target_auto_activated(ndev, ntf: &ntf); |
673 | } else { /* ndev->state == NCI_W4_HOST_SELECT */ |
674 | /* A selected target was activated, so complete the |
675 | * request */ |
676 | atomic_set(v: &ndev->state, i: NCI_POLL_ACTIVE); |
677 | nci_req_complete(ndev, result: err); |
678 | } |
679 | } else { |
680 | listen: |
681 | /* Listen mode */ |
682 | atomic_set(v: &ndev->state, i: NCI_LISTEN_ACTIVE); |
683 | if (err == NCI_STATUS_OK && |
684 | ntf.rf_protocol == NCI_RF_PROTOCOL_NFC_DEP) { |
685 | err = nfc_tm_activated(dev: ndev->nfc_dev, |
686 | NFC_PROTO_NFC_DEP_MASK, |
687 | NFC_COMM_PASSIVE, |
688 | gb: ndev->remote_gb, |
689 | gb_len: ndev->remote_gb_len); |
690 | if (err != NCI_STATUS_OK) |
691 | pr_err("error when signaling tm activation\n" ); |
692 | } |
693 | } |
694 | } |
695 | |
696 | static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, |
697 | const struct sk_buff *skb) |
698 | { |
699 | const struct nci_conn_info *conn_info; |
700 | const struct nci_rf_deactivate_ntf *ntf = (void *)skb->data; |
701 | |
702 | pr_debug("entry, type 0x%x, reason 0x%x\n" , ntf->type, ntf->reason); |
703 | |
704 | conn_info = ndev->rf_conn_info; |
705 | if (!conn_info) |
706 | return; |
707 | |
708 | /* drop tx data queue */ |
709 | skb_queue_purge(list: &ndev->tx_q); |
710 | |
711 | /* drop partial rx data packet */ |
712 | if (ndev->rx_data_reassembly) { |
713 | kfree_skb(skb: ndev->rx_data_reassembly); |
714 | ndev->rx_data_reassembly = NULL; |
715 | } |
716 | |
717 | /* complete the data exchange transaction, if exists */ |
718 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) |
719 | nci_data_exchange_complete(ndev, NULL, NCI_STATIC_RF_CONN_ID, |
720 | err: -EIO); |
721 | |
722 | switch (ntf->type) { |
723 | case NCI_DEACTIVATE_TYPE_IDLE_MODE: |
724 | nci_clear_target_list(ndev); |
725 | atomic_set(v: &ndev->state, i: NCI_IDLE); |
726 | break; |
727 | case NCI_DEACTIVATE_TYPE_SLEEP_MODE: |
728 | case NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE: |
729 | atomic_set(v: &ndev->state, i: NCI_W4_HOST_SELECT); |
730 | break; |
731 | case NCI_DEACTIVATE_TYPE_DISCOVERY: |
732 | nci_clear_target_list(ndev); |
733 | atomic_set(v: &ndev->state, i: NCI_DISCOVERY); |
734 | break; |
735 | } |
736 | |
737 | nci_req_complete(ndev, NCI_STATUS_OK); |
738 | } |
739 | |
740 | static void nci_nfcee_discover_ntf_packet(struct nci_dev *ndev, |
741 | const struct sk_buff *skb) |
742 | { |
743 | u8 status = NCI_STATUS_OK; |
744 | const struct nci_nfcee_discover_ntf *nfcee_ntf = |
745 | (struct nci_nfcee_discover_ntf *)skb->data; |
746 | |
747 | /* NFCForum NCI 9.2.1 HCI Network Specific Handling |
748 | * If the NFCC supports the HCI Network, it SHALL return one, |
749 | * and only one, NFCEE_DISCOVER_NTF with a Protocol type of |
750 | * “HCI Access”, even if the HCI Network contains multiple NFCEEs. |
751 | */ |
752 | ndev->hci_dev->nfcee_id = nfcee_ntf->nfcee_id; |
753 | ndev->cur_params.id = nfcee_ntf->nfcee_id; |
754 | |
755 | nci_req_complete(ndev, result: status); |
756 | } |
757 | |
758 | void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) |
759 | { |
760 | __u16 ntf_opcode = nci_opcode(skb->data); |
761 | |
762 | pr_debug("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n" , |
763 | nci_pbf(skb->data), |
764 | nci_opcode_gid(ntf_opcode), |
765 | nci_opcode_oid(ntf_opcode), |
766 | nci_plen(skb->data)); |
767 | |
768 | /* strip the nci control header */ |
769 | skb_pull(skb, NCI_CTRL_HDR_SIZE); |
770 | |
771 | if (nci_opcode_gid(ntf_opcode) == NCI_GID_PROPRIETARY) { |
772 | if (nci_prop_ntf_packet(ndev, opcode: ntf_opcode, skb) == -ENOTSUPP) { |
773 | pr_err("unsupported ntf opcode 0x%x\n" , |
774 | ntf_opcode); |
775 | } |
776 | |
777 | goto end; |
778 | } |
779 | |
780 | switch (ntf_opcode) { |
781 | case NCI_OP_CORE_RESET_NTF: |
782 | nci_core_reset_ntf_packet(ndev, skb); |
783 | break; |
784 | |
785 | case NCI_OP_CORE_CONN_CREDITS_NTF: |
786 | nci_core_conn_credits_ntf_packet(ndev, skb); |
787 | break; |
788 | |
789 | case NCI_OP_CORE_GENERIC_ERROR_NTF: |
790 | nci_core_generic_error_ntf_packet(ndev, skb); |
791 | break; |
792 | |
793 | case NCI_OP_CORE_INTF_ERROR_NTF: |
794 | nci_core_conn_intf_error_ntf_packet(ndev, skb); |
795 | break; |
796 | |
797 | case NCI_OP_RF_DISCOVER_NTF: |
798 | nci_rf_discover_ntf_packet(ndev, skb); |
799 | break; |
800 | |
801 | case NCI_OP_RF_INTF_ACTIVATED_NTF: |
802 | nci_rf_intf_activated_ntf_packet(ndev, skb); |
803 | break; |
804 | |
805 | case NCI_OP_RF_DEACTIVATE_NTF: |
806 | nci_rf_deactivate_ntf_packet(ndev, skb); |
807 | break; |
808 | |
809 | case NCI_OP_NFCEE_DISCOVER_NTF: |
810 | nci_nfcee_discover_ntf_packet(ndev, skb); |
811 | break; |
812 | |
813 | case NCI_OP_RF_NFCEE_ACTION_NTF: |
814 | break; |
815 | |
816 | default: |
817 | pr_err("unknown ntf opcode 0x%x\n" , ntf_opcode); |
818 | break; |
819 | } |
820 | |
821 | nci_core_ntf_packet(ndev, opcode: ntf_opcode, skb); |
822 | end: |
823 | kfree_skb(skb); |
824 | } |
825 | |