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) 2011 Texas Instruments, Inc.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Written by Ilan Elias <ilane@ti.com>
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Acknowledgements:
11*4882a593Smuzhiyun * This file is based on hci_event.c, which was written
12*4882a593Smuzhiyun * by Maxim Krasnyansky.
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/types.h>
18*4882a593Smuzhiyun #include <linux/interrupt.h>
19*4882a593Smuzhiyun #include <linux/bitops.h>
20*4882a593Smuzhiyun #include <linux/skbuff.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include "../nfc.h"
23*4882a593Smuzhiyun #include <net/nfc/nci.h>
24*4882a593Smuzhiyun #include <net/nfc/nci_core.h>
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /* Handle NCI Response packets */
27*4882a593Smuzhiyun
nci_core_reset_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)28*4882a593Smuzhiyun static void nci_core_reset_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun struct nci_core_reset_rsp *rsp = (void *) skb->data;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun pr_debug("status 0x%x\n", rsp->status);
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun if (rsp->status == NCI_STATUS_OK) {
35*4882a593Smuzhiyun ndev->nci_ver = rsp->nci_ver;
36*4882a593Smuzhiyun pr_debug("nci_ver 0x%x, config_status 0x%x\n",
37*4882a593Smuzhiyun rsp->nci_ver, rsp->config_status);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun nci_req_complete(ndev, rsp->status);
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
nci_core_init_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)43*4882a593Smuzhiyun static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data;
46*4882a593Smuzhiyun struct nci_core_init_rsp_2 *rsp_2;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun pr_debug("status 0x%x\n", rsp_1->status);
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (rsp_1->status != NCI_STATUS_OK)
51*4882a593Smuzhiyun goto exit;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
54*4882a593Smuzhiyun ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun if (ndev->num_supported_rf_interfaces >
57*4882a593Smuzhiyun NCI_MAX_SUPPORTED_RF_INTERFACES) {
58*4882a593Smuzhiyun ndev->num_supported_rf_interfaces =
59*4882a593Smuzhiyun NCI_MAX_SUPPORTED_RF_INTERFACES;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun memcpy(ndev->supported_rf_interfaces,
63*4882a593Smuzhiyun rsp_1->supported_rf_interfaces,
64*4882a593Smuzhiyun ndev->num_supported_rf_interfaces);
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun rsp_2 = (void *) (skb->data + 6 + rsp_1->num_supported_rf_interfaces);
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun ndev->max_logical_connections = rsp_2->max_logical_connections;
69*4882a593Smuzhiyun ndev->max_routing_table_size =
70*4882a593Smuzhiyun __le16_to_cpu(rsp_2->max_routing_table_size);
71*4882a593Smuzhiyun ndev->max_ctrl_pkt_payload_len =
72*4882a593Smuzhiyun rsp_2->max_ctrl_pkt_payload_len;
73*4882a593Smuzhiyun ndev->max_size_for_large_params =
74*4882a593Smuzhiyun __le16_to_cpu(rsp_2->max_size_for_large_params);
75*4882a593Smuzhiyun ndev->manufact_id =
76*4882a593Smuzhiyun rsp_2->manufact_id;
77*4882a593Smuzhiyun ndev->manufact_specific_info =
78*4882a593Smuzhiyun __le32_to_cpu(rsp_2->manufact_specific_info);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun pr_debug("nfcc_features 0x%x\n",
81*4882a593Smuzhiyun ndev->nfcc_features);
82*4882a593Smuzhiyun pr_debug("num_supported_rf_interfaces %d\n",
83*4882a593Smuzhiyun ndev->num_supported_rf_interfaces);
84*4882a593Smuzhiyun pr_debug("supported_rf_interfaces[0] 0x%x\n",
85*4882a593Smuzhiyun ndev->supported_rf_interfaces[0]);
86*4882a593Smuzhiyun pr_debug("supported_rf_interfaces[1] 0x%x\n",
87*4882a593Smuzhiyun ndev->supported_rf_interfaces[1]);
88*4882a593Smuzhiyun pr_debug("supported_rf_interfaces[2] 0x%x\n",
89*4882a593Smuzhiyun ndev->supported_rf_interfaces[2]);
90*4882a593Smuzhiyun pr_debug("supported_rf_interfaces[3] 0x%x\n",
91*4882a593Smuzhiyun ndev->supported_rf_interfaces[3]);
92*4882a593Smuzhiyun pr_debug("max_logical_connections %d\n",
93*4882a593Smuzhiyun ndev->max_logical_connections);
94*4882a593Smuzhiyun pr_debug("max_routing_table_size %d\n",
95*4882a593Smuzhiyun ndev->max_routing_table_size);
96*4882a593Smuzhiyun pr_debug("max_ctrl_pkt_payload_len %d\n",
97*4882a593Smuzhiyun ndev->max_ctrl_pkt_payload_len);
98*4882a593Smuzhiyun pr_debug("max_size_for_large_params %d\n",
99*4882a593Smuzhiyun ndev->max_size_for_large_params);
100*4882a593Smuzhiyun pr_debug("manufact_id 0x%x\n",
101*4882a593Smuzhiyun ndev->manufact_id);
102*4882a593Smuzhiyun pr_debug("manufact_specific_info 0x%x\n",
103*4882a593Smuzhiyun ndev->manufact_specific_info);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun exit:
106*4882a593Smuzhiyun nci_req_complete(ndev, rsp_1->status);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
nci_core_set_config_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)109*4882a593Smuzhiyun static void nci_core_set_config_rsp_packet(struct nci_dev *ndev,
110*4882a593Smuzhiyun struct sk_buff *skb)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun struct nci_core_set_config_rsp *rsp = (void *) skb->data;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun pr_debug("status 0x%x\n", rsp->status);
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun nci_req_complete(ndev, rsp->status);
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
nci_rf_disc_map_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)119*4882a593Smuzhiyun static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev,
120*4882a593Smuzhiyun struct sk_buff *skb)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun __u8 status = skb->data[0];
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun pr_debug("status 0x%x\n", status);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun nci_req_complete(ndev, status);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
nci_rf_disc_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)129*4882a593Smuzhiyun static void nci_rf_disc_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun struct nci_conn_info *conn_info;
132*4882a593Smuzhiyun __u8 status = skb->data[0];
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun pr_debug("status 0x%x\n", status);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun if (status == NCI_STATUS_OK) {
137*4882a593Smuzhiyun atomic_set(&ndev->state, NCI_DISCOVERY);
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun conn_info = ndev->rf_conn_info;
140*4882a593Smuzhiyun if (!conn_info) {
141*4882a593Smuzhiyun conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
142*4882a593Smuzhiyun sizeof(struct nci_conn_info),
143*4882a593Smuzhiyun GFP_KERNEL);
144*4882a593Smuzhiyun if (!conn_info) {
145*4882a593Smuzhiyun status = NCI_STATUS_REJECTED;
146*4882a593Smuzhiyun goto exit;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun conn_info->conn_id = NCI_STATIC_RF_CONN_ID;
149*4882a593Smuzhiyun INIT_LIST_HEAD(&conn_info->list);
150*4882a593Smuzhiyun list_add(&conn_info->list, &ndev->conn_info_list);
151*4882a593Smuzhiyun ndev->rf_conn_info = conn_info;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun exit:
156*4882a593Smuzhiyun nci_req_complete(ndev, status);
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
nci_rf_disc_select_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)159*4882a593Smuzhiyun static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev,
160*4882a593Smuzhiyun struct sk_buff *skb)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun __u8 status = skb->data[0];
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun pr_debug("status 0x%x\n", status);
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun /* Complete the request on intf_activated_ntf or generic_error_ntf */
167*4882a593Smuzhiyun if (status != NCI_STATUS_OK)
168*4882a593Smuzhiyun nci_req_complete(ndev, status);
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
nci_rf_deactivate_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)171*4882a593Smuzhiyun static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev,
172*4882a593Smuzhiyun struct sk_buff *skb)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun __u8 status = skb->data[0];
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun pr_debug("status 0x%x\n", status);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun /* If target was active, complete the request only in deactivate_ntf */
179*4882a593Smuzhiyun if ((status != NCI_STATUS_OK) ||
180*4882a593Smuzhiyun (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
181*4882a593Smuzhiyun nci_clear_target_list(ndev);
182*4882a593Smuzhiyun atomic_set(&ndev->state, NCI_IDLE);
183*4882a593Smuzhiyun nci_req_complete(ndev, status);
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
nci_nfcee_discover_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)187*4882a593Smuzhiyun static void nci_nfcee_discover_rsp_packet(struct nci_dev *ndev,
188*4882a593Smuzhiyun struct sk_buff *skb)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun struct nci_nfcee_discover_rsp *discover_rsp;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun if (skb->len != 2) {
193*4882a593Smuzhiyun nci_req_complete(ndev, NCI_STATUS_NFCEE_PROTOCOL_ERROR);
194*4882a593Smuzhiyun return;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun discover_rsp = (struct nci_nfcee_discover_rsp *)skb->data;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun if (discover_rsp->status != NCI_STATUS_OK ||
200*4882a593Smuzhiyun discover_rsp->num_nfcee == 0)
201*4882a593Smuzhiyun nci_req_complete(ndev, discover_rsp->status);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
nci_nfcee_mode_set_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)204*4882a593Smuzhiyun static void nci_nfcee_mode_set_rsp_packet(struct nci_dev *ndev,
205*4882a593Smuzhiyun struct sk_buff *skb)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun __u8 status = skb->data[0];
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun pr_debug("status 0x%x\n", status);
210*4882a593Smuzhiyun nci_req_complete(ndev, status);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
nci_core_conn_create_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)213*4882a593Smuzhiyun static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
214*4882a593Smuzhiyun struct sk_buff *skb)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun __u8 status = skb->data[0];
217*4882a593Smuzhiyun struct nci_conn_info *conn_info = NULL;
218*4882a593Smuzhiyun struct nci_core_conn_create_rsp *rsp;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun pr_debug("status 0x%x\n", status);
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if (status == NCI_STATUS_OK) {
223*4882a593Smuzhiyun rsp = (struct nci_core_conn_create_rsp *)skb->data;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
226*4882a593Smuzhiyun sizeof(*conn_info), GFP_KERNEL);
227*4882a593Smuzhiyun if (!conn_info) {
228*4882a593Smuzhiyun status = NCI_STATUS_REJECTED;
229*4882a593Smuzhiyun goto exit;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun conn_info->dest_params = devm_kzalloc(&ndev->nfc_dev->dev,
233*4882a593Smuzhiyun sizeof(struct dest_spec_params),
234*4882a593Smuzhiyun GFP_KERNEL);
235*4882a593Smuzhiyun if (!conn_info->dest_params) {
236*4882a593Smuzhiyun status = NCI_STATUS_REJECTED;
237*4882a593Smuzhiyun goto free_conn_info;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun conn_info->dest_type = ndev->cur_dest_type;
241*4882a593Smuzhiyun conn_info->dest_params->id = ndev->cur_params.id;
242*4882a593Smuzhiyun conn_info->dest_params->protocol = ndev->cur_params.protocol;
243*4882a593Smuzhiyun conn_info->conn_id = rsp->conn_id;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun /* Note: data_exchange_cb and data_exchange_cb_context need to
246*4882a593Smuzhiyun * be specify out of nci_core_conn_create_rsp_packet
247*4882a593Smuzhiyun */
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun INIT_LIST_HEAD(&conn_info->list);
250*4882a593Smuzhiyun list_add(&conn_info->list, &ndev->conn_info_list);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun if (ndev->cur_params.id == ndev->hci_dev->nfcee_id)
253*4882a593Smuzhiyun ndev->hci_dev->conn_info = conn_info;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun conn_info->conn_id = rsp->conn_id;
256*4882a593Smuzhiyun conn_info->max_pkt_payload_len = rsp->max_ctrl_pkt_payload_len;
257*4882a593Smuzhiyun atomic_set(&conn_info->credits_cnt, rsp->credits_cnt);
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun free_conn_info:
261*4882a593Smuzhiyun if (status == NCI_STATUS_REJECTED)
262*4882a593Smuzhiyun devm_kfree(&ndev->nfc_dev->dev, conn_info);
263*4882a593Smuzhiyun exit:
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun nci_req_complete(ndev, status);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
nci_core_conn_close_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)268*4882a593Smuzhiyun static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev,
269*4882a593Smuzhiyun struct sk_buff *skb)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun struct nci_conn_info *conn_info;
272*4882a593Smuzhiyun __u8 status = skb->data[0];
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun pr_debug("status 0x%x\n", status);
275*4882a593Smuzhiyun if (status == NCI_STATUS_OK) {
276*4882a593Smuzhiyun conn_info = nci_get_conn_info_by_conn_id(ndev,
277*4882a593Smuzhiyun ndev->cur_conn_id);
278*4882a593Smuzhiyun if (conn_info) {
279*4882a593Smuzhiyun list_del(&conn_info->list);
280*4882a593Smuzhiyun if (conn_info == ndev->rf_conn_info)
281*4882a593Smuzhiyun ndev->rf_conn_info = NULL;
282*4882a593Smuzhiyun devm_kfree(&ndev->nfc_dev->dev, conn_info);
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun nci_req_complete(ndev, status);
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
nci_rsp_packet(struct nci_dev * ndev,struct sk_buff * skb)288*4882a593Smuzhiyun void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun __u16 rsp_opcode = nci_opcode(skb->data);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun /* we got a rsp, stop the cmd timer */
293*4882a593Smuzhiyun del_timer(&ndev->cmd_timer);
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun pr_debug("NCI RX: MT=rsp, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n",
296*4882a593Smuzhiyun nci_pbf(skb->data),
297*4882a593Smuzhiyun nci_opcode_gid(rsp_opcode),
298*4882a593Smuzhiyun nci_opcode_oid(rsp_opcode),
299*4882a593Smuzhiyun nci_plen(skb->data));
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /* strip the nci control header */
302*4882a593Smuzhiyun skb_pull(skb, NCI_CTRL_HDR_SIZE);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun if (nci_opcode_gid(rsp_opcode) == NCI_GID_PROPRIETARY) {
305*4882a593Smuzhiyun if (nci_prop_rsp_packet(ndev, rsp_opcode, skb) == -ENOTSUPP) {
306*4882a593Smuzhiyun pr_err("unsupported rsp opcode 0x%x\n",
307*4882a593Smuzhiyun rsp_opcode);
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun goto end;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun switch (rsp_opcode) {
314*4882a593Smuzhiyun case NCI_OP_CORE_RESET_RSP:
315*4882a593Smuzhiyun nci_core_reset_rsp_packet(ndev, skb);
316*4882a593Smuzhiyun break;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun case NCI_OP_CORE_INIT_RSP:
319*4882a593Smuzhiyun nci_core_init_rsp_packet(ndev, skb);
320*4882a593Smuzhiyun break;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun case NCI_OP_CORE_SET_CONFIG_RSP:
323*4882a593Smuzhiyun nci_core_set_config_rsp_packet(ndev, skb);
324*4882a593Smuzhiyun break;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun case NCI_OP_CORE_CONN_CREATE_RSP:
327*4882a593Smuzhiyun nci_core_conn_create_rsp_packet(ndev, skb);
328*4882a593Smuzhiyun break;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun case NCI_OP_CORE_CONN_CLOSE_RSP:
331*4882a593Smuzhiyun nci_core_conn_close_rsp_packet(ndev, skb);
332*4882a593Smuzhiyun break;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun case NCI_OP_RF_DISCOVER_MAP_RSP:
335*4882a593Smuzhiyun nci_rf_disc_map_rsp_packet(ndev, skb);
336*4882a593Smuzhiyun break;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun case NCI_OP_RF_DISCOVER_RSP:
339*4882a593Smuzhiyun nci_rf_disc_rsp_packet(ndev, skb);
340*4882a593Smuzhiyun break;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun case NCI_OP_RF_DISCOVER_SELECT_RSP:
343*4882a593Smuzhiyun nci_rf_disc_select_rsp_packet(ndev, skb);
344*4882a593Smuzhiyun break;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun case NCI_OP_RF_DEACTIVATE_RSP:
347*4882a593Smuzhiyun nci_rf_deactivate_rsp_packet(ndev, skb);
348*4882a593Smuzhiyun break;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun case NCI_OP_NFCEE_DISCOVER_RSP:
351*4882a593Smuzhiyun nci_nfcee_discover_rsp_packet(ndev, skb);
352*4882a593Smuzhiyun break;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun case NCI_OP_NFCEE_MODE_SET_RSP:
355*4882a593Smuzhiyun nci_nfcee_mode_set_rsp_packet(ndev, skb);
356*4882a593Smuzhiyun break;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun default:
359*4882a593Smuzhiyun pr_err("unknown rsp opcode 0x%x\n", rsp_opcode);
360*4882a593Smuzhiyun break;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun nci_core_rsp_packet(ndev, rsp_opcode, skb);
364*4882a593Smuzhiyun end:
365*4882a593Smuzhiyun kfree_skb(skb);
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun /* trigger the next cmd */
368*4882a593Smuzhiyun atomic_set(&ndev->cmd_cnt, 1);
369*4882a593Smuzhiyun if (!skb_queue_empty(&ndev->cmd_q))
370*4882a593Smuzhiyun queue_work(ndev->cmd_wq, &ndev->cmd_work);
371*4882a593Smuzhiyun }
372