xref: /OK3568_Linux_fs/kernel/net/nfc/nci/rsp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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