PageRenderTime 67ms CodeModel.GetById 17ms app.highlight 45ms RepoModel.GetById 2ms app.codeStats 0ms

/net/nfc/nci/rsp.c

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