1/*
2 *  The NFC Controller Interface is the communication protocol between an
3 *  NFC Controller (NFCC) and a Device Host (DH).
4 *  This is the HCI over NCI implementation, as specified in the 10.2
5 *  section of the NCI 1.1 specification.
6 *
7 *  Copyright (C) 2014  STMicroelectronics SAS. All rights reserved.
8 *
9 *  This program is free software; you can redistribute it and/or modify
10 *  it under the terms of the GNU General Public License version 2
11 *  as published by the Free Software Foundation
12 *
13 *  This program is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *  GNU General Public License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include <linux/skbuff.h>
24
25#include "../nfc.h"
26#include <net/nfc/nci.h>
27#include <net/nfc/nci_core.h>
28#include <linux/nfc.h>
29
30struct nci_data {
31	u8              conn_id;
32	u8              pipe;
33	u8              cmd;
34	const u8        *data;
35	u32             data_len;
36} __packed;
37
38struct nci_hci_create_pipe_params {
39	u8 src_gate;
40	u8 dest_host;
41	u8 dest_gate;
42} __packed;
43
44struct nci_hci_create_pipe_resp {
45	u8 src_host;
46	u8 src_gate;
47	u8 dest_host;
48	u8 dest_gate;
49	u8 pipe;
50} __packed;
51
52struct nci_hci_delete_pipe_noti {
53	u8 pipe;
54} __packed;
55
56struct nci_hci_all_pipe_cleared_noti {
57	u8 host;
58} __packed;
59
60struct nci_hcp_message {
61	u8 header;      /* type -cmd,evt,rsp- + instruction */
62	u8 data[];
63} __packed;
64
65struct nci_hcp_packet {
66	u8 header;      /* cbit+pipe */
67	struct nci_hcp_message message;
68} __packed;
69
70#define NCI_HCI_ANY_SET_PARAMETER  0x01
71#define NCI_HCI_ANY_GET_PARAMETER  0x02
72#define NCI_HCI_ANY_CLOSE_PIPE     0x04
73
74#define NCI_HFP_NO_CHAINING        0x80
75
76#define NCI_NFCEE_ID_HCI                0x80
77
78#define NCI_EVT_HOT_PLUG           0x03
79
80#define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY       0x01
81
82/* HCP headers */
83#define NCI_HCI_HCP_PACKET_HEADER_LEN      1
84#define NCI_HCI_HCP_MESSAGE_HEADER_LEN     1
85#define NCI_HCI_HCP_HEADER_LEN             2
86
87/* HCP types */
88#define NCI_HCI_HCP_COMMAND        0x00
89#define NCI_HCI_HCP_EVENT          0x01
90#define NCI_HCI_HCP_RESPONSE       0x02
91
92#define NCI_HCI_ADM_NOTIFY_PIPE_CREATED     0x12
93#define NCI_HCI_ADM_NOTIFY_PIPE_DELETED     0x13
94#define NCI_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED 0x15
95
96#define NCI_HCI_FRAGMENT           0x7f
97#define NCI_HCP_HEADER(type, instr) ((((type) & 0x03) << 6) |\
98				      ((instr) & 0x3f))
99
100#define NCI_HCP_MSG_GET_TYPE(header) ((header & 0xc0) >> 6)
101#define NCI_HCP_MSG_GET_CMD(header)  (header & 0x3f)
102#define NCI_HCP_MSG_GET_PIPE(header) (header & 0x7f)
103
104static int nci_hci_result_to_errno(u8 result)
105{
106	switch (result) {
107	case NCI_HCI_ANY_OK:
108		return 0;
109	case NCI_HCI_ANY_E_REG_PAR_UNKNOWN:
110		return -EOPNOTSUPP;
111	case NCI_HCI_ANY_E_TIMEOUT:
112		return -ETIME;
113	default:
114		return -1;
115	}
116}
117
118/* HCI core */
119static void nci_hci_reset_pipes(struct nci_hci_dev *hdev)
120{
121	int i;
122
123	for (i = 0; i < NCI_HCI_MAX_PIPES; i++) {
124		hdev->pipes[i].gate = NCI_HCI_INVALID_GATE;
125		hdev->pipes[i].host = NCI_HCI_INVALID_HOST;
126	}
127	memset(hdev->gate2pipe, NCI_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe));
128}
129
130static void nci_hci_reset_pipes_per_host(struct nci_dev *ndev, u8 host)
131{
132	int i;
133
134	for (i = 0; i < NCI_HCI_MAX_PIPES; i++) {
135		if (ndev->hci_dev->pipes[i].host == host) {
136			ndev->hci_dev->pipes[i].gate = NCI_HCI_INVALID_GATE;
137			ndev->hci_dev->pipes[i].host = NCI_HCI_INVALID_HOST;
138		}
139	}
140}
141
142/* Fragment HCI data over NCI packet.
143 * NFC Forum NCI 10.2.2 Data Exchange:
144 * The payload of the Data Packets sent on the Logical Connection SHALL be
145 * valid HCP packets, as defined within [ETSI_102622]. Each Data Packet SHALL
146 * contain a single HCP packet. NCI Segmentation and Reassembly SHALL NOT be
147 * applied to Data Messages in either direction. The HCI fragmentation mechanism
148 * is used if required.
149 */
150static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
151			     const u8 data_type, const u8 *data,
152			     size_t data_len)
153{
154	struct nci_conn_info    *conn_info;
155	struct sk_buff *skb;
156	int len, i, r;
157	u8 cb = pipe;
158
159	conn_info = ndev->hci_dev->conn_info;
160	if (!conn_info)
161		return -EPROTO;
162
163	i = 0;
164	skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len +
165			    NCI_DATA_HDR_SIZE, GFP_KERNEL);
166	if (!skb)
167		return -ENOMEM;
168
169	skb_reserve(skb, NCI_DATA_HDR_SIZE + 2);
170	*skb_push(skb, 1) = data_type;
171
172	do {
173		len = conn_info->max_pkt_payload_len;
174
175		/* If last packet add NCI_HFP_NO_CHAINING */
176		if (i + conn_info->max_pkt_payload_len -
177		    (skb->len + 1) >= data_len) {
178			cb |= NCI_HFP_NO_CHAINING;
179			len = data_len - i;
180		} else {
181			len = conn_info->max_pkt_payload_len - skb->len - 1;
182		}
183
184		*skb_push(skb, 1) = cb;
185
186		if (len > 0)
187			memcpy(skb_put(skb, len), data + i, len);
188
189		r = nci_send_data(ndev, conn_info->conn_id, skb);
190		if (r < 0)
191			return r;
192
193		i += len;
194
195		if (i < data_len) {
196			skb = nci_skb_alloc(ndev,
197					    conn_info->max_pkt_payload_len +
198					    NCI_DATA_HDR_SIZE, GFP_KERNEL);
199			if (!skb)
200				return -ENOMEM;
201
202			skb_reserve(skb, NCI_DATA_HDR_SIZE + 1);
203		}
204	} while (i < data_len);
205
206	return i;
207}
208
209static void nci_hci_send_data_req(struct nci_dev *ndev, unsigned long opt)
210{
211	struct nci_data *data = (struct nci_data *)opt;
212
213	nci_hci_send_data(ndev, data->pipe, data->cmd,
214			  data->data, data->data_len);
215}
216
217int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
218		       const u8 *param, size_t param_len)
219{
220	u8 pipe = ndev->hci_dev->gate2pipe[gate];
221
222	if (pipe == NCI_HCI_INVALID_PIPE)
223		return -EADDRNOTAVAIL;
224
225	return nci_hci_send_data(ndev, pipe,
226			NCI_HCP_HEADER(NCI_HCI_HCP_EVENT, event),
227			param, param_len);
228}
229EXPORT_SYMBOL(nci_hci_send_event);
230
231int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
232		     const u8 *param, size_t param_len,
233		     struct sk_buff **skb)
234{
235	struct nci_hcp_message *message;
236	struct nci_conn_info   *conn_info;
237	struct nci_data data;
238	int r;
239	u8 pipe = ndev->hci_dev->gate2pipe[gate];
240
241	if (pipe == NCI_HCI_INVALID_PIPE)
242		return -EADDRNOTAVAIL;
243
244	conn_info = ndev->hci_dev->conn_info;
245	if (!conn_info)
246		return -EPROTO;
247
248	data.conn_id = conn_info->conn_id;
249	data.pipe = pipe;
250	data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND, cmd);
251	data.data = param;
252	data.data_len = param_len;
253
254	r = nci_request(ndev, nci_hci_send_data_req, (unsigned long)&data,
255			msecs_to_jiffies(NCI_DATA_TIMEOUT));
256	if (r == NCI_STATUS_OK) {
257		message = (struct nci_hcp_message *)conn_info->rx_skb->data;
258		r = nci_hci_result_to_errno(
259			NCI_HCP_MSG_GET_CMD(message->header));
260		skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
261
262		if (!r && skb)
263			*skb = conn_info->rx_skb;
264	}
265
266	return r;
267}
268EXPORT_SYMBOL(nci_hci_send_cmd);
269
270static void nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
271				   u8 event, struct sk_buff *skb)
272{
273	if (ndev->ops->hci_event_received)
274		ndev->ops->hci_event_received(ndev, pipe, event, skb);
275}
276
277static void nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe,
278				 u8 cmd, struct sk_buff *skb)
279{
280	u8 gate = ndev->hci_dev->pipes[pipe].gate;
281	u8 status = NCI_HCI_ANY_OK | ~NCI_HCI_FRAGMENT;
282	u8 dest_gate, new_pipe;
283	struct nci_hci_create_pipe_resp *create_info;
284	struct nci_hci_delete_pipe_noti *delete_info;
285	struct nci_hci_all_pipe_cleared_noti *cleared_info;
286
287	pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd);
288
289	switch (cmd) {
290	case NCI_HCI_ADM_NOTIFY_PIPE_CREATED:
291		if (skb->len != 5) {
292			status = NCI_HCI_ANY_E_NOK;
293			goto exit;
294		}
295		create_info = (struct nci_hci_create_pipe_resp *)skb->data;
296		dest_gate = create_info->dest_gate;
297		new_pipe = create_info->pipe;
298
299		/* Save the new created pipe and bind with local gate,
300		 * the description for skb->data[3] is destination gate id
301		 * but since we received this cmd from host controller, we
302		 * are the destination and it is our local gate
303		 */
304		ndev->hci_dev->gate2pipe[dest_gate] = new_pipe;
305		ndev->hci_dev->pipes[new_pipe].gate = dest_gate;
306		ndev->hci_dev->pipes[new_pipe].host =
307						create_info->src_host;
308		break;
309	case NCI_HCI_ANY_OPEN_PIPE:
310		/* If the pipe is not created report an error */
311		if (gate == NCI_HCI_INVALID_GATE) {
312			status = NCI_HCI_ANY_E_NOK;
313			goto exit;
314		}
315		break;
316	case NCI_HCI_ADM_NOTIFY_PIPE_DELETED:
317		if (skb->len != 1) {
318			status = NCI_HCI_ANY_E_NOK;
319			goto exit;
320		}
321		delete_info = (struct nci_hci_delete_pipe_noti *)skb->data;
322
323		ndev->hci_dev->pipes[delete_info->pipe].gate =
324						NCI_HCI_INVALID_GATE;
325		ndev->hci_dev->pipes[delete_info->pipe].host =
326						NCI_HCI_INVALID_HOST;
327		break;
328	case NCI_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
329		if (skb->len != 1) {
330			status = NCI_HCI_ANY_E_NOK;
331			goto exit;
332		}
333
334		cleared_info =
335			(struct nci_hci_all_pipe_cleared_noti *)skb->data;
336		nci_hci_reset_pipes_per_host(ndev, cleared_info->host);
337		break;
338	default:
339		pr_debug("Discarded unknown cmd %x to gate %x\n", cmd, gate);
340		break;
341	}
342
343	if (ndev->ops->hci_cmd_received)
344		ndev->ops->hci_cmd_received(ndev, pipe, cmd, skb);
345
346exit:
347	nci_hci_send_data(ndev, pipe, status, NULL, 0);
348
349	kfree_skb(skb);
350}
351
352static void nci_hci_resp_received(struct nci_dev *ndev, u8 pipe,
353				  u8 result, struct sk_buff *skb)
354{
355	struct nci_conn_info    *conn_info;
356	u8 status = result;
357
358	conn_info = ndev->hci_dev->conn_info;
359	if (!conn_info) {
360		status = NCI_STATUS_REJECTED;
361		goto exit;
362	}
363
364	conn_info->rx_skb = skb;
365
366exit:
367	nci_req_complete(ndev, NCI_STATUS_OK);
368}
369
370/* Receive hcp message for pipe, with type and cmd.
371 * skb contains optional message data only.
372 */
373static void nci_hci_hcp_message_rx(struct nci_dev *ndev, u8 pipe,
374				   u8 type, u8 instruction, struct sk_buff *skb)
375{
376	switch (type) {
377	case NCI_HCI_HCP_RESPONSE:
378		nci_hci_resp_received(ndev, pipe, instruction, skb);
379		break;
380	case NCI_HCI_HCP_COMMAND:
381		nci_hci_cmd_received(ndev, pipe, instruction, skb);
382		break;
383	case NCI_HCI_HCP_EVENT:
384		nci_hci_event_received(ndev, pipe, instruction, skb);
385		break;
386	default:
387		pr_err("UNKNOWN MSG Type %d, instruction=%d\n",
388		       type, instruction);
389		kfree_skb(skb);
390		break;
391	}
392
393	nci_req_complete(ndev, 0);
394}
395
396static void nci_hci_msg_rx_work(struct work_struct *work)
397{
398	struct nci_hci_dev *hdev =
399		container_of(work, struct nci_hci_dev, msg_rx_work);
400	struct sk_buff *skb;
401	struct nci_hcp_message *message;
402	u8 pipe, type, instruction;
403
404	while ((skb = skb_dequeue(&hdev->msg_rx_queue)) != NULL) {
405		pipe = NCI_HCP_MSG_GET_PIPE(skb->data[0]);
406		skb_pull(skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
407		message = (struct nci_hcp_message *)skb->data;
408		type = NCI_HCP_MSG_GET_TYPE(message->header);
409		instruction = NCI_HCP_MSG_GET_CMD(message->header);
410		skb_pull(skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
411
412		nci_hci_hcp_message_rx(hdev->ndev, pipe,
413				       type, instruction, skb);
414	}
415}
416
417void nci_hci_data_received_cb(void *context,
418			      struct sk_buff *skb, int err)
419{
420	struct nci_dev *ndev = (struct nci_dev *)context;
421	struct nci_hcp_packet *packet;
422	u8 pipe, type;
423	struct sk_buff *hcp_skb;
424	struct sk_buff *frag_skb;
425	int msg_len;
426
427	pr_debug("\n");
428
429	if (err) {
430		nci_req_complete(ndev, err);
431		return;
432	}
433
434	packet = (struct nci_hcp_packet *)skb->data;
435	if ((packet->header & ~NCI_HCI_FRAGMENT) == 0) {
436		skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
437		return;
438	}
439
440	/* it's the last fragment. Does it need re-aggregation? */
441	if (skb_queue_len(&ndev->hci_dev->rx_hcp_frags)) {
442		pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
443		skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
444
445		msg_len = 0;
446		skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
447			msg_len += (frag_skb->len -
448				    NCI_HCI_HCP_PACKET_HEADER_LEN);
449		}
450
451		hcp_skb = nfc_alloc_recv_skb(NCI_HCI_HCP_PACKET_HEADER_LEN +
452					     msg_len, GFP_KERNEL);
453		if (!hcp_skb) {
454			nci_req_complete(ndev, -ENOMEM);
455			return;
456		}
457
458		*skb_put(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN) = pipe;
459
460		skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
461			msg_len = frag_skb->len - NCI_HCI_HCP_PACKET_HEADER_LEN;
462			memcpy(skb_put(hcp_skb, msg_len), frag_skb->data +
463			       NCI_HCI_HCP_PACKET_HEADER_LEN, msg_len);
464		}
465
466		skb_queue_purge(&ndev->hci_dev->rx_hcp_frags);
467	} else {
468		packet->header &= NCI_HCI_FRAGMENT;
469		hcp_skb = skb;
470	}
471
472	/* if this is a response, dispatch immediately to
473	 * unblock waiting cmd context. Otherwise, enqueue to dispatch
474	 * in separate context where handler can also execute command.
475	 */
476	packet = (struct nci_hcp_packet *)hcp_skb->data;
477	type = NCI_HCP_MSG_GET_TYPE(packet->message.header);
478	if (type == NCI_HCI_HCP_RESPONSE) {
479		pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
480		skb_pull(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
481		nci_hci_hcp_message_rx(ndev, pipe, type,
482				       NCI_STATUS_OK, hcp_skb);
483	} else {
484		skb_queue_tail(&ndev->hci_dev->msg_rx_queue, hcp_skb);
485		schedule_work(&ndev->hci_dev->msg_rx_work);
486	}
487}
488
489int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe)
490{
491	struct nci_data data;
492	struct nci_conn_info    *conn_info;
493
494	conn_info = ndev->hci_dev->conn_info;
495	if (!conn_info)
496		return -EPROTO;
497
498	data.conn_id = conn_info->conn_id;
499	data.pipe = pipe;
500	data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
501				       NCI_HCI_ANY_OPEN_PIPE);
502	data.data = NULL;
503	data.data_len = 0;
504
505	return nci_request(ndev, nci_hci_send_data_req,
506			(unsigned long)&data,
507			msecs_to_jiffies(NCI_DATA_TIMEOUT));
508}
509EXPORT_SYMBOL(nci_hci_open_pipe);
510
511int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
512		      const u8 *param, size_t param_len)
513{
514	struct nci_hcp_message *message;
515	struct nci_conn_info *conn_info;
516	struct nci_data data;
517	int r;
518	u8 *tmp;
519	u8 pipe = ndev->hci_dev->gate2pipe[gate];
520
521	pr_debug("idx=%d to gate %d\n", idx, gate);
522
523	if (pipe == NCI_HCI_INVALID_PIPE)
524		return -EADDRNOTAVAIL;
525
526	conn_info = ndev->hci_dev->conn_info;
527	if (!conn_info)
528		return -EPROTO;
529
530	tmp = kmalloc(1 + param_len, GFP_KERNEL);
531	if (!tmp)
532		return -ENOMEM;
533
534	*tmp = idx;
535	memcpy(tmp + 1, param, param_len);
536
537	data.conn_id = conn_info->conn_id;
538	data.pipe = pipe;
539	data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
540				       NCI_HCI_ANY_SET_PARAMETER);
541	data.data = tmp;
542	data.data_len = param_len + 1;
543
544	r = nci_request(ndev, nci_hci_send_data_req,
545			(unsigned long)&data,
546			msecs_to_jiffies(NCI_DATA_TIMEOUT));
547	if (r == NCI_STATUS_OK) {
548		message = (struct nci_hcp_message *)conn_info->rx_skb->data;
549		r = nci_hci_result_to_errno(
550			NCI_HCP_MSG_GET_CMD(message->header));
551		skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
552	}
553
554	kfree(tmp);
555	return r;
556}
557EXPORT_SYMBOL(nci_hci_set_param);
558
559int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
560		      struct sk_buff **skb)
561{
562	struct nci_hcp_message *message;
563	struct nci_conn_info    *conn_info;
564	struct nci_data data;
565	int r;
566	u8 pipe = ndev->hci_dev->gate2pipe[gate];
567
568	pr_debug("idx=%d to gate %d\n", idx, gate);
569
570	if (pipe == NCI_HCI_INVALID_PIPE)
571		return -EADDRNOTAVAIL;
572
573	conn_info = ndev->hci_dev->conn_info;
574	if (!conn_info)
575		return -EPROTO;
576
577	data.conn_id = conn_info->conn_id;
578	data.pipe = pipe;
579	data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
580				  NCI_HCI_ANY_GET_PARAMETER);
581	data.data = &idx;
582	data.data_len = 1;
583
584	r = nci_request(ndev, nci_hci_send_data_req, (unsigned long)&data,
585			msecs_to_jiffies(NCI_DATA_TIMEOUT));
586
587	if (r == NCI_STATUS_OK) {
588		message = (struct nci_hcp_message *)conn_info->rx_skb->data;
589		r = nci_hci_result_to_errno(
590			NCI_HCP_MSG_GET_CMD(message->header));
591		skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
592
593		if (!r && skb)
594			*skb = conn_info->rx_skb;
595	}
596
597	return r;
598}
599EXPORT_SYMBOL(nci_hci_get_param);
600
601int nci_hci_connect_gate(struct nci_dev *ndev,
602			 u8 dest_host, u8 dest_gate, u8 pipe)
603{
604	int r;
605
606	if (pipe == NCI_HCI_DO_NOT_OPEN_PIPE)
607		return 0;
608
609	if (ndev->hci_dev->gate2pipe[dest_gate] != NCI_HCI_INVALID_PIPE)
610		return -EADDRINUSE;
611
612	if (pipe != NCI_HCI_INVALID_PIPE)
613		goto open_pipe;
614
615	switch (dest_gate) {
616	case NCI_HCI_LINK_MGMT_GATE:
617		pipe = NCI_HCI_LINK_MGMT_PIPE;
618	break;
619	case NCI_HCI_ADMIN_GATE:
620		pipe = NCI_HCI_ADMIN_PIPE;
621	break;
622	}
623
624open_pipe:
625	r = nci_hci_open_pipe(ndev, pipe);
626	if (r < 0)
627		return r;
628
629	ndev->hci_dev->pipes[pipe].gate = dest_gate;
630	ndev->hci_dev->pipes[pipe].host = dest_host;
631	ndev->hci_dev->gate2pipe[dest_gate] = pipe;
632
633	return 0;
634}
635EXPORT_SYMBOL(nci_hci_connect_gate);
636
637static int nci_hci_dev_connect_gates(struct nci_dev *ndev,
638				     u8 gate_count,
639				     struct nci_hci_gate *gates)
640{
641	int r;
642
643	while (gate_count--) {
644		r = nci_hci_connect_gate(ndev, gates->dest_host,
645					 gates->gate, gates->pipe);
646		if (r < 0)
647			return r;
648		gates++;
649	}
650
651	return 0;
652}
653
654int nci_hci_dev_session_init(struct nci_dev *ndev)
655{
656	struct nci_conn_info    *conn_info;
657	struct sk_buff *skb;
658	int r;
659
660	ndev->hci_dev->count_pipes = 0;
661	ndev->hci_dev->expected_pipes = 0;
662
663	conn_info = ndev->hci_dev->conn_info;
664	if (!conn_info)
665		return -EPROTO;
666
667	conn_info->data_exchange_cb = nci_hci_data_received_cb;
668	conn_info->data_exchange_cb_context = ndev;
669
670	nci_hci_reset_pipes(ndev->hci_dev);
671
672	if (ndev->hci_dev->init_data.gates[0].gate != NCI_HCI_ADMIN_GATE)
673		return -EPROTO;
674
675	r = nci_hci_connect_gate(ndev,
676				 ndev->hci_dev->init_data.gates[0].dest_host,
677				 ndev->hci_dev->init_data.gates[0].gate,
678				 ndev->hci_dev->init_data.gates[0].pipe);
679	if (r < 0)
680		goto exit;
681
682	r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
683			      NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY, &skb);
684	if (r < 0)
685		goto exit;
686
687	if (skb->len &&
688	    skb->len == strlen(ndev->hci_dev->init_data.session_id) &&
689	    memcmp(ndev->hci_dev->init_data.session_id,
690		   skb->data, skb->len) == 0 &&
691	    ndev->ops->hci_load_session) {
692		/* Restore gate<->pipe table from some proprietary location. */
693		r = ndev->ops->hci_load_session(ndev);
694		if (r < 0)
695			goto exit;
696	} else {
697		r = nci_hci_dev_connect_gates(ndev,
698					      ndev->hci_dev->init_data.gate_count,
699					      ndev->hci_dev->init_data.gates);
700		if (r < 0)
701			goto exit;
702
703		r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
704				      NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY,
705				      ndev->hci_dev->init_data.session_id,
706				      strlen(ndev->hci_dev->init_data.session_id));
707	}
708	if (r == 0)
709		goto exit;
710
711exit:
712	kfree_skb(skb);
713
714	return r;
715}
716EXPORT_SYMBOL(nci_hci_dev_session_init);
717
718struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev)
719{
720	struct nci_hci_dev *hdev;
721
722	hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
723	if (!hdev)
724		return NULL;
725
726	skb_queue_head_init(&hdev->rx_hcp_frags);
727	INIT_WORK(&hdev->msg_rx_work, nci_hci_msg_rx_work);
728	skb_queue_head_init(&hdev->msg_rx_queue);
729	hdev->ndev = ndev;
730
731	return hdev;
732}
733