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