Merge git://www.linux-watchdog.org/linux-watchdog
[linux-2.6-block.git] / net / nfc / nci / ntf.c
CommitLineData
6a2968aa
IE
1/*
2 * The NFC Controller Interface is the communication protocol between an
3 * NFC Controller (NFCC) and a Device Host (DH).
4 *
5 * Copyright (C) 2011 Texas Instruments, Inc.
6 *
7 * Written by Ilan Elias <ilane@ti.com>
8 *
9 * Acknowledgements:
10 * This file is based on hci_event.c, which was written
11 * by Maxim Krasnyansky.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2
15 * as published by the Free Software Foundation
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
98b32dec 23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
6a2968aa
IE
24 *
25 */
26
52858b51 27#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
ed1e0ad8 28
6a2968aa
IE
29#include <linux/types.h>
30#include <linux/interrupt.h>
31#include <linux/bitops.h>
32#include <linux/skbuff.h>
33
34#include "../nfc.h"
35#include <net/nfc/nci.h>
36#include <net/nfc/nci_core.h>
37#include <linux/nfc.h>
38
39/* Handle NCI Notification packets */
40
41static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
eb9bc6e9 42 struct sk_buff *skb)
6a2968aa
IE
43{
44 struct nci_core_conn_credit_ntf *ntf = (void *) skb->data;
45 int i;
46
24bf3304 47 pr_debug("num_entries %d\n", ntf->num_entries);
6a2968aa
IE
48
49 if (ntf->num_entries > NCI_MAX_NUM_CONN)
50 ntf->num_entries = NCI_MAX_NUM_CONN;
51
52 /* update the credits */
53 for (i = 0; i < ntf->num_entries; i++) {
637d85a7
IE
54 ntf->conn_entries[i].conn_id =
55 nci_conn_id(&ntf->conn_entries[i].conn_id);
56
20c239c1
JP
57 pr_debug("entry[%d]: conn_id %d, credits %d\n",
58 i, ntf->conn_entries[i].conn_id,
59 ntf->conn_entries[i].credits);
6a2968aa 60
e8c0dacd 61 if (ntf->conn_entries[i].conn_id == NCI_STATIC_RF_CONN_ID) {
6a2968aa
IE
62 /* found static rf connection */
63 atomic_add(ntf->conn_entries[i].credits,
eb9bc6e9 64 &ndev->credits_cnt);
6a2968aa
IE
65 }
66 }
67
68 /* trigger the next tx */
69 if (!skb_queue_empty(&ndev->tx_q))
70 queue_work(ndev->tx_wq, &ndev->tx_work);
71}
72
019c4fba 73static void nci_core_generic_error_ntf_packet(struct nci_dev *ndev,
eb9bc6e9 74 struct sk_buff *skb)
019c4fba
IE
75{
76 __u8 status = skb->data[0];
77
78 pr_debug("status 0x%x\n", status);
79
80 if (atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) {
81 /* Activation failed, so complete the request
eb9bc6e9 82 (the state remains the same) */
019c4fba
IE
83 nci_req_complete(ndev, status);
84 }
85}
86
004161cb
IE
87static void nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev,
88 struct sk_buff *skb)
89{
90 struct nci_core_intf_error_ntf *ntf = (void *) skb->data;
91
92 ntf->conn_id = nci_conn_id(&ntf->conn_id);
93
94 pr_debug("status 0x%x, conn_id %d\n", ntf->status, ntf->conn_id);
95
96 /* complete the data exchange transaction, if exists */
97 if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
98 nci_data_exchange_complete(ndev, NULL, -EIO);
99}
100
e8c0dacd 101static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev,
019c4fba 102 struct rf_tech_specific_params_nfca_poll *nfca_poll,
eb9bc6e9 103 __u8 *data)
6a2968aa 104{
6a2968aa
IE
105 nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data));
106 data += 2;
107
67de956f 108 nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE);
6a2968aa 109
20c239c1
JP
110 pr_debug("sens_res 0x%x, nfcid1_len %d\n",
111 nfca_poll->sens_res, nfca_poll->nfcid1_len);
6a2968aa
IE
112
113 memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len);
114 data += nfca_poll->nfcid1_len;
115
116 nfca_poll->sel_res_len = *data++;
117
118 if (nfca_poll->sel_res_len != 0)
119 nfca_poll->sel_res = *data++;
120
20c239c1
JP
121 pr_debug("sel_res_len %d, sel_res 0x%x\n",
122 nfca_poll->sel_res_len,
123 nfca_poll->sel_res);
e8c0dacd
IE
124
125 return data;
126}
127
d5a2ca60 128static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev,
019c4fba 129 struct rf_tech_specific_params_nfcb_poll *nfcb_poll,
eb9bc6e9 130 __u8 *data)
d5a2ca60 131{
67de956f 132 nfcb_poll->sensb_res_len = min_t(__u8, *data++, NFC_SENSB_RES_MAXSIZE);
d5a2ca60
IE
133
134 pr_debug("sensb_res_len %d\n", nfcb_poll->sensb_res_len);
135
136 memcpy(nfcb_poll->sensb_res, data, nfcb_poll->sensb_res_len);
137 data += nfcb_poll->sensb_res_len;
138
139 return data;
140}
141
142static __u8 *nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev,
019c4fba 143 struct rf_tech_specific_params_nfcf_poll *nfcf_poll,
eb9bc6e9 144 __u8 *data)
d5a2ca60 145{
d5a2ca60 146 nfcf_poll->bit_rate = *data++;
67de956f 147 nfcf_poll->sensf_res_len = min_t(__u8, *data++, NFC_SENSF_RES_MAXSIZE);
d5a2ca60
IE
148
149 pr_debug("bit_rate %d, sensf_res_len %d\n",
eb9bc6e9 150 nfcf_poll->bit_rate, nfcf_poll->sensf_res_len);
d5a2ca60
IE
151
152 memcpy(nfcf_poll->sensf_res, data, nfcf_poll->sensf_res_len);
153 data += nfcf_poll->sensf_res_len;
154
155 return data;
156}
157
019c4fba
IE
158static int nci_add_new_protocol(struct nci_dev *ndev,
159 struct nfc_target *target,
160 __u8 rf_protocol,
161 __u8 rf_tech_and_mode,
162 void *params)
163{
164 struct rf_tech_specific_params_nfca_poll *nfca_poll;
165 struct rf_tech_specific_params_nfcb_poll *nfcb_poll;
166 struct rf_tech_specific_params_nfcf_poll *nfcf_poll;
167 __u32 protocol;
168
bb15b217
CR
169 if (rf_protocol == NCI_RF_PROTOCOL_T1T)
170 protocol = NFC_PROTO_JEWEL_MASK;
171 else if (rf_protocol == NCI_RF_PROTOCOL_T2T)
019c4fba
IE
172 protocol = NFC_PROTO_MIFARE_MASK;
173 else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP)
01d719a2
SO
174 if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE)
175 protocol = NFC_PROTO_ISO14443_MASK;
176 else
177 protocol = NFC_PROTO_ISO14443_B_MASK;
019c4fba
IE
178 else if (rf_protocol == NCI_RF_PROTOCOL_T3T)
179 protocol = NFC_PROTO_FELICA_MASK;
767f19ae
IE
180 else if (rf_protocol == NCI_RF_PROTOCOL_NFC_DEP)
181 protocol = NFC_PROTO_NFC_DEP_MASK;
019c4fba
IE
182 else
183 protocol = 0;
184
185 if (!(protocol & ndev->poll_prots)) {
186 pr_err("the target found does not have the desired protocol\n");
187 return -EPROTO;
188 }
189
190 if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE) {
191 nfca_poll = (struct rf_tech_specific_params_nfca_poll *)params;
192
193 target->sens_res = nfca_poll->sens_res;
194 target->sel_res = nfca_poll->sel_res;
195 target->nfcid1_len = nfca_poll->nfcid1_len;
196 if (target->nfcid1_len > 0) {
197 memcpy(target->nfcid1, nfca_poll->nfcid1,
eb9bc6e9 198 target->nfcid1_len);
019c4fba
IE
199 }
200 } else if (rf_tech_and_mode == NCI_NFC_B_PASSIVE_POLL_MODE) {
201 nfcb_poll = (struct rf_tech_specific_params_nfcb_poll *)params;
202
203 target->sensb_res_len = nfcb_poll->sensb_res_len;
204 if (target->sensb_res_len > 0) {
205 memcpy(target->sensb_res, nfcb_poll->sensb_res,
eb9bc6e9 206 target->sensb_res_len);
019c4fba
IE
207 }
208 } else if (rf_tech_and_mode == NCI_NFC_F_PASSIVE_POLL_MODE) {
209 nfcf_poll = (struct rf_tech_specific_params_nfcf_poll *)params;
210
211 target->sensf_res_len = nfcf_poll->sensf_res_len;
212 if (target->sensf_res_len > 0) {
213 memcpy(target->sensf_res, nfcf_poll->sensf_res,
eb9bc6e9 214 target->sensf_res_len);
019c4fba
IE
215 }
216 } else {
217 pr_err("unsupported rf_tech_and_mode 0x%x\n", rf_tech_and_mode);
218 return -EPROTO;
219 }
220
221 target->supported_protocols |= protocol;
222
223 pr_debug("protocol 0x%x\n", protocol);
224
225 return 0;
226}
227
228static void nci_add_new_target(struct nci_dev *ndev,
eb9bc6e9 229 struct nci_rf_discover_ntf *ntf)
019c4fba
IE
230{
231 struct nfc_target *target;
232 int i, rc;
233
234 for (i = 0; i < ndev->n_targets; i++) {
235 target = &ndev->targets[i];
c4fbb651 236 if (target->logical_idx == ntf->rf_discovery_id) {
019c4fba
IE
237 /* This target already exists, add the new protocol */
238 nci_add_new_protocol(ndev, target, ntf->rf_protocol,
eb9bc6e9
SO
239 ntf->rf_tech_and_mode,
240 &ntf->rf_tech_specific_params);
019c4fba
IE
241 return;
242 }
243 }
244
245 /* This is a new target, check if we've enough room */
246 if (ndev->n_targets == NCI_MAX_DISCOVERED_TARGETS) {
247 pr_debug("not enough room, ignoring new target...\n");
248 return;
249 }
250
251 target = &ndev->targets[ndev->n_targets];
252
253 rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol,
eb9bc6e9
SO
254 ntf->rf_tech_and_mode,
255 &ntf->rf_tech_specific_params);
019c4fba 256 if (!rc) {
c4fbb651 257 target->logical_idx = ntf->rf_discovery_id;
019c4fba
IE
258 ndev->n_targets++;
259
c4fbb651 260 pr_debug("logical idx %d, n_targets %d\n", target->logical_idx,
eb9bc6e9 261 ndev->n_targets);
019c4fba
IE
262 }
263}
264
265void nci_clear_target_list(struct nci_dev *ndev)
266{
267 memset(ndev->targets, 0,
eb9bc6e9 268 (sizeof(struct nfc_target)*NCI_MAX_DISCOVERED_TARGETS));
019c4fba
IE
269
270 ndev->n_targets = 0;
271}
272
273static void nci_rf_discover_ntf_packet(struct nci_dev *ndev,
eb9bc6e9 274 struct sk_buff *skb)
019c4fba
IE
275{
276 struct nci_rf_discover_ntf ntf;
277 __u8 *data = skb->data;
278 bool add_target = true;
279
280 ntf.rf_discovery_id = *data++;
281 ntf.rf_protocol = *data++;
282 ntf.rf_tech_and_mode = *data++;
283 ntf.rf_tech_specific_params_len = *data++;
284
285 pr_debug("rf_discovery_id %d\n", ntf.rf_discovery_id);
286 pr_debug("rf_protocol 0x%x\n", ntf.rf_protocol);
287 pr_debug("rf_tech_and_mode 0x%x\n", ntf.rf_tech_and_mode);
288 pr_debug("rf_tech_specific_params_len %d\n",
eb9bc6e9 289 ntf.rf_tech_specific_params_len);
019c4fba
IE
290
291 if (ntf.rf_tech_specific_params_len > 0) {
292 switch (ntf.rf_tech_and_mode) {
293 case NCI_NFC_A_PASSIVE_POLL_MODE:
294 data = nci_extract_rf_params_nfca_passive_poll(ndev,
295 &(ntf.rf_tech_specific_params.nfca_poll), data);
296 break;
297
298 case NCI_NFC_B_PASSIVE_POLL_MODE:
299 data = nci_extract_rf_params_nfcb_passive_poll(ndev,
300 &(ntf.rf_tech_specific_params.nfcb_poll), data);
301 break;
302
303 case NCI_NFC_F_PASSIVE_POLL_MODE:
304 data = nci_extract_rf_params_nfcf_passive_poll(ndev,
305 &(ntf.rf_tech_specific_params.nfcf_poll), data);
306 break;
307
308 default:
309 pr_err("unsupported rf_tech_and_mode 0x%x\n",
310 ntf.rf_tech_and_mode);
311 data += ntf.rf_tech_specific_params_len;
312 add_target = false;
313 }
314 }
315
316 ntf.ntf_type = *data++;
317 pr_debug("ntf_type %d\n", ntf.ntf_type);
318
319 if (add_target == true)
320 nci_add_new_target(ndev, &ntf);
321
322 if (ntf.ntf_type == NCI_DISCOVER_NTF_TYPE_MORE) {
323 atomic_set(&ndev->state, NCI_W4_ALL_DISCOVERIES);
324 } else {
325 atomic_set(&ndev->state, NCI_W4_HOST_SELECT);
326 nfc_targets_found(ndev->nfc_dev, ndev->targets,
eb9bc6e9 327 ndev->n_targets);
019c4fba
IE
328 }
329}
330
e8c0dacd
IE
331static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev,
332 struct nci_rf_intf_activated_ntf *ntf, __u8 *data)
333{
334 struct activation_params_nfca_poll_iso_dep *nfca_poll;
d5a2ca60 335 struct activation_params_nfcb_poll_iso_dep *nfcb_poll;
e8c0dacd
IE
336
337 switch (ntf->activation_rf_tech_and_mode) {
338 case NCI_NFC_A_PASSIVE_POLL_MODE:
339 nfca_poll = &ntf->activation_params.nfca_poll_iso_dep;
67de956f 340 nfca_poll->rats_res_len = min_t(__u8, *data++, 20);
d5a2ca60 341 pr_debug("rats_res_len %d\n", nfca_poll->rats_res_len);
e8c0dacd
IE
342 if (nfca_poll->rats_res_len > 0) {
343 memcpy(nfca_poll->rats_res,
eb9bc6e9 344 data, nfca_poll->rats_res_len);
6a2968aa
IE
345 }
346 break;
347
d5a2ca60
IE
348 case NCI_NFC_B_PASSIVE_POLL_MODE:
349 nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep;
67de956f 350 nfcb_poll->attrib_res_len = min_t(__u8, *data++, 50);
eb9bc6e9 351 pr_debug("attrib_res_len %d\n", nfcb_poll->attrib_res_len);
d5a2ca60
IE
352 if (nfcb_poll->attrib_res_len > 0) {
353 memcpy(nfcb_poll->attrib_res,
eb9bc6e9 354 data, nfcb_poll->attrib_res_len);
d5a2ca60
IE
355 }
356 break;
357
6a2968aa 358 default:
ed1e0ad8
JP
359 pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
360 ntf->activation_rf_tech_and_mode);
019c4fba 361 return NCI_STATUS_RF_PROTOCOL_ERROR;
6a2968aa
IE
362 }
363
019c4fba 364 return NCI_STATUS_OK;
6a2968aa
IE
365}
366
ac206838
IE
367static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev,
368 struct nci_rf_intf_activated_ntf *ntf, __u8 *data)
369{
370 struct activation_params_poll_nfc_dep *poll;
ac206838
IE
371
372 switch (ntf->activation_rf_tech_and_mode) {
373 case NCI_NFC_A_PASSIVE_POLL_MODE:
374 case NCI_NFC_F_PASSIVE_POLL_MODE:
375 poll = &ntf->activation_params.poll_nfc_dep;
376 poll->atr_res_len = min_t(__u8, *data++, 63);
377 pr_debug("atr_res_len %d\n", poll->atr_res_len);
c79d9f9e
HT
378 if (poll->atr_res_len > 0)
379 memcpy(poll->atr_res, data, poll->atr_res_len);
ac206838
IE
380 break;
381
382 default:
383 pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
384 ntf->activation_rf_tech_and_mode);
385 return NCI_STATUS_RF_PROTOCOL_ERROR;
386 }
387
388 return NCI_STATUS_OK;
389}
390
019c4fba 391static void nci_target_auto_activated(struct nci_dev *ndev,
eb9bc6e9 392 struct nci_rf_intf_activated_ntf *ntf)
6a2968aa 393{
019c4fba
IE
394 struct nfc_target *target;
395 int rc;
6a2968aa 396
019c4fba 397 target = &ndev->targets[ndev->n_targets];
d5a2ca60 398
019c4fba 399 rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol,
eb9bc6e9
SO
400 ntf->activation_rf_tech_and_mode,
401 &ntf->rf_tech_specific_params);
019c4fba 402 if (rc)
6a2968aa 403 return;
6a2968aa 404
c4fbb651 405 target->logical_idx = ntf->rf_discovery_id;
019c4fba 406 ndev->n_targets++;
d5a2ca60 407
c4fbb651
SO
408 pr_debug("logical idx %d, n_targets %d\n",
409 target->logical_idx, ndev->n_targets);
637d85a7 410
019c4fba 411 nfc_targets_found(ndev->nfc_dev, ndev->targets, ndev->n_targets);
6a2968aa
IE
412}
413
e8c0dacd 414static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
eb9bc6e9 415 struct sk_buff *skb)
6a2968aa 416{
e8c0dacd 417 struct nci_rf_intf_activated_ntf ntf;
6a2968aa 418 __u8 *data = skb->data;
019c4fba 419 int err = NCI_STATUS_OK;
6a2968aa 420
e8c0dacd 421 ntf.rf_discovery_id = *data++;
637d85a7 422 ntf.rf_interface = *data++;
6a2968aa 423 ntf.rf_protocol = *data++;
e8c0dacd 424 ntf.activation_rf_tech_and_mode = *data++;
637d85a7
IE
425 ntf.max_data_pkt_payload_size = *data++;
426 ntf.initial_num_credits = *data++;
6a2968aa
IE
427 ntf.rf_tech_specific_params_len = *data++;
428
20c239c1 429 pr_debug("rf_discovery_id %d\n", ntf.rf_discovery_id);
637d85a7 430 pr_debug("rf_interface 0x%x\n", ntf.rf_interface);
20c239c1
JP
431 pr_debug("rf_protocol 0x%x\n", ntf.rf_protocol);
432 pr_debug("activation_rf_tech_and_mode 0x%x\n",
433 ntf.activation_rf_tech_and_mode);
637d85a7
IE
434 pr_debug("max_data_pkt_payload_size 0x%x\n",
435 ntf.max_data_pkt_payload_size);
eb9bc6e9
SO
436 pr_debug("initial_num_credits 0x%x\n",
437 ntf.initial_num_credits);
20c239c1
JP
438 pr_debug("rf_tech_specific_params_len %d\n",
439 ntf.rf_tech_specific_params_len);
6a2968aa 440
e8c0dacd
IE
441 if (ntf.rf_tech_specific_params_len > 0) {
442 switch (ntf.activation_rf_tech_and_mode) {
443 case NCI_NFC_A_PASSIVE_POLL_MODE:
444 data = nci_extract_rf_params_nfca_passive_poll(ndev,
019c4fba 445 &(ntf.rf_tech_specific_params.nfca_poll), data);
e8c0dacd
IE
446 break;
447
d5a2ca60
IE
448 case NCI_NFC_B_PASSIVE_POLL_MODE:
449 data = nci_extract_rf_params_nfcb_passive_poll(ndev,
019c4fba 450 &(ntf.rf_tech_specific_params.nfcb_poll), data);
d5a2ca60
IE
451 break;
452
453 case NCI_NFC_F_PASSIVE_POLL_MODE:
454 data = nci_extract_rf_params_nfcf_passive_poll(ndev,
019c4fba 455 &(ntf.rf_tech_specific_params.nfcf_poll), data);
d5a2ca60
IE
456 break;
457
e8c0dacd 458 default:
ed1e0ad8
JP
459 pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
460 ntf.activation_rf_tech_and_mode);
019c4fba
IE
461 err = NCI_STATUS_RF_PROTOCOL_ERROR;
462 goto exit;
e8c0dacd
IE
463 }
464 }
6a2968aa 465
e8c0dacd
IE
466 ntf.data_exch_rf_tech_and_mode = *data++;
467 ntf.data_exch_tx_bit_rate = *data++;
468 ntf.data_exch_rx_bit_rate = *data++;
469 ntf.activation_params_len = *data++;
470
20c239c1
JP
471 pr_debug("data_exch_rf_tech_and_mode 0x%x\n",
472 ntf.data_exch_rf_tech_and_mode);
eb9bc6e9
SO
473 pr_debug("data_exch_tx_bit_rate 0x%x\n", ntf.data_exch_tx_bit_rate);
474 pr_debug("data_exch_rx_bit_rate 0x%x\n", ntf.data_exch_rx_bit_rate);
475 pr_debug("activation_params_len %d\n", ntf.activation_params_len);
e8c0dacd
IE
476
477 if (ntf.activation_params_len > 0) {
637d85a7 478 switch (ntf.rf_interface) {
e8c0dacd
IE
479 case NCI_RF_INTERFACE_ISO_DEP:
480 err = nci_extract_activation_params_iso_dep(ndev,
eb9bc6e9 481 &ntf, data);
e8c0dacd
IE
482 break;
483
ac206838
IE
484 case NCI_RF_INTERFACE_NFC_DEP:
485 err = nci_extract_activation_params_nfc_dep(ndev,
486 &ntf, data);
487 break;
488
e8c0dacd
IE
489 case NCI_RF_INTERFACE_FRAME:
490 /* no activation params */
491 break;
492
493 default:
637d85a7
IE
494 pr_err("unsupported rf_interface 0x%x\n",
495 ntf.rf_interface);
019c4fba
IE
496 err = NCI_STATUS_RF_PROTOCOL_ERROR;
497 break;
e8c0dacd 498 }
6a2968aa
IE
499 }
500
019c4fba
IE
501exit:
502 if (err == NCI_STATUS_OK) {
503 ndev->max_data_pkt_payload_size = ntf.max_data_pkt_payload_size;
504 ndev->initial_num_credits = ntf.initial_num_credits;
505
506 /* set the available credits to initial value */
507 atomic_set(&ndev->credits_cnt, ndev->initial_num_credits);
767f19ae
IE
508
509 /* store general bytes to be reported later in dep_link_up */
510 if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) {
511 ndev->remote_gb_len = 0;
512
513 if (ntf.activation_params_len > 0) {
514 /* ATR_RES general bytes at offset 15 */
515 ndev->remote_gb_len = min_t(__u8,
516 (ntf.activation_params
517 .poll_nfc_dep.atr_res_len
518 - NFC_ATR_RES_GT_OFFSET),
519 NFC_MAX_GT_LEN);
520 memcpy(ndev->remote_gb,
521 (ntf.activation_params.poll_nfc_dep
522 .atr_res + NFC_ATR_RES_GT_OFFSET),
523 ndev->remote_gb_len);
524 }
525 }
019c4fba
IE
526 }
527
528 if (atomic_read(&ndev->state) == NCI_DISCOVERY) {
529 /* A single target was found and activated automatically */
530 atomic_set(&ndev->state, NCI_POLL_ACTIVE);
531 if (err == NCI_STATUS_OK)
532 nci_target_auto_activated(ndev, &ntf);
533 } else { /* ndev->state == NCI_W4_HOST_SELECT */
534 /* A selected target was activated, so complete the request */
535 atomic_set(&ndev->state, NCI_POLL_ACTIVE);
536 nci_req_complete(ndev, err);
537 }
6a2968aa
IE
538}
539
540static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
eb9bc6e9 541 struct sk_buff *skb)
6a2968aa 542{
e8c0dacd 543 struct nci_rf_deactivate_ntf *ntf = (void *) skb->data;
6a2968aa 544
20c239c1 545 pr_debug("entry, type 0x%x, reason 0x%x\n", ntf->type, ntf->reason);
6a2968aa 546
6a2968aa
IE
547 /* drop tx data queue */
548 skb_queue_purge(&ndev->tx_q);
549
550 /* drop partial rx data packet */
551 if (ndev->rx_data_reassembly) {
552 kfree_skb(ndev->rx_data_reassembly);
799030b7 553 ndev->rx_data_reassembly = NULL;
6a2968aa
IE
554 }
555
556 /* complete the data exchange transaction, if exists */
38f04c6b 557 if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
6a2968aa 558 nci_data_exchange_complete(ndev, NULL, -EIO);
bd7e01bc 559
019c4fba
IE
560 nci_clear_target_list(ndev);
561 atomic_set(&ndev->state, NCI_IDLE);
bd7e01bc 562 nci_req_complete(ndev, NCI_STATUS_OK);
6a2968aa
IE
563}
564
565void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
566{
567 __u16 ntf_opcode = nci_opcode(skb->data);
568
20c239c1
JP
569 pr_debug("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n",
570 nci_pbf(skb->data),
571 nci_opcode_gid(ntf_opcode),
572 nci_opcode_oid(ntf_opcode),
573 nci_plen(skb->data));
6a2968aa
IE
574
575 /* strip the nci control header */
576 skb_pull(skb, NCI_CTRL_HDR_SIZE);
577
578 switch (ntf_opcode) {
579 case NCI_OP_CORE_CONN_CREDITS_NTF:
580 nci_core_conn_credits_ntf_packet(ndev, skb);
581 break;
582
019c4fba
IE
583 case NCI_OP_CORE_GENERIC_ERROR_NTF:
584 nci_core_generic_error_ntf_packet(ndev, skb);
585 break;
586
004161cb
IE
587 case NCI_OP_CORE_INTF_ERROR_NTF:
588 nci_core_conn_intf_error_ntf_packet(ndev, skb);
589 break;
590
019c4fba
IE
591 case NCI_OP_RF_DISCOVER_NTF:
592 nci_rf_discover_ntf_packet(ndev, skb);
593 break;
594
e8c0dacd
IE
595 case NCI_OP_RF_INTF_ACTIVATED_NTF:
596 nci_rf_intf_activated_ntf_packet(ndev, skb);
6a2968aa
IE
597 break;
598
599 case NCI_OP_RF_DEACTIVATE_NTF:
600 nci_rf_deactivate_ntf_packet(ndev, skb);
601 break;
602
603 default:
ed1e0ad8 604 pr_err("unknown ntf opcode 0x%x\n", ntf_opcode);
6a2968aa
IE
605 break;
606 }
607
608 kfree_skb(skb);
609}