xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 55bc1a37)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds    BlueZ - Bluetooth protocol stack for Linux
32d0a0346SRon Shaffer    Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds    This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds    it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds    published by the Free Software Foundation;
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
121da177e4SLinus Torvalds    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131da177e4SLinus Torvalds    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
141da177e4SLinus Torvalds    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
151da177e4SLinus Torvalds    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
161da177e4SLinus Torvalds    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
171da177e4SLinus Torvalds    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
181da177e4SLinus Torvalds    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
211da177e4SLinus Torvalds    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
221da177e4SLinus Torvalds    SOFTWARE IS DISCLAIMED.
231da177e4SLinus Torvalds */
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds #include <linux/module.h>
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds #include <linux/types.h>
301da177e4SLinus Torvalds #include <linux/errno.h>
311da177e4SLinus Torvalds #include <linux/kernel.h>
321da177e4SLinus Torvalds #include <linux/slab.h>
331da177e4SLinus Torvalds #include <linux/poll.h>
341da177e4SLinus Torvalds #include <linux/fcntl.h>
351da177e4SLinus Torvalds #include <linux/init.h>
361da177e4SLinus Torvalds #include <linux/skbuff.h>
371da177e4SLinus Torvalds #include <linux/interrupt.h>
381da177e4SLinus Torvalds #include <linux/notifier.h>
391da177e4SLinus Torvalds #include <net/sock.h>
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds #include <asm/system.h>
4270f23020SAndrei Emeltchenko #include <linux/uaccess.h>
431da177e4SLinus Torvalds #include <asm/unaligned.h>
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
461da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds /* Handle HCI Event packets */
491da177e4SLinus Torvalds 
50a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
511da177e4SLinus Torvalds {
52a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
531da177e4SLinus Torvalds 
54a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
551da177e4SLinus Torvalds 
56a9de9248SMarcel Holtmann 	if (status)
57a9de9248SMarcel Holtmann 		return;
581da177e4SLinus Torvalds 
59314b2381SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags) &&
60314b2381SJohan Hedberg 				test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
61314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 0);
62a9de9248SMarcel Holtmann 
6323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
64a9de9248SMarcel Holtmann 
65a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
661da177e4SLinus Torvalds }
676bd57416SMarcel Holtmann 
68a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
691da177e4SLinus Torvalds {
70a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
71a9de9248SMarcel Holtmann 
72a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
73a9de9248SMarcel Holtmann 
74a9de9248SMarcel Holtmann 	if (status)
75a9de9248SMarcel Holtmann 		return;
76a9de9248SMarcel Holtmann 
77314b2381SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags) &&
78314b2381SJohan Hedberg 				test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
79314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 0);
80a9de9248SMarcel Holtmann 
81a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
82a9de9248SMarcel Holtmann }
83a9de9248SMarcel Holtmann 
84a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
85a9de9248SMarcel Holtmann {
86a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
87a9de9248SMarcel Holtmann }
88a9de9248SMarcel Holtmann 
89a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
90a9de9248SMarcel Holtmann {
91a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
921da177e4SLinus Torvalds 	struct hci_conn *conn;
931da177e4SLinus Torvalds 
94a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
951da177e4SLinus Torvalds 
96a9de9248SMarcel Holtmann 	if (rp->status)
97a9de9248SMarcel Holtmann 		return;
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1001da177e4SLinus Torvalds 
101a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1021da177e4SLinus Torvalds 	if (conn) {
103a9de9248SMarcel Holtmann 		if (rp->role)
1041da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1051da177e4SLinus Torvalds 		else
1061da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1071da177e4SLinus Torvalds 	}
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
110a9de9248SMarcel Holtmann }
1111da177e4SLinus Torvalds 
112e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
113e4e8e37cSMarcel Holtmann {
114e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
115e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
116e4e8e37cSMarcel Holtmann 
117e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
118e4e8e37cSMarcel Holtmann 
119e4e8e37cSMarcel Holtmann 	if (rp->status)
120e4e8e37cSMarcel Holtmann 		return;
121e4e8e37cSMarcel Holtmann 
122e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
123e4e8e37cSMarcel Holtmann 
124e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
125e4e8e37cSMarcel Holtmann 	if (conn)
126e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
127e4e8e37cSMarcel Holtmann 
128e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
129e4e8e37cSMarcel Holtmann }
130e4e8e37cSMarcel Holtmann 
131a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
132a9de9248SMarcel Holtmann {
133a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
134a9de9248SMarcel Holtmann 	struct hci_conn *conn;
135a9de9248SMarcel Holtmann 	void *sent;
136a9de9248SMarcel Holtmann 
137a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
138a9de9248SMarcel Holtmann 
139a9de9248SMarcel Holtmann 	if (rp->status)
140a9de9248SMarcel Holtmann 		return;
141a9de9248SMarcel Holtmann 
142a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14304837f64SMarcel Holtmann 	if (!sent)
144a9de9248SMarcel Holtmann 		return;
14504837f64SMarcel Holtmann 
14604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14704837f64SMarcel Holtmann 
148a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
149e4e8e37cSMarcel Holtmann 	if (conn)
15083985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15104837f64SMarcel Holtmann 
15204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1531da177e4SLinus Torvalds }
1541da177e4SLinus Torvalds 
155e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
156e4e8e37cSMarcel Holtmann {
157e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
158e4e8e37cSMarcel Holtmann 
159e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
160e4e8e37cSMarcel Holtmann 
161e4e8e37cSMarcel Holtmann 	if (rp->status)
162e4e8e37cSMarcel Holtmann 		return;
163e4e8e37cSMarcel Holtmann 
164e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
165e4e8e37cSMarcel Holtmann }
166e4e8e37cSMarcel Holtmann 
167e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
168e4e8e37cSMarcel Holtmann {
169e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
170e4e8e37cSMarcel Holtmann 	void *sent;
171e4e8e37cSMarcel Holtmann 
172e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
173e4e8e37cSMarcel Holtmann 
174e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
175e4e8e37cSMarcel Holtmann 	if (!sent)
176e4e8e37cSMarcel Holtmann 		return;
177e4e8e37cSMarcel Holtmann 
178e4e8e37cSMarcel Holtmann 	if (!status)
179e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
180e4e8e37cSMarcel Holtmann 
18123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
182e4e8e37cSMarcel Holtmann }
183e4e8e37cSMarcel Holtmann 
184a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1851da177e4SLinus Torvalds {
186a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
187a9de9248SMarcel Holtmann 
188a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
189a9de9248SMarcel Holtmann 
19010572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19110572132SGustavo F. Padovan 
19223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
193a9de9248SMarcel Holtmann }
194a9de9248SMarcel Holtmann 
195a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
196a9de9248SMarcel Holtmann {
197a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1981da177e4SLinus Torvalds 	void *sent;
1991da177e4SLinus Torvalds 
200a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2011da177e4SLinus Torvalds 
202a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2031da177e4SLinus Torvalds 	if (!sent)
204a9de9248SMarcel Holtmann 		return;
2051da177e4SLinus Torvalds 
206b312b161SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
207b312b161SJohan Hedberg 		mgmt_set_local_name_complete(hdev->id, sent, status);
208b312b161SJohan Hedberg 
209b312b161SJohan Hedberg 	if (status)
210b312b161SJohan Hedberg 		return;
211b312b161SJohan Hedberg 
2121f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
213a9de9248SMarcel Holtmann }
214a9de9248SMarcel Holtmann 
215a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
216a9de9248SMarcel Holtmann {
217a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
218a9de9248SMarcel Holtmann 
219a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
220a9de9248SMarcel Holtmann 
221a9de9248SMarcel Holtmann 	if (rp->status)
222a9de9248SMarcel Holtmann 		return;
223a9de9248SMarcel Holtmann 
2241f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
225a9de9248SMarcel Holtmann }
226a9de9248SMarcel Holtmann 
227a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
228a9de9248SMarcel Holtmann {
229a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
230a9de9248SMarcel Holtmann 	void *sent;
231a9de9248SMarcel Holtmann 
232a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
233a9de9248SMarcel Holtmann 
234a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
235a9de9248SMarcel Holtmann 	if (!sent)
236a9de9248SMarcel Holtmann 		return;
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds 	if (!status) {
239a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
240a9de9248SMarcel Holtmann 
2411da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2421da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2431da177e4SLinus Torvalds 		else
2441da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2451da177e4SLinus Torvalds 	}
246a9de9248SMarcel Holtmann 
24723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
248a9de9248SMarcel Holtmann }
2491da177e4SLinus Torvalds 
250a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
251a9de9248SMarcel Holtmann {
252a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
253a9de9248SMarcel Holtmann 	void *sent;
254a9de9248SMarcel Holtmann 
255a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
256a9de9248SMarcel Holtmann 
257a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2581da177e4SLinus Torvalds 	if (!sent)
259a9de9248SMarcel Holtmann 		return;
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds 	if (!status) {
262a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
263a9de9248SMarcel Holtmann 
2641da177e4SLinus Torvalds 		if (param)
2651da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2661da177e4SLinus Torvalds 		else
2671da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2681da177e4SLinus Torvalds 	}
269a9de9248SMarcel Holtmann 
27023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2711da177e4SLinus Torvalds }
2721da177e4SLinus Torvalds 
273a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
274a9de9248SMarcel Holtmann {
275a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
276a9de9248SMarcel Holtmann 	void *sent;
2771da177e4SLinus Torvalds 
278a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
279a9de9248SMarcel Holtmann 
280a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2811da177e4SLinus Torvalds 	if (!sent)
282a9de9248SMarcel Holtmann 		return;
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds 	if (!status) {
285a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
2869fbcbb45SJohan Hedberg 		int old_pscan, old_iscan;
287a9de9248SMarcel Holtmann 
2889fbcbb45SJohan Hedberg 		old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
2899fbcbb45SJohan Hedberg 		old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
290a9de9248SMarcel Holtmann 
29173f22f62SJohan Hedberg 		if (param & SCAN_INQUIRY) {
2921da177e4SLinus Torvalds 			set_bit(HCI_ISCAN, &hdev->flags);
2939fbcbb45SJohan Hedberg 			if (!old_iscan)
29473f22f62SJohan Hedberg 				mgmt_discoverable(hdev->id, 1);
2959fbcbb45SJohan Hedberg 		} else if (old_iscan)
29673f22f62SJohan Hedberg 			mgmt_discoverable(hdev->id, 0);
2971da177e4SLinus Torvalds 
2989fbcbb45SJohan Hedberg 		if (param & SCAN_PAGE) {
2991da177e4SLinus Torvalds 			set_bit(HCI_PSCAN, &hdev->flags);
3009fbcbb45SJohan Hedberg 			if (!old_pscan)
3019fbcbb45SJohan Hedberg 				mgmt_connectable(hdev->id, 1);
3029fbcbb45SJohan Hedberg 		} else if (old_pscan)
3039fbcbb45SJohan Hedberg 			mgmt_connectable(hdev->id, 0);
3041da177e4SLinus Torvalds 	}
305a9de9248SMarcel Holtmann 
30623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3071da177e4SLinus Torvalds }
3081da177e4SLinus Torvalds 
309a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
310a9de9248SMarcel Holtmann {
311a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
312a9de9248SMarcel Holtmann 
313a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
314a9de9248SMarcel Holtmann 
315a9de9248SMarcel Holtmann 	if (rp->status)
316a9de9248SMarcel Holtmann 		return;
317a9de9248SMarcel Holtmann 
318a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
319a9de9248SMarcel Holtmann 
320a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
321a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
322a9de9248SMarcel Holtmann }
323a9de9248SMarcel Holtmann 
324a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
325a9de9248SMarcel Holtmann {
326a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
327a9de9248SMarcel Holtmann 	void *sent;
328a9de9248SMarcel Holtmann 
329a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
330a9de9248SMarcel Holtmann 
331f383f275SMarcel Holtmann 	if (status)
332f383f275SMarcel Holtmann 		return;
333f383f275SMarcel Holtmann 
334a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
335a9de9248SMarcel Holtmann 	if (!sent)
336a9de9248SMarcel Holtmann 		return;
337a9de9248SMarcel Holtmann 
338a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
339a9de9248SMarcel Holtmann }
340a9de9248SMarcel Holtmann 
341a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
342a9de9248SMarcel Holtmann {
343a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
344a9de9248SMarcel Holtmann 	__u16 setting;
345a9de9248SMarcel Holtmann 
346a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
347a9de9248SMarcel Holtmann 
348a9de9248SMarcel Holtmann 	if (rp->status)
349a9de9248SMarcel Holtmann 		return;
350a9de9248SMarcel Holtmann 
351a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
352a9de9248SMarcel Holtmann 
353a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
354a9de9248SMarcel Holtmann 		return;
355a9de9248SMarcel Holtmann 
356a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
357a9de9248SMarcel Holtmann 
358a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
359a9de9248SMarcel Holtmann 
360a9de9248SMarcel Holtmann 	if (hdev->notify) {
361a9de9248SMarcel Holtmann 		tasklet_disable(&hdev->tx_task);
362a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
363a9de9248SMarcel Holtmann 		tasklet_enable(&hdev->tx_task);
364a9de9248SMarcel Holtmann 	}
365a9de9248SMarcel Holtmann }
366a9de9248SMarcel Holtmann 
367a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
368a9de9248SMarcel Holtmann {
369a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
370f383f275SMarcel Holtmann 	__u16 setting;
371a9de9248SMarcel Holtmann 	void *sent;
372a9de9248SMarcel Holtmann 
373a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
374a9de9248SMarcel Holtmann 
375f383f275SMarcel Holtmann 	if (status)
376f383f275SMarcel Holtmann 		return;
377f383f275SMarcel Holtmann 
378a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
379a9de9248SMarcel Holtmann 	if (!sent)
380a9de9248SMarcel Holtmann 		return;
381a9de9248SMarcel Holtmann 
382f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
3831da177e4SLinus Torvalds 
384f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
385f383f275SMarcel Holtmann 		return;
386f383f275SMarcel Holtmann 
3871da177e4SLinus Torvalds 	hdev->voice_setting = setting;
3881da177e4SLinus Torvalds 
389a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
3901da177e4SLinus Torvalds 
3911da177e4SLinus Torvalds 	if (hdev->notify) {
3921da177e4SLinus Torvalds 		tasklet_disable(&hdev->tx_task);
3931da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
3941da177e4SLinus Torvalds 		tasklet_enable(&hdev->tx_task);
3951da177e4SLinus Torvalds 	}
3961da177e4SLinus Torvalds }
3971da177e4SLinus Torvalds 
398a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
3991da177e4SLinus Torvalds {
400a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4011da177e4SLinus Torvalds 
402a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4031da177e4SLinus Torvalds 
40423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4051143e5a6SMarcel Holtmann }
4061143e5a6SMarcel Holtmann 
407333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
408333140b5SMarcel Holtmann {
409333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
410333140b5SMarcel Holtmann 
411333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
412333140b5SMarcel Holtmann 
413333140b5SMarcel Holtmann 	if (rp->status)
414333140b5SMarcel Holtmann 		return;
415333140b5SMarcel Holtmann 
416333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
417333140b5SMarcel Holtmann }
418333140b5SMarcel Holtmann 
419333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
420333140b5SMarcel Holtmann {
421333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
422333140b5SMarcel Holtmann 	void *sent;
423333140b5SMarcel Holtmann 
424333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
425333140b5SMarcel Holtmann 
426333140b5SMarcel Holtmann 	if (status)
427333140b5SMarcel Holtmann 		return;
428333140b5SMarcel Holtmann 
429333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
430333140b5SMarcel Holtmann 	if (!sent)
431333140b5SMarcel Holtmann 		return;
432333140b5SMarcel Holtmann 
433333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
434333140b5SMarcel Holtmann }
435333140b5SMarcel Holtmann 
436d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
437d5859e22SJohan Hedberg {
438d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
439d5859e22SJohan Hedberg 		return 2;
440d5859e22SJohan Hedberg 
441d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
442d5859e22SJohan Hedberg 		return 1;
443d5859e22SJohan Hedberg 
444d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
445d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
446d5859e22SJohan Hedberg 		return 1;
447d5859e22SJohan Hedberg 
448d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
449d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
450d5859e22SJohan Hedberg 			return 1;
451d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
452d5859e22SJohan Hedberg 			return 1;
453d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
454d5859e22SJohan Hedberg 			return 1;
455d5859e22SJohan Hedberg 	}
456d5859e22SJohan Hedberg 
457d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
458d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
459d5859e22SJohan Hedberg 		return 1;
460d5859e22SJohan Hedberg 
461d5859e22SJohan Hedberg 	return 0;
462d5859e22SJohan Hedberg }
463d5859e22SJohan Hedberg 
464d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
465d5859e22SJohan Hedberg {
466d5859e22SJohan Hedberg 	u8 mode;
467d5859e22SJohan Hedberg 
468d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
469d5859e22SJohan Hedberg 
470d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
471d5859e22SJohan Hedberg }
472d5859e22SJohan Hedberg 
473d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
474d5859e22SJohan Hedberg {
475d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
476d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
477d5859e22SJohan Hedberg 	 * command otherwise */
478d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
479d5859e22SJohan Hedberg 
480d5859e22SJohan Hedberg 	/* Events for 1.2 and newer controllers */
481d5859e22SJohan Hedberg 	if (hdev->lmp_ver > 1) {
482d5859e22SJohan Hedberg 		events[4] |= 0x01; /* Flow Specification Complete */
483d5859e22SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
484d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Read Remote Extended Features Complete */
485d5859e22SJohan Hedberg 		events[5] |= 0x08; /* Synchronous Connection Complete */
486d5859e22SJohan Hedberg 		events[5] |= 0x10; /* Synchronous Connection Changed */
487d5859e22SJohan Hedberg 	}
488d5859e22SJohan Hedberg 
489d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
490d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
491d5859e22SJohan Hedberg 
492d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
493d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
494d5859e22SJohan Hedberg 
495d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
496d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
497d5859e22SJohan Hedberg 
498d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
499d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
500d5859e22SJohan Hedberg 
501d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
502d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
503d5859e22SJohan Hedberg 
504d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
505d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
506d5859e22SJohan Hedberg 
507d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
508d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
509d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
510d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
511d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
512d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
513d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
514d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
515d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
516d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
517d5859e22SJohan Hedberg 					 * Features Notification */
518d5859e22SJohan Hedberg 	}
519d5859e22SJohan Hedberg 
520d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
521d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
522d5859e22SJohan Hedberg 
523d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
524d5859e22SJohan Hedberg }
525d5859e22SJohan Hedberg 
526d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
527d5859e22SJohan Hedberg {
528d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
529d5859e22SJohan Hedberg 
530d5859e22SJohan Hedberg 	if (hdev->lmp_ver > 1)
531d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
532d5859e22SJohan Hedberg 
533d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
534d5859e22SJohan Hedberg 		u8 mode = 0x01;
535d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
536d5859e22SJohan Hedberg 	}
537d5859e22SJohan Hedberg 
538d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
539d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
540d5859e22SJohan Hedberg 
541d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
542d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
543d5859e22SJohan Hedberg }
544d5859e22SJohan Hedberg 
545a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
546a9de9248SMarcel Holtmann {
547a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5481143e5a6SMarcel Holtmann 
549a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5501143e5a6SMarcel Holtmann 
551a9de9248SMarcel Holtmann 	if (rp->status)
552a9de9248SMarcel Holtmann 		return;
5531143e5a6SMarcel Holtmann 
554a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
555e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
556d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
557e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
558d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5591da177e4SLinus Torvalds 
560a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
561a9de9248SMarcel Holtmann 					hdev->manufacturer,
562a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
563d5859e22SJohan Hedberg 
564d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
565d5859e22SJohan Hedberg 		hci_setup(hdev);
566d5859e22SJohan Hedberg }
567d5859e22SJohan Hedberg 
568d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
569d5859e22SJohan Hedberg {
570d5859e22SJohan Hedberg 	u16 link_policy = 0;
571d5859e22SJohan Hedberg 
572d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
573d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
574d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
575d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
576d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
577d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
578d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
579d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
580d5859e22SJohan Hedberg 
581d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
582d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
583d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
5841da177e4SLinus Torvalds }
5851da177e4SLinus Torvalds 
586a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
587a9de9248SMarcel Holtmann {
588a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
589a9de9248SMarcel Holtmann 
590a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
591a9de9248SMarcel Holtmann 
592a9de9248SMarcel Holtmann 	if (rp->status)
593d5859e22SJohan Hedberg 		goto done;
594a9de9248SMarcel Holtmann 
595a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
596d5859e22SJohan Hedberg 
597d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
598d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
599d5859e22SJohan Hedberg 
600d5859e22SJohan Hedberg done:
601d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
602a9de9248SMarcel Holtmann }
603a9de9248SMarcel Holtmann 
604a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
605a9de9248SMarcel Holtmann {
606a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
607a9de9248SMarcel Holtmann 
608a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
609a9de9248SMarcel Holtmann 
610a9de9248SMarcel Holtmann 	if (rp->status)
611a9de9248SMarcel Holtmann 		return;
612a9de9248SMarcel Holtmann 
613a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6141da177e4SLinus Torvalds 
6151da177e4SLinus Torvalds 	/* Adjust default settings according to features
6161da177e4SLinus Torvalds 	 * supported by device. */
617a9de9248SMarcel Holtmann 
6181da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6191da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6201da177e4SLinus Torvalds 
6211da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6221da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6231da177e4SLinus Torvalds 
6245b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6251da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6265b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6275b7f9909SMarcel Holtmann 	}
6281da177e4SLinus Torvalds 
6295b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6301da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6315b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6325b7f9909SMarcel Holtmann 	}
6335b7f9909SMarcel Holtmann 
6345b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6355b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6365b7f9909SMarcel Holtmann 
6375b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6385b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6395b7f9909SMarcel Holtmann 
6405b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6415b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6421da177e4SLinus Torvalds 
643efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
644efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
645efc7688bSMarcel Holtmann 
646efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
647efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
648efc7688bSMarcel Holtmann 
649efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
650efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
651efc7688bSMarcel Holtmann 
652a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
653a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
654a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
655a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
656a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
6571da177e4SLinus Torvalds }
6581da177e4SLinus Torvalds 
659a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
660a9de9248SMarcel Holtmann {
661a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
662a9de9248SMarcel Holtmann 
663a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
664a9de9248SMarcel Holtmann 
665a9de9248SMarcel Holtmann 	if (rp->status)
666a9de9248SMarcel Holtmann 		return;
667a9de9248SMarcel Holtmann 
668a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
669a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
670a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
671a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
672da1f5198SMarcel Holtmann 
673da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
674da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
675da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
676da1f5198SMarcel Holtmann 	}
677da1f5198SMarcel Holtmann 
678da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
679da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
6801da177e4SLinus Torvalds 
681a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
682a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
683a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
6841da177e4SLinus Torvalds }
6851da177e4SLinus Torvalds 
686a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
687a9de9248SMarcel Holtmann {
688a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6891da177e4SLinus Torvalds 
690a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
691a9de9248SMarcel Holtmann 
692a9de9248SMarcel Holtmann 	if (!rp->status)
693a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
694a9de9248SMarcel Holtmann 
69523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
69623bb5763SJohan Hedberg }
69723bb5763SJohan Hedberg 
69823bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
69923bb5763SJohan Hedberg {
70023bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
70123bb5763SJohan Hedberg 
70223bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
70323bb5763SJohan Hedberg 
70423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
7051da177e4SLinus Torvalds }
7061da177e4SLinus Torvalds 
707b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
708b0916ea0SJohan Hedberg 							struct sk_buff *skb)
709b0916ea0SJohan Hedberg {
710b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
711b0916ea0SJohan Hedberg 
712b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
713b0916ea0SJohan Hedberg 
714b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
715b0916ea0SJohan Hedberg }
716b0916ea0SJohan Hedberg 
717d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
718d5859e22SJohan Hedberg {
719d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
720d5859e22SJohan Hedberg 
721d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
722d5859e22SJohan Hedberg 
723d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
724d5859e22SJohan Hedberg }
725d5859e22SJohan Hedberg 
726d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
727d5859e22SJohan Hedberg 							struct sk_buff *skb)
728d5859e22SJohan Hedberg {
729d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
730d5859e22SJohan Hedberg 
731d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
732d5859e22SJohan Hedberg 
733d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
734d5859e22SJohan Hedberg }
735d5859e22SJohan Hedberg 
736d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
737d5859e22SJohan Hedberg 							struct sk_buff *skb)
738d5859e22SJohan Hedberg {
739d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
740d5859e22SJohan Hedberg 
741d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
742d5859e22SJohan Hedberg 
743d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
744d5859e22SJohan Hedberg }
745d5859e22SJohan Hedberg 
746d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
747d5859e22SJohan Hedberg {
748d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
749d5859e22SJohan Hedberg 
750d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
751d5859e22SJohan Hedberg 
752d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
753d5859e22SJohan Hedberg }
754d5859e22SJohan Hedberg 
755980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
756980e1a53SJohan Hedberg {
757980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
758980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
759980e1a53SJohan Hedberg 	struct hci_conn *conn;
760980e1a53SJohan Hedberg 
761980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
762980e1a53SJohan Hedberg 
763980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
764980e1a53SJohan Hedberg 		mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);
765980e1a53SJohan Hedberg 
766980e1a53SJohan Hedberg 	if (rp->status != 0)
767980e1a53SJohan Hedberg 		return;
768980e1a53SJohan Hedberg 
769980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
770980e1a53SJohan Hedberg 	if (!cp)
771980e1a53SJohan Hedberg 		return;
772980e1a53SJohan Hedberg 
773980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
774980e1a53SJohan Hedberg 	if (conn)
775980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
776980e1a53SJohan Hedberg }
777980e1a53SJohan Hedberg 
778980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
779980e1a53SJohan Hedberg {
780980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
781980e1a53SJohan Hedberg 
782980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
783980e1a53SJohan Hedberg 
784980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
785980e1a53SJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
786980e1a53SJohan Hedberg 								rp->status);
787980e1a53SJohan Hedberg }
7886ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
7896ed58ec5SVille Tervo 				       struct sk_buff *skb)
7906ed58ec5SVille Tervo {
7916ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
7926ed58ec5SVille Tervo 
7936ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7946ed58ec5SVille Tervo 
7956ed58ec5SVille Tervo 	if (rp->status)
7966ed58ec5SVille Tervo 		return;
7976ed58ec5SVille Tervo 
7986ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
7996ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8006ed58ec5SVille Tervo 
8016ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8026ed58ec5SVille Tervo 
8036ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8046ed58ec5SVille Tervo 
8056ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
8066ed58ec5SVille Tervo }
807980e1a53SJohan Hedberg 
808a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
809a5c29683SJohan Hedberg {
810a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
811a5c29683SJohan Hedberg 
812a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
813a5c29683SJohan Hedberg 
814a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
815a5c29683SJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr,
816a5c29683SJohan Hedberg 								rp->status);
817a5c29683SJohan Hedberg }
818a5c29683SJohan Hedberg 
819a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
820a5c29683SJohan Hedberg 							struct sk_buff *skb)
821a5c29683SJohan Hedberg {
822a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
823a5c29683SJohan Hedberg 
824a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
825a5c29683SJohan Hedberg 
826a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
827a5c29683SJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr,
828a5c29683SJohan Hedberg 								rp->status);
829a5c29683SJohan Hedberg }
830a5c29683SJohan Hedberg 
831c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
832c35938b2SSzymon Janc 							struct sk_buff *skb)
833c35938b2SSzymon Janc {
834c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
835c35938b2SSzymon Janc 
836c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
837c35938b2SSzymon Janc 
838c35938b2SSzymon Janc 	mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash,
839c35938b2SSzymon Janc 						rp->randomizer, rp->status);
840c35938b2SSzymon Janc }
841c35938b2SSzymon Janc 
842a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
843a9de9248SMarcel Holtmann {
844a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
845a9de9248SMarcel Holtmann 
846a9de9248SMarcel Holtmann 	if (status) {
84723bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
848a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
849314b2381SJohan Hedberg 		return;
850314b2381SJohan Hedberg 	}
851314b2381SJohan Hedberg 
852314b2381SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags) &&
853314b2381SJohan Hedberg 					!test_and_set_bit(HCI_INQUIRY,
854314b2381SJohan Hedberg 							&hdev->flags))
855314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 1);
856a9de9248SMarcel Holtmann }
857a9de9248SMarcel Holtmann 
8581da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
8591da177e4SLinus Torvalds {
860a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
8611da177e4SLinus Torvalds 	struct hci_conn *conn;
8621da177e4SLinus Torvalds 
863a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
864a9de9248SMarcel Holtmann 
865a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
8661da177e4SLinus Torvalds 	if (!cp)
8671da177e4SLinus Torvalds 		return;
8681da177e4SLinus Torvalds 
8691da177e4SLinus Torvalds 	hci_dev_lock(hdev);
8701da177e4SLinus Torvalds 
8711da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
8721da177e4SLinus Torvalds 
873a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
8741da177e4SLinus Torvalds 
8751da177e4SLinus Torvalds 	if (status) {
8761da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
8774c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
8781da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
8791da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
8801da177e4SLinus Torvalds 				hci_conn_del(conn);
8814c67bc74SMarcel Holtmann 			} else
8824c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
8831da177e4SLinus Torvalds 		}
8841da177e4SLinus Torvalds 	} else {
8851da177e4SLinus Torvalds 		if (!conn) {
8861da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
8871da177e4SLinus Torvalds 			if (conn) {
8881da177e4SLinus Torvalds 				conn->out = 1;
8891da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
8901da177e4SLinus Torvalds 			} else
891893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
8921da177e4SLinus Torvalds 		}
8931da177e4SLinus Torvalds 	}
8941da177e4SLinus Torvalds 
8951da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
8961da177e4SLinus Torvalds }
8971da177e4SLinus Torvalds 
898a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
8991da177e4SLinus Torvalds {
900a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
9011da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
9021da177e4SLinus Torvalds 	__u16 handle;
9031da177e4SLinus Torvalds 
904b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
905b6a0dc82SMarcel Holtmann 
906a9de9248SMarcel Holtmann 	if (!status)
907a9de9248SMarcel Holtmann 		return;
908a9de9248SMarcel Holtmann 
909a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
9101da177e4SLinus Torvalds 	if (!cp)
911a9de9248SMarcel Holtmann 		return;
9121da177e4SLinus Torvalds 
9131da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
9141da177e4SLinus Torvalds 
915a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
9161da177e4SLinus Torvalds 
9171da177e4SLinus Torvalds 	hci_dev_lock(hdev);
9181da177e4SLinus Torvalds 
9191da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
9205a08ecceSAndrei Emeltchenko 	if (acl) {
9215a08ecceSAndrei Emeltchenko 		sco = acl->link;
9225a08ecceSAndrei Emeltchenko 		if (sco) {
9231da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
9241da177e4SLinus Torvalds 
9251da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
9261da177e4SLinus Torvalds 			hci_conn_del(sco);
9271da177e4SLinus Torvalds 		}
9285a08ecceSAndrei Emeltchenko 	}
9291da177e4SLinus Torvalds 
9301da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
9311da177e4SLinus Torvalds }
9321da177e4SLinus Torvalds 
933f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
934f8558555SMarcel Holtmann {
935f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
936f8558555SMarcel Holtmann 	struct hci_conn *conn;
937f8558555SMarcel Holtmann 
938f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
939f8558555SMarcel Holtmann 
940f8558555SMarcel Holtmann 	if (!status)
941f8558555SMarcel Holtmann 		return;
942f8558555SMarcel Holtmann 
943f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
944f8558555SMarcel Holtmann 	if (!cp)
945f8558555SMarcel Holtmann 		return;
946f8558555SMarcel Holtmann 
947f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
948f8558555SMarcel Holtmann 
949f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
950f8558555SMarcel Holtmann 	if (conn) {
951f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
952f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
953f8558555SMarcel Holtmann 			hci_conn_put(conn);
954f8558555SMarcel Holtmann 		}
955f8558555SMarcel Holtmann 	}
956f8558555SMarcel Holtmann 
957f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
958f8558555SMarcel Holtmann }
959f8558555SMarcel Holtmann 
960f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
961f8558555SMarcel Holtmann {
962f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
963f8558555SMarcel Holtmann 	struct hci_conn *conn;
964f8558555SMarcel Holtmann 
965f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
966f8558555SMarcel Holtmann 
967f8558555SMarcel Holtmann 	if (!status)
968f8558555SMarcel Holtmann 		return;
969f8558555SMarcel Holtmann 
970f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
971f8558555SMarcel Holtmann 	if (!cp)
972f8558555SMarcel Holtmann 		return;
973f8558555SMarcel Holtmann 
974f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
975f8558555SMarcel Holtmann 
976f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
977f8558555SMarcel Holtmann 	if (conn) {
978f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
979f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
980f8558555SMarcel Holtmann 			hci_conn_put(conn);
981f8558555SMarcel Holtmann 		}
982f8558555SMarcel Holtmann 	}
983f8558555SMarcel Holtmann 
984f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
985f8558555SMarcel Holtmann }
986f8558555SMarcel Holtmann 
987127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
988392599b9SJohan Hedberg 							struct hci_conn *conn)
989392599b9SJohan Hedberg {
990392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
991392599b9SJohan Hedberg 		return 0;
992392599b9SJohan Hedberg 
993765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
994392599b9SJohan Hedberg 		return 0;
995392599b9SJohan Hedberg 
996392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
997392599b9SJohan Hedberg 	 * devices with sec_level HIGH */
998392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
999765c2a96SJohan Hedberg 				conn->pending_sec_level != BT_SECURITY_HIGH)
1000392599b9SJohan Hedberg 		return 0;
1001392599b9SJohan Hedberg 
1002392599b9SJohan Hedberg 	return 1;
1003392599b9SJohan Hedberg }
1004392599b9SJohan Hedberg 
1005a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
10061da177e4SLinus Torvalds {
1007127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1008127178d2SJohan Hedberg 	struct hci_conn *conn;
1009127178d2SJohan Hedberg 
1010a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1011127178d2SJohan Hedberg 
1012127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1013127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1014127178d2SJohan Hedberg 	if (!status)
1015127178d2SJohan Hedberg 		return;
1016127178d2SJohan Hedberg 
1017127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1018127178d2SJohan Hedberg 	if (!cp)
1019127178d2SJohan Hedberg 		return;
1020127178d2SJohan Hedberg 
1021127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1022127178d2SJohan Hedberg 
1023127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
102479c6c70cSJohan Hedberg 	if (!conn)
102579c6c70cSJohan Hedberg 		goto unlock;
102679c6c70cSJohan Hedberg 
102779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
102879c6c70cSJohan Hedberg 		goto unlock;
102979c6c70cSJohan Hedberg 
103079c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1031127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1032127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1033127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1034127178d2SJohan Hedberg 	}
1035127178d2SJohan Hedberg 
103679c6c70cSJohan Hedberg unlock:
1037127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1038a9de9248SMarcel Holtmann }
10391da177e4SLinus Torvalds 
1040769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1041769be974SMarcel Holtmann {
1042769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1043769be974SMarcel Holtmann 	struct hci_conn *conn;
1044769be974SMarcel Holtmann 
1045769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1046769be974SMarcel Holtmann 
1047769be974SMarcel Holtmann 	if (!status)
1048769be974SMarcel Holtmann 		return;
1049769be974SMarcel Holtmann 
1050769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1051769be974SMarcel Holtmann 	if (!cp)
1052769be974SMarcel Holtmann 		return;
1053769be974SMarcel Holtmann 
1054769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1055769be974SMarcel Holtmann 
1056769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1057769be974SMarcel Holtmann 	if (conn) {
1058769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1059769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1060769be974SMarcel Holtmann 			hci_conn_put(conn);
1061769be974SMarcel Holtmann 		}
1062769be974SMarcel Holtmann 	}
1063769be974SMarcel Holtmann 
1064769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1065769be974SMarcel Holtmann }
1066769be974SMarcel Holtmann 
1067769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1068769be974SMarcel Holtmann {
1069769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1070769be974SMarcel Holtmann 	struct hci_conn *conn;
1071769be974SMarcel Holtmann 
1072769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1073769be974SMarcel Holtmann 
1074769be974SMarcel Holtmann 	if (!status)
1075769be974SMarcel Holtmann 		return;
1076769be974SMarcel Holtmann 
1077769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1078769be974SMarcel Holtmann 	if (!cp)
1079769be974SMarcel Holtmann 		return;
1080769be974SMarcel Holtmann 
1081769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1082769be974SMarcel Holtmann 
1083769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1084769be974SMarcel Holtmann 	if (conn) {
1085769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1086769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1087769be974SMarcel Holtmann 			hci_conn_put(conn);
1088769be974SMarcel Holtmann 		}
1089769be974SMarcel Holtmann 	}
1090769be974SMarcel Holtmann 
1091769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1092769be974SMarcel Holtmann }
1093769be974SMarcel Holtmann 
1094a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1095a9de9248SMarcel Holtmann {
1096b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1097b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1098b6a0dc82SMarcel Holtmann 	__u16 handle;
1099b6a0dc82SMarcel Holtmann 
1100a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1101b6a0dc82SMarcel Holtmann 
1102b6a0dc82SMarcel Holtmann 	if (!status)
1103b6a0dc82SMarcel Holtmann 		return;
1104b6a0dc82SMarcel Holtmann 
1105b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1106b6a0dc82SMarcel Holtmann 	if (!cp)
1107b6a0dc82SMarcel Holtmann 		return;
1108b6a0dc82SMarcel Holtmann 
1109b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1110b6a0dc82SMarcel Holtmann 
1111b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1112b6a0dc82SMarcel Holtmann 
1113b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1114b6a0dc82SMarcel Holtmann 
1115b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11165a08ecceSAndrei Emeltchenko 	if (acl) {
11175a08ecceSAndrei Emeltchenko 		sco = acl->link;
11185a08ecceSAndrei Emeltchenko 		if (sco) {
1119b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1120b6a0dc82SMarcel Holtmann 
1121b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1122b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1123b6a0dc82SMarcel Holtmann 		}
11245a08ecceSAndrei Emeltchenko 	}
1125b6a0dc82SMarcel Holtmann 
1126b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1127a9de9248SMarcel Holtmann }
1128a9de9248SMarcel Holtmann 
1129a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1130a9de9248SMarcel Holtmann {
1131a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
113204837f64SMarcel Holtmann 	struct hci_conn *conn;
113304837f64SMarcel Holtmann 
1134a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1135a9de9248SMarcel Holtmann 
1136a9de9248SMarcel Holtmann 	if (!status)
1137a9de9248SMarcel Holtmann 		return;
1138a9de9248SMarcel Holtmann 
1139a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
114004837f64SMarcel Holtmann 	if (!cp)
1141a9de9248SMarcel Holtmann 		return;
114204837f64SMarcel Holtmann 
114304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
114404837f64SMarcel Holtmann 
114504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1146e73439d8SMarcel Holtmann 	if (conn) {
114704837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
114804837f64SMarcel Holtmann 
1149e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1150e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1151e73439d8SMarcel Holtmann 	}
1152e73439d8SMarcel Holtmann 
115304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
115404837f64SMarcel Holtmann }
115504837f64SMarcel Holtmann 
1156a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1157a9de9248SMarcel Holtmann {
1158a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
115904837f64SMarcel Holtmann 	struct hci_conn *conn;
116004837f64SMarcel Holtmann 
1161a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1162a9de9248SMarcel Holtmann 
1163a9de9248SMarcel Holtmann 	if (!status)
1164a9de9248SMarcel Holtmann 		return;
1165a9de9248SMarcel Holtmann 
1166a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
116704837f64SMarcel Holtmann 	if (!cp)
1168a9de9248SMarcel Holtmann 		return;
116904837f64SMarcel Holtmann 
117004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
117104837f64SMarcel Holtmann 
117204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1173e73439d8SMarcel Holtmann 	if (conn) {
117404837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
117504837f64SMarcel Holtmann 
1176e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1177e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1178e73439d8SMarcel Holtmann 	}
1179e73439d8SMarcel Holtmann 
118004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
118104837f64SMarcel Holtmann }
118204837f64SMarcel Holtmann 
1183fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1184fcd89c09SVille Tervo {
1185fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1186fcd89c09SVille Tervo 	struct hci_conn *conn;
1187fcd89c09SVille Tervo 
1188fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1189fcd89c09SVille Tervo 
1190fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1191fcd89c09SVille Tervo 	if (!cp)
1192fcd89c09SVille Tervo 		return;
1193fcd89c09SVille Tervo 
1194fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1195fcd89c09SVille Tervo 
1196fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1197fcd89c09SVille Tervo 
1198fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1199fcd89c09SVille Tervo 		conn);
1200fcd89c09SVille Tervo 
1201fcd89c09SVille Tervo 	if (status) {
1202fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1203fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1204fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1205fcd89c09SVille Tervo 			hci_conn_del(conn);
1206fcd89c09SVille Tervo 		}
1207fcd89c09SVille Tervo 	} else {
1208fcd89c09SVille Tervo 		if (!conn) {
1209fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
1210fcd89c09SVille Tervo 			if (conn)
1211fcd89c09SVille Tervo 				conn->out = 1;
1212fcd89c09SVille Tervo 			else
1213fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1214fcd89c09SVille Tervo 		}
1215fcd89c09SVille Tervo 	}
1216fcd89c09SVille Tervo 
1217fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1218fcd89c09SVille Tervo }
1219fcd89c09SVille Tervo 
12201da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
12211da177e4SLinus Torvalds {
12221da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
12251da177e4SLinus Torvalds 
1226314b2381SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags) &&
1227314b2381SJohan Hedberg 				test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1228314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 0);
1229a9de9248SMarcel Holtmann 
123023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
12316bd57416SMarcel Holtmann 
1232a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
12331da177e4SLinus Torvalds }
12341da177e4SLinus Torvalds 
12351da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
12361da177e4SLinus Torvalds {
123745bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1238a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
12391da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
12401da177e4SLinus Torvalds 
12411da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
12421da177e4SLinus Torvalds 
124345bb4bf0SMarcel Holtmann 	if (!num_rsp)
124445bb4bf0SMarcel Holtmann 		return;
124545bb4bf0SMarcel Holtmann 
12461da177e4SLinus Torvalds 	hci_dev_lock(hdev);
124745bb4bf0SMarcel Holtmann 
1248314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
1249314b2381SJohan Hedberg 
1250314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
1251314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
1252314b2381SJohan Hedberg 	}
1253314b2381SJohan Hedberg 
1254e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
12551da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
12561da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
12571da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
12581da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
12591da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
12601da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
12611da177e4SLinus Torvalds 		data.rssi		= 0x00;
126241a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
12631da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
1264e17acd40SJohan Hedberg 		mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0,
1265e17acd40SJohan Hedberg 									NULL);
12661da177e4SLinus Torvalds 	}
126745bb4bf0SMarcel Holtmann 
12681da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12691da177e4SLinus Torvalds }
12701da177e4SLinus Torvalds 
1271a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
12721da177e4SLinus Torvalds {
1273a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1274a9de9248SMarcel Holtmann 	struct hci_conn *conn;
12751da177e4SLinus Torvalds 
1276a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
127745bb4bf0SMarcel Holtmann 
12781da177e4SLinus Torvalds 	hci_dev_lock(hdev);
127945bb4bf0SMarcel Holtmann 
1280a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
12819499237aSMarcel Holtmann 	if (!conn) {
12829499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
12839499237aSMarcel Holtmann 			goto unlock;
12849499237aSMarcel Holtmann 
12859499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1286a9de9248SMarcel Holtmann 		if (!conn)
1287a9de9248SMarcel Holtmann 			goto unlock;
128845bb4bf0SMarcel Holtmann 
12899499237aSMarcel Holtmann 		conn->type = SCO_LINK;
12909499237aSMarcel Holtmann 	}
12919499237aSMarcel Holtmann 
1292a9de9248SMarcel Holtmann 	if (!ev->status) {
1293a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1294769be974SMarcel Holtmann 
1295769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1296769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1297769be974SMarcel Holtmann 			hci_conn_hold(conn);
1298052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1299f7520543SJohan Hedberg 			mgmt_connected(hdev->id, &ev->bdaddr);
1300769be974SMarcel Holtmann 		} else
1301a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1302a9de9248SMarcel Holtmann 
13039eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
13047d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
13057d0db0a3SMarcel Holtmann 
1306a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1307a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1308a9de9248SMarcel Holtmann 
1309a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1310a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1311a9de9248SMarcel Holtmann 
1312a9de9248SMarcel Holtmann 		/* Get remote features */
1313a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1314a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1315a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1316769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1317769be974SMarcel Holtmann 							sizeof(cp), &cp);
131845bb4bf0SMarcel Holtmann 		}
1319a9de9248SMarcel Holtmann 
1320a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1321a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
1322a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1323a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1324a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1325a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1326a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1327a9de9248SMarcel Holtmann 		}
132817d5c04cSJohan Hedberg 	} else {
1329a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
133017d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
133117d5c04cSJohan Hedberg 			mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
133217d5c04cSJohan Hedberg 	}
133345bb4bf0SMarcel Holtmann 
1334e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1335e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
133645bb4bf0SMarcel Holtmann 
1337769be974SMarcel Holtmann 	if (ev->status) {
1338a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1339a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1340c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1341c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1342a9de9248SMarcel Holtmann 
1343a9de9248SMarcel Holtmann unlock:
13441da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1345a9de9248SMarcel Holtmann 
1346a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
13471da177e4SLinus Torvalds }
13481da177e4SLinus Torvalds 
13491da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
13501da177e4SLinus Torvalds {
1351a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
13521da177e4SLinus Torvalds 	int mask = hdev->link_mode;
13531da177e4SLinus Torvalds 
1354a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
13551da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
13561da177e4SLinus Torvalds 
13571da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
13581da177e4SLinus Torvalds 
1359138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1360138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
13611da177e4SLinus Torvalds 		/* Connection accepted */
1362c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
13631da177e4SLinus Torvalds 		struct hci_conn *conn;
13641da177e4SLinus Torvalds 
13651da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1366b6a0dc82SMarcel Holtmann 
1367cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1368cc11b9c1SAndrei Emeltchenko 		if (ie)
1369c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1370c7bdd502SMarcel Holtmann 
13711da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
13721da177e4SLinus Torvalds 		if (!conn) {
1373cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1374cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1375893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
13761da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
13771da177e4SLinus Torvalds 				return;
13781da177e4SLinus Torvalds 			}
13791da177e4SLinus Torvalds 		}
1380b6a0dc82SMarcel Holtmann 
13811da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
13821da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1383b6a0dc82SMarcel Holtmann 
13841da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
13851da177e4SLinus Torvalds 
1386b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1387b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1388b6a0dc82SMarcel Holtmann 
13891da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
13901da177e4SLinus Torvalds 
13911da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
13921da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
13931da177e4SLinus Torvalds 			else
13941da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
13951da177e4SLinus Torvalds 
1396b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1397b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1398b6a0dc82SMarcel Holtmann 		} else {
1399b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1400b6a0dc82SMarcel Holtmann 
1401b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1402a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1403b6a0dc82SMarcel Holtmann 
1404b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1405b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1406b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1407b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1408b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1409b6a0dc82SMarcel Holtmann 
1410b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1411b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1412b6a0dc82SMarcel Holtmann 		}
14131da177e4SLinus Torvalds 	} else {
14141da177e4SLinus Torvalds 		/* Connection rejected */
14151da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
14161da177e4SLinus Torvalds 
14171da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
14181da177e4SLinus Torvalds 		cp.reason = 0x0f;
1419a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
14201da177e4SLinus Torvalds 	}
14211da177e4SLinus Torvalds }
14221da177e4SLinus Torvalds 
14231da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14241da177e4SLinus Torvalds {
1425a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
142604837f64SMarcel Holtmann 	struct hci_conn *conn;
14271da177e4SLinus Torvalds 
14281da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
14291da177e4SLinus Torvalds 
14308962ee74SJohan Hedberg 	if (ev->status) {
14318962ee74SJohan Hedberg 		mgmt_disconnect_failed(hdev->id);
14321da177e4SLinus Torvalds 		return;
14338962ee74SJohan Hedberg 	}
14341da177e4SLinus Torvalds 
14351da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14361da177e4SLinus Torvalds 
143704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1438f7520543SJohan Hedberg 	if (!conn)
1439f7520543SJohan Hedberg 		goto unlock;
1440f7520543SJohan Hedberg 
14411da177e4SLinus Torvalds 	conn->state = BT_CLOSED;
14427d0db0a3SMarcel Holtmann 
1443f7520543SJohan Hedberg 	if (conn->type == ACL_LINK)
1444f7520543SJohan Hedberg 		mgmt_disconnected(hdev->id, &conn->dst);
1445f7520543SJohan Hedberg 
14462950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
14471da177e4SLinus Torvalds 	hci_conn_del(conn);
14481da177e4SLinus Torvalds 
1449f7520543SJohan Hedberg unlock:
14501da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14511da177e4SLinus Torvalds }
14521da177e4SLinus Torvalds 
1453a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1454a9de9248SMarcel Holtmann {
1455a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1456a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1457a9de9248SMarcel Holtmann 
1458a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1459a9de9248SMarcel Holtmann 
1460a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1461a9de9248SMarcel Holtmann 
1462a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1463a9de9248SMarcel Holtmann 	if (conn) {
1464765c2a96SJohan Hedberg 		if (!ev->status) {
1465a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1466765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
14672a611692SJohan Hedberg 		} else {
14682a611692SJohan Hedberg 			mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
14692a611692SJohan Hedberg 		}
1470a9de9248SMarcel Holtmann 
1471a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1472a9de9248SMarcel Holtmann 
1473f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1474f8558555SMarcel Holtmann 			if (!ev->status && hdev->ssp_mode > 0 &&
1475f8558555SMarcel Holtmann 							conn->ssp_mode > 0) {
1476f8558555SMarcel Holtmann 				struct hci_cp_set_conn_encrypt cp;
1477f8558555SMarcel Holtmann 				cp.handle  = ev->handle;
1478f8558555SMarcel Holtmann 				cp.encrypt = 0x01;
1479f8558555SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1480f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1481f8558555SMarcel Holtmann 			} else {
1482f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1483f8558555SMarcel Holtmann 				hci_proto_connect_cfm(conn, ev->status);
1484f8558555SMarcel Holtmann 				hci_conn_put(conn);
1485f8558555SMarcel Holtmann 			}
1486052b30b0SMarcel Holtmann 		} else {
1487a9de9248SMarcel Holtmann 			hci_auth_cfm(conn, ev->status);
1488a9de9248SMarcel Holtmann 
1489052b30b0SMarcel Holtmann 			hci_conn_hold(conn);
1490052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1491052b30b0SMarcel Holtmann 			hci_conn_put(conn);
1492052b30b0SMarcel Holtmann 		}
1493052b30b0SMarcel Holtmann 
1494a9de9248SMarcel Holtmann 		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1495a9de9248SMarcel Holtmann 			if (!ev->status) {
1496a9de9248SMarcel Holtmann 				struct hci_cp_set_conn_encrypt cp;
1497f8558555SMarcel Holtmann 				cp.handle  = ev->handle;
1498f8558555SMarcel Holtmann 				cp.encrypt = 0x01;
1499f8558555SMarcel Holtmann 				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
1500f8558555SMarcel Holtmann 							sizeof(cp), &cp);
1501a9de9248SMarcel Holtmann 			} else {
1502a9de9248SMarcel Holtmann 				clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1503a9de9248SMarcel Holtmann 				hci_encrypt_cfm(conn, ev->status, 0x00);
1504a9de9248SMarcel Holtmann 			}
1505a9de9248SMarcel Holtmann 		}
1506a9de9248SMarcel Holtmann 	}
1507a9de9248SMarcel Holtmann 
1508a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1509a9de9248SMarcel Holtmann }
1510a9de9248SMarcel Holtmann 
1511a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1512a9de9248SMarcel Holtmann {
1513127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1514127178d2SJohan Hedberg 	struct hci_conn *conn;
1515127178d2SJohan Hedberg 
1516a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1517a9de9248SMarcel Holtmann 
1518a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1519127178d2SJohan Hedberg 
1520127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1521127178d2SJohan Hedberg 
1522a88a9652SJohan Hedberg 	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
1523a88a9652SJohan Hedberg 		mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name);
1524a88a9652SJohan Hedberg 
1525127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
152679c6c70cSJohan Hedberg 	if (!conn)
152779c6c70cSJohan Hedberg 		goto unlock;
152879c6c70cSJohan Hedberg 
152979c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
153079c6c70cSJohan Hedberg 		goto unlock;
153179c6c70cSJohan Hedberg 
153279c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1533127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1534127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1535127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1536127178d2SJohan Hedberg 	}
1537127178d2SJohan Hedberg 
153879c6c70cSJohan Hedberg unlock:
1539127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1540a9de9248SMarcel Holtmann }
1541a9de9248SMarcel Holtmann 
1542a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1543a9de9248SMarcel Holtmann {
1544a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1545a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1546a9de9248SMarcel Holtmann 
1547a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1548a9de9248SMarcel Holtmann 
1549a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1550a9de9248SMarcel Holtmann 
1551a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1552a9de9248SMarcel Holtmann 	if (conn) {
1553a9de9248SMarcel Holtmann 		if (!ev->status) {
1554ae293196SMarcel Holtmann 			if (ev->encrypt) {
1555ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1556ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1557a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1558ae293196SMarcel Holtmann 			} else
1559a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1560a9de9248SMarcel Holtmann 		}
1561a9de9248SMarcel Holtmann 
1562a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1563a9de9248SMarcel Holtmann 
1564f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1565f8558555SMarcel Holtmann 			if (!ev->status)
1566f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1567f8558555SMarcel Holtmann 
1568f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1569f8558555SMarcel Holtmann 			hci_conn_put(conn);
1570f8558555SMarcel Holtmann 		} else
1571a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1572a9de9248SMarcel Holtmann 	}
1573a9de9248SMarcel Holtmann 
1574a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1575a9de9248SMarcel Holtmann }
1576a9de9248SMarcel Holtmann 
1577a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1578a9de9248SMarcel Holtmann {
1579a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1580a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1581a9de9248SMarcel Holtmann 
1582a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1583a9de9248SMarcel Holtmann 
1584a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1585a9de9248SMarcel Holtmann 
1586a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1587a9de9248SMarcel Holtmann 	if (conn) {
1588a9de9248SMarcel Holtmann 		if (!ev->status)
1589a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1590a9de9248SMarcel Holtmann 
1591a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1592a9de9248SMarcel Holtmann 
1593a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1594a9de9248SMarcel Holtmann 	}
1595a9de9248SMarcel Holtmann 
1596a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1597a9de9248SMarcel Holtmann }
1598a9de9248SMarcel Holtmann 
1599a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1600a9de9248SMarcel Holtmann {
1601a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1602a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1603a9de9248SMarcel Holtmann 
1604a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1605a9de9248SMarcel Holtmann 
1606a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1607a9de9248SMarcel Holtmann 
1608a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1609ccd556feSJohan Hedberg 	if (!conn)
1610ccd556feSJohan Hedberg 		goto unlock;
1611ccd556feSJohan Hedberg 
1612769be974SMarcel Holtmann 	if (!ev->status)
1613a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1614a9de9248SMarcel Holtmann 
1615ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1616ccd556feSJohan Hedberg 		goto unlock;
1617ccd556feSJohan Hedberg 
1618ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1619769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1620769be974SMarcel Holtmann 		cp.handle = ev->handle;
1621769be974SMarcel Holtmann 		cp.page = 0x01;
1622ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1623769be974SMarcel Holtmann 							sizeof(cp), &cp);
1624392599b9SJohan Hedberg 		goto unlock;
1625392599b9SJohan Hedberg 	}
1626392599b9SJohan Hedberg 
1627127178d2SJohan Hedberg 	if (!ev->status) {
1628127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1629127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1630127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1631127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1632127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1633127178d2SJohan Hedberg 	}
1634392599b9SJohan Hedberg 
1635127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1636769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1637769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1638769be974SMarcel Holtmann 		hci_conn_put(conn);
1639769be974SMarcel Holtmann 	}
1640769be974SMarcel Holtmann 
1641ccd556feSJohan Hedberg unlock:
1642a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1643a9de9248SMarcel Holtmann }
1644a9de9248SMarcel Holtmann 
1645a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1646a9de9248SMarcel Holtmann {
1647a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1648a9de9248SMarcel Holtmann }
1649a9de9248SMarcel Holtmann 
1650a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1651a9de9248SMarcel Holtmann {
1652a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1653a9de9248SMarcel Holtmann }
1654a9de9248SMarcel Holtmann 
1655a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1656a9de9248SMarcel Holtmann {
1657a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1658a9de9248SMarcel Holtmann 	__u16 opcode;
1659a9de9248SMarcel Holtmann 
1660a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1661a9de9248SMarcel Holtmann 
1662a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1663a9de9248SMarcel Holtmann 
1664a9de9248SMarcel Holtmann 	switch (opcode) {
1665a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1666a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1667a9de9248SMarcel Holtmann 		break;
1668a9de9248SMarcel Holtmann 
1669a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1670a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1671a9de9248SMarcel Holtmann 		break;
1672a9de9248SMarcel Holtmann 
1673a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1674a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1675a9de9248SMarcel Holtmann 		break;
1676a9de9248SMarcel Holtmann 
1677a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1678a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1679a9de9248SMarcel Holtmann 		break;
1680a9de9248SMarcel Holtmann 
1681e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1682e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1683e4e8e37cSMarcel Holtmann 		break;
1684e4e8e37cSMarcel Holtmann 
1685a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1686a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1687a9de9248SMarcel Holtmann 		break;
1688a9de9248SMarcel Holtmann 
1689e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1690e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1691e4e8e37cSMarcel Holtmann 		break;
1692e4e8e37cSMarcel Holtmann 
1693e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1694e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1695e4e8e37cSMarcel Holtmann 		break;
1696e4e8e37cSMarcel Holtmann 
1697a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1698a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1699a9de9248SMarcel Holtmann 		break;
1700a9de9248SMarcel Holtmann 
1701a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1702a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1703a9de9248SMarcel Holtmann 		break;
1704a9de9248SMarcel Holtmann 
1705a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1706a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1707a9de9248SMarcel Holtmann 		break;
1708a9de9248SMarcel Holtmann 
1709a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1710a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1711a9de9248SMarcel Holtmann 		break;
1712a9de9248SMarcel Holtmann 
1713a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1714a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1715a9de9248SMarcel Holtmann 		break;
1716a9de9248SMarcel Holtmann 
1717a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1718a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1719a9de9248SMarcel Holtmann 		break;
1720a9de9248SMarcel Holtmann 
1721a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1722a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1723a9de9248SMarcel Holtmann 		break;
1724a9de9248SMarcel Holtmann 
1725a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1726a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1727a9de9248SMarcel Holtmann 		break;
1728a9de9248SMarcel Holtmann 
1729a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1730a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1731a9de9248SMarcel Holtmann 		break;
1732a9de9248SMarcel Holtmann 
1733a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1734a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1735a9de9248SMarcel Holtmann 		break;
1736a9de9248SMarcel Holtmann 
1737a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1738a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1739a9de9248SMarcel Holtmann 		break;
1740a9de9248SMarcel Holtmann 
1741333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1742333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1743333140b5SMarcel Holtmann 		break;
1744333140b5SMarcel Holtmann 
1745333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1746333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1747333140b5SMarcel Holtmann 		break;
1748333140b5SMarcel Holtmann 
1749a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1750a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1751a9de9248SMarcel Holtmann 		break;
1752a9de9248SMarcel Holtmann 
1753a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1754a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1755a9de9248SMarcel Holtmann 		break;
1756a9de9248SMarcel Holtmann 
1757a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1758a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1759a9de9248SMarcel Holtmann 		break;
1760a9de9248SMarcel Holtmann 
1761a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
1762a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
1763a9de9248SMarcel Holtmann 		break;
1764a9de9248SMarcel Holtmann 
1765a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
1766a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
1767a9de9248SMarcel Holtmann 		break;
1768a9de9248SMarcel Holtmann 
176923bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
177023bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
177123bb5763SJohan Hedberg 		break;
177223bb5763SJohan Hedberg 
1773b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
1774b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
1775b0916ea0SJohan Hedberg 		break;
1776b0916ea0SJohan Hedberg 
1777d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
1778d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
1779d5859e22SJohan Hedberg 		break;
1780d5859e22SJohan Hedberg 
1781d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
1782d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
1783d5859e22SJohan Hedberg 		break;
1784d5859e22SJohan Hedberg 
1785d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
1786d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
1787d5859e22SJohan Hedberg 		break;
1788d5859e22SJohan Hedberg 
1789d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
1790d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
1791d5859e22SJohan Hedberg 		break;
1792d5859e22SJohan Hedberg 
1793980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
1794980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
1795980e1a53SJohan Hedberg 		break;
1796980e1a53SJohan Hedberg 
1797980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
1798980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
1799980e1a53SJohan Hedberg 		break;
1800980e1a53SJohan Hedberg 
1801c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
1802c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
1803c35938b2SSzymon Janc 		break;
1804c35938b2SSzymon Janc 
18056ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
18066ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
18076ed58ec5SVille Tervo 		break;
18086ed58ec5SVille Tervo 
1809a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
1810a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
1811a5c29683SJohan Hedberg 		break;
1812a5c29683SJohan Hedberg 
1813a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
1814a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
1815a5c29683SJohan Hedberg 		break;
1816a5c29683SJohan Hedberg 
1817a9de9248SMarcel Holtmann 	default:
1818a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1819a9de9248SMarcel Holtmann 		break;
1820a9de9248SMarcel Holtmann 	}
1821a9de9248SMarcel Holtmann 
18226bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
18236bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
18246bd32326SVille Tervo 
1825a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1826a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1827a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1828c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
1829a9de9248SMarcel Holtmann 	}
1830a9de9248SMarcel Holtmann }
1831a9de9248SMarcel Holtmann 
1832a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1833a9de9248SMarcel Holtmann {
1834a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
1835a9de9248SMarcel Holtmann 	__u16 opcode;
1836a9de9248SMarcel Holtmann 
1837a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1838a9de9248SMarcel Holtmann 
1839a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1840a9de9248SMarcel Holtmann 
1841a9de9248SMarcel Holtmann 	switch (opcode) {
1842a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
1843a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
1844a9de9248SMarcel Holtmann 		break;
1845a9de9248SMarcel Holtmann 
1846a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
1847a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
1848a9de9248SMarcel Holtmann 		break;
1849a9de9248SMarcel Holtmann 
1850a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
1851a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
1852a9de9248SMarcel Holtmann 		break;
1853a9de9248SMarcel Holtmann 
1854f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
1855f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
1856f8558555SMarcel Holtmann 		break;
1857f8558555SMarcel Holtmann 
1858f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
1859f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
1860f8558555SMarcel Holtmann 		break;
1861f8558555SMarcel Holtmann 
1862a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
1863a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
1864a9de9248SMarcel Holtmann 		break;
1865a9de9248SMarcel Holtmann 
1866769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
1867769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
1868769be974SMarcel Holtmann 		break;
1869769be974SMarcel Holtmann 
1870769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
1871769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
1872769be974SMarcel Holtmann 		break;
1873769be974SMarcel Holtmann 
1874a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
1875a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
1876a9de9248SMarcel Holtmann 		break;
1877a9de9248SMarcel Holtmann 
1878a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
1879a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
1880a9de9248SMarcel Holtmann 		break;
1881a9de9248SMarcel Holtmann 
1882a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
1883a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
1884a9de9248SMarcel Holtmann 		break;
1885a9de9248SMarcel Holtmann 
18868962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
18878962ee74SJohan Hedberg 		if (ev->status != 0)
18888962ee74SJohan Hedberg 			mgmt_disconnect_failed(hdev->id);
18898962ee74SJohan Hedberg 		break;
18908962ee74SJohan Hedberg 
1891fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
1892fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
1893fcd89c09SVille Tervo 		break;
1894fcd89c09SVille Tervo 
1895a9de9248SMarcel Holtmann 	default:
1896a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1897a9de9248SMarcel Holtmann 		break;
1898a9de9248SMarcel Holtmann 	}
1899a9de9248SMarcel Holtmann 
19006bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
19016bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
19026bd32326SVille Tervo 
190310572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
1904a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1905a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1906c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
1907a9de9248SMarcel Holtmann 	}
1908a9de9248SMarcel Holtmann }
1909a9de9248SMarcel Holtmann 
1910a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1911a9de9248SMarcel Holtmann {
1912a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
1913a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1914a9de9248SMarcel Holtmann 
1915a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1916a9de9248SMarcel Holtmann 
1917a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1918a9de9248SMarcel Holtmann 
1919a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1920a9de9248SMarcel Holtmann 	if (conn) {
1921a9de9248SMarcel Holtmann 		if (!ev->status) {
1922a9de9248SMarcel Holtmann 			if (ev->role)
1923a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
1924a9de9248SMarcel Holtmann 			else
1925a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
1926a9de9248SMarcel Holtmann 		}
1927a9de9248SMarcel Holtmann 
1928a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
1929a9de9248SMarcel Holtmann 
1930a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
1931a9de9248SMarcel Holtmann 	}
1932a9de9248SMarcel Holtmann 
1933a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1934a9de9248SMarcel Holtmann }
1935a9de9248SMarcel Holtmann 
19361da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
19371da177e4SLinus Torvalds {
1938a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
19391ebb9252SMarcel Holtmann 	__le16 *ptr;
19401da177e4SLinus Torvalds 	int i;
19411da177e4SLinus Torvalds 
19421da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
19431da177e4SLinus Torvalds 
19441da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
19451da177e4SLinus Torvalds 
19461da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
19471da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
19481da177e4SLinus Torvalds 		return;
19491da177e4SLinus Torvalds 	}
19501da177e4SLinus Torvalds 
19511da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
19521da177e4SLinus Torvalds 
19531ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
19541da177e4SLinus Torvalds 		struct hci_conn *conn;
19551da177e4SLinus Torvalds 		__u16  handle, count;
19561da177e4SLinus Torvalds 
195783985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
195883985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
19591da177e4SLinus Torvalds 
19601da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
19611da177e4SLinus Torvalds 		if (conn) {
19621da177e4SLinus Torvalds 			conn->sent -= count;
19631da177e4SLinus Torvalds 
19645b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
196570f23020SAndrei Emeltchenko 				hdev->acl_cnt += count;
196670f23020SAndrei Emeltchenko 				if (hdev->acl_cnt > hdev->acl_pkts)
19671da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
19686ed58ec5SVille Tervo 			} else if (conn->type == LE_LINK) {
19696ed58ec5SVille Tervo 				if (hdev->le_pkts) {
19706ed58ec5SVille Tervo 					hdev->le_cnt += count;
19716ed58ec5SVille Tervo 					if (hdev->le_cnt > hdev->le_pkts)
19726ed58ec5SVille Tervo 						hdev->le_cnt = hdev->le_pkts;
19736ed58ec5SVille Tervo 				} else {
19746ed58ec5SVille Tervo 					hdev->acl_cnt += count;
19756ed58ec5SVille Tervo 					if (hdev->acl_cnt > hdev->acl_pkts)
19766ed58ec5SVille Tervo 						hdev->acl_cnt = hdev->acl_pkts;
19776ed58ec5SVille Tervo 				}
19785b7f9909SMarcel Holtmann 			} else {
197970f23020SAndrei Emeltchenko 				hdev->sco_cnt += count;
198070f23020SAndrei Emeltchenko 				if (hdev->sco_cnt > hdev->sco_pkts)
19815b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
19821da177e4SLinus Torvalds 			}
19831da177e4SLinus Torvalds 		}
19841da177e4SLinus Torvalds 	}
1985a9de9248SMarcel Holtmann 
1986c78ae283SMarcel Holtmann 	tasklet_schedule(&hdev->tx_task);
19871da177e4SLinus Torvalds 
19881da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
19891da177e4SLinus Torvalds }
19901da177e4SLinus Torvalds 
199104837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
19921da177e4SLinus Torvalds {
1993a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
199404837f64SMarcel Holtmann 	struct hci_conn *conn;
19951da177e4SLinus Torvalds 
19961da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
19971da177e4SLinus Torvalds 
19981da177e4SLinus Torvalds 	hci_dev_lock(hdev);
19991da177e4SLinus Torvalds 
200004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
200104837f64SMarcel Holtmann 	if (conn) {
200204837f64SMarcel Holtmann 		conn->mode = ev->mode;
200304837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
200404837f64SMarcel Holtmann 
200504837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
200604837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
200704837f64SMarcel Holtmann 				conn->power_save = 1;
200804837f64SMarcel Holtmann 			else
200904837f64SMarcel Holtmann 				conn->power_save = 0;
201004837f64SMarcel Holtmann 		}
2011e73439d8SMarcel Holtmann 
2012e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2013e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
201404837f64SMarcel Holtmann 	}
201504837f64SMarcel Holtmann 
201604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
201704837f64SMarcel Holtmann }
201804837f64SMarcel Holtmann 
20191da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
20201da177e4SLinus Torvalds {
2021052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2022052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2023052b30b0SMarcel Holtmann 
2024a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2025052b30b0SMarcel Holtmann 
2026052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2027052b30b0SMarcel Holtmann 
2028052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
20293d7a9d1cSMarcel Holtmann 	if (conn && conn->state == BT_CONNECTED) {
2030052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2031052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2032052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2033052b30b0SMarcel Holtmann 	}
2034052b30b0SMarcel Holtmann 
203503b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
203603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
203703b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
203803b555e1SJohan Hedberg 
2039a770bb5aSWaldemar Rymarkiewicz 	if (test_bit(HCI_MGMT, &hdev->flags)) {
2040a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2041a770bb5aSWaldemar Rymarkiewicz 
2042a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2043a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2044a770bb5aSWaldemar Rymarkiewicz 		else
2045a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2046a770bb5aSWaldemar Rymarkiewicz 
2047a770bb5aSWaldemar Rymarkiewicz 		mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure);
2048a770bb5aSWaldemar Rymarkiewicz 	}
2049980e1a53SJohan Hedberg 
2050052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
20511da177e4SLinus Torvalds }
20521da177e4SLinus Torvalds 
20531da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
20541da177e4SLinus Torvalds {
205555ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
205655ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
205755ed8ca1SJohan Hedberg 	struct hci_conn *conn;
205855ed8ca1SJohan Hedberg 	struct link_key *key;
205955ed8ca1SJohan Hedberg 
2060a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
206155ed8ca1SJohan Hedberg 
206255ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
206355ed8ca1SJohan Hedberg 		return;
206455ed8ca1SJohan Hedberg 
206555ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
206655ed8ca1SJohan Hedberg 
206755ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
206855ed8ca1SJohan Hedberg 	if (!key) {
206955ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
207055ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
207155ed8ca1SJohan Hedberg 		goto not_found;
207255ed8ca1SJohan Hedberg 	}
207355ed8ca1SJohan Hedberg 
207455ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
207555ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
207655ed8ca1SJohan Hedberg 
2077b6020ba0SWaldemar Rymarkiewicz 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2078b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
207955ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
208055ed8ca1SJohan Hedberg 		goto not_found;
208155ed8ca1SJohan Hedberg 	}
208255ed8ca1SJohan Hedberg 
208355ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
208460b83f57SWaldemar Rymarkiewicz 	if (conn) {
208560b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
208660b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
208760b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
208855ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
208955ed8ca1SJohan Hedberg 			goto not_found;
209055ed8ca1SJohan Hedberg 		}
209155ed8ca1SJohan Hedberg 
209260b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
209360b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
209460b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
209560b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
209660b83f57SWaldemar Rymarkiewicz 			goto not_found;
209760b83f57SWaldemar Rymarkiewicz 		}
209860b83f57SWaldemar Rymarkiewicz 
209960b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
210060b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
210160b83f57SWaldemar Rymarkiewicz 	}
210260b83f57SWaldemar Rymarkiewicz 
210355ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
210455ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
210555ed8ca1SJohan Hedberg 
210655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
210755ed8ca1SJohan Hedberg 
210855ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
210955ed8ca1SJohan Hedberg 
211055ed8ca1SJohan Hedberg 	return;
211155ed8ca1SJohan Hedberg 
211255ed8ca1SJohan Hedberg not_found:
211355ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
211455ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
21151da177e4SLinus Torvalds }
21161da177e4SLinus Torvalds 
21171da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
21181da177e4SLinus Torvalds {
2119052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2120052b30b0SMarcel Holtmann 	struct hci_conn *conn;
212155ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2122052b30b0SMarcel Holtmann 
2123a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2124052b30b0SMarcel Holtmann 
2125052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2126052b30b0SMarcel Holtmann 
2127052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2128052b30b0SMarcel Holtmann 	if (conn) {
2129052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2130052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2131980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
213213d39315SWaldemar Rymarkiewicz 
213313d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
213413d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
213513d39315SWaldemar Rymarkiewicz 
2136052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2137052b30b0SMarcel Holtmann 	}
2138052b30b0SMarcel Holtmann 
213955ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
214055ed8ca1SJohan Hedberg 		hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
214155ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
214255ed8ca1SJohan Hedberg 
2143052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
21441da177e4SLinus Torvalds }
21451da177e4SLinus Torvalds 
214604837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
214704837f64SMarcel Holtmann {
2148a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
214904837f64SMarcel Holtmann 	struct hci_conn *conn;
215004837f64SMarcel Holtmann 
215104837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
215204837f64SMarcel Holtmann 
215304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
215404837f64SMarcel Holtmann 
215504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
21561da177e4SLinus Torvalds 	if (conn && !ev->status) {
21571da177e4SLinus Torvalds 		struct inquiry_entry *ie;
21581da177e4SLinus Torvalds 
2159cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2160cc11b9c1SAndrei Emeltchenko 		if (ie) {
21611da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
21621da177e4SLinus Torvalds 			ie->timestamp = jiffies;
21631da177e4SLinus Torvalds 		}
21641da177e4SLinus Torvalds 	}
21651da177e4SLinus Torvalds 
21661da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
21671da177e4SLinus Torvalds }
21681da177e4SLinus Torvalds 
2169a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2170a8746417SMarcel Holtmann {
2171a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2172a8746417SMarcel Holtmann 	struct hci_conn *conn;
2173a8746417SMarcel Holtmann 
2174a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2175a8746417SMarcel Holtmann 
2176a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2177a8746417SMarcel Holtmann 
2178a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2179a8746417SMarcel Holtmann 	if (conn && !ev->status)
2180a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2181a8746417SMarcel Holtmann 
2182a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2183a8746417SMarcel Holtmann }
2184a8746417SMarcel Holtmann 
218585a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
218685a1e930SMarcel Holtmann {
2187a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
218885a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
218985a1e930SMarcel Holtmann 
219085a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
219185a1e930SMarcel Holtmann 
219285a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
219385a1e930SMarcel Holtmann 
2194cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2195cc11b9c1SAndrei Emeltchenko 	if (ie) {
219685a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
219785a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
219885a1e930SMarcel Holtmann 	}
219985a1e930SMarcel Holtmann 
220085a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
220185a1e930SMarcel Holtmann }
220285a1e930SMarcel Holtmann 
2203a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2204a9de9248SMarcel Holtmann {
2205a9de9248SMarcel Holtmann 	struct inquiry_data data;
2206a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2207a9de9248SMarcel Holtmann 
2208a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2209a9de9248SMarcel Holtmann 
2210a9de9248SMarcel Holtmann 	if (!num_rsp)
2211a9de9248SMarcel Holtmann 		return;
2212a9de9248SMarcel Holtmann 
2213a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2214a9de9248SMarcel Holtmann 
2215314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
2216314b2381SJohan Hedberg 
2217314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
2218314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
2219314b2381SJohan Hedberg 	}
2220314b2381SJohan Hedberg 
2221a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2222138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2223138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2224a9de9248SMarcel Holtmann 
2225e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2226a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2227a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2228a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2229a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2230a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2231a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2232a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
223341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2234a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
2235e17acd40SJohan Hedberg 			mgmt_device_found(hdev->id, &info->bdaddr,
2236e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2237e17acd40SJohan Hedberg 						NULL);
2238a9de9248SMarcel Holtmann 		}
2239a9de9248SMarcel Holtmann 	} else {
2240a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2241a9de9248SMarcel Holtmann 
2242e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2243a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2244a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2245a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2246a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2247a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2248a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2249a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
225041a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2251a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
2252e17acd40SJohan Hedberg 			mgmt_device_found(hdev->id, &info->bdaddr,
2253e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2254e17acd40SJohan Hedberg 						NULL);
2255a9de9248SMarcel Holtmann 		}
2256a9de9248SMarcel Holtmann 	}
2257a9de9248SMarcel Holtmann 
2258a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2259a9de9248SMarcel Holtmann }
2260a9de9248SMarcel Holtmann 
2261a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2262a9de9248SMarcel Holtmann {
226341a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
226441a96212SMarcel Holtmann 	struct hci_conn *conn;
226541a96212SMarcel Holtmann 
2266a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
226741a96212SMarcel Holtmann 
226841a96212SMarcel Holtmann 	hci_dev_lock(hdev);
226941a96212SMarcel Holtmann 
227041a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2271ccd556feSJohan Hedberg 	if (!conn)
2272ccd556feSJohan Hedberg 		goto unlock;
2273ccd556feSJohan Hedberg 
2274769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
227541a96212SMarcel Holtmann 		struct inquiry_entry *ie;
227641a96212SMarcel Holtmann 
2277cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2278cc11b9c1SAndrei Emeltchenko 		if (ie)
227941a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
228041a96212SMarcel Holtmann 
228141a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
228241a96212SMarcel Holtmann 	}
228341a96212SMarcel Holtmann 
2284ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2285ccd556feSJohan Hedberg 		goto unlock;
2286ccd556feSJohan Hedberg 
2287127178d2SJohan Hedberg 	if (!ev->status) {
2288127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2289127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2290127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2291127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2292127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2293127178d2SJohan Hedberg 	}
2294392599b9SJohan Hedberg 
2295127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2296769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2297769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2298769be974SMarcel Holtmann 		hci_conn_put(conn);
2299769be974SMarcel Holtmann 	}
2300769be974SMarcel Holtmann 
2301ccd556feSJohan Hedberg unlock:
230241a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2303a9de9248SMarcel Holtmann }
2304a9de9248SMarcel Holtmann 
2305a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2306a9de9248SMarcel Holtmann {
2307b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2308b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2309b6a0dc82SMarcel Holtmann 
2310b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2311b6a0dc82SMarcel Holtmann 
2312b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2313b6a0dc82SMarcel Holtmann 
2314b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
23159dc0a3afSMarcel Holtmann 	if (!conn) {
23169dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
23179dc0a3afSMarcel Holtmann 			goto unlock;
23189dc0a3afSMarcel Holtmann 
23199dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2320b6a0dc82SMarcel Holtmann 		if (!conn)
2321b6a0dc82SMarcel Holtmann 			goto unlock;
2322b6a0dc82SMarcel Holtmann 
23239dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
23249dc0a3afSMarcel Holtmann 	}
23259dc0a3afSMarcel Holtmann 
2326732547f9SMarcel Holtmann 	switch (ev->status) {
2327732547f9SMarcel Holtmann 	case 0x00:
2328732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2329732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2330732547f9SMarcel Holtmann 
23319eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2332732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2333732547f9SMarcel Holtmann 		break;
2334732547f9SMarcel Holtmann 
2335705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2336732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
23371038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2338732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2339732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2340efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2341efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2342efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2343efc7688bSMarcel Holtmann 			goto unlock;
2344efc7688bSMarcel Holtmann 		}
2345732547f9SMarcel Holtmann 		/* fall through */
2346efc7688bSMarcel Holtmann 
2347732547f9SMarcel Holtmann 	default:
2348b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2349732547f9SMarcel Holtmann 		break;
2350732547f9SMarcel Holtmann 	}
2351b6a0dc82SMarcel Holtmann 
2352b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2353b6a0dc82SMarcel Holtmann 	if (ev->status)
2354b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2355b6a0dc82SMarcel Holtmann 
2356b6a0dc82SMarcel Holtmann unlock:
2357b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2358a9de9248SMarcel Holtmann }
2359a9de9248SMarcel Holtmann 
2360a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2361a9de9248SMarcel Holtmann {
2362a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2363a9de9248SMarcel Holtmann }
2364a9de9248SMarcel Holtmann 
236504837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
236604837f64SMarcel Holtmann {
2367a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
236804837f64SMarcel Holtmann 
236904837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
237004837f64SMarcel Holtmann }
237104837f64SMarcel Holtmann 
2372a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2373a9de9248SMarcel Holtmann {
2374a9de9248SMarcel Holtmann 	struct inquiry_data data;
2375a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2376a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2377a9de9248SMarcel Holtmann 
2378a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2379a9de9248SMarcel Holtmann 
2380a9de9248SMarcel Holtmann 	if (!num_rsp)
2381a9de9248SMarcel Holtmann 		return;
2382a9de9248SMarcel Holtmann 
2383314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
2384314b2381SJohan Hedberg 
2385314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
2386314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
2387314b2381SJohan Hedberg 	}
2388314b2381SJohan Hedberg 
2389a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2390a9de9248SMarcel Holtmann 
2391e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2392a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2393a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2394a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2395a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2396a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2397a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2398a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
239941a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2400a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
2401e17acd40SJohan Hedberg 		mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class,
2402e17acd40SJohan Hedberg 						info->rssi, info->data);
2403a9de9248SMarcel Holtmann 	}
2404a9de9248SMarcel Holtmann 
2405a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2406a9de9248SMarcel Holtmann }
2407a9de9248SMarcel Holtmann 
240817fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
240917fa4b9dSJohan Hedberg {
241017fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
241117fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
241217fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
241317fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
241417fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
241517fa4b9dSJohan Hedberg 			return 0x02;
241617fa4b9dSJohan Hedberg 		else
241717fa4b9dSJohan Hedberg 			return 0x03;
241817fa4b9dSJohan Hedberg 	}
241917fa4b9dSJohan Hedberg 
242017fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
242117fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
242258797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
242317fa4b9dSJohan Hedberg 
242417fa4b9dSJohan Hedberg 	return conn->auth_type;
242517fa4b9dSJohan Hedberg }
242617fa4b9dSJohan Hedberg 
24270493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
24280493684eSMarcel Holtmann {
24290493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
24300493684eSMarcel Holtmann 	struct hci_conn *conn;
24310493684eSMarcel Holtmann 
24320493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
24330493684eSMarcel Holtmann 
24340493684eSMarcel Holtmann 	hci_dev_lock(hdev);
24350493684eSMarcel Holtmann 
24360493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
243703b555e1SJohan Hedberg 	if (!conn)
243803b555e1SJohan Hedberg 		goto unlock;
243903b555e1SJohan Hedberg 
24400493684eSMarcel Holtmann 	hci_conn_hold(conn);
24410493684eSMarcel Holtmann 
244203b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
244303b555e1SJohan Hedberg 		goto unlock;
244403b555e1SJohan Hedberg 
244503b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
244603b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
244717fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
244817fa4b9dSJohan Hedberg 
244917fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
245017fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
245117fa4b9dSJohan Hedberg 		cp.authentication = hci_get_auth_req(conn);
245217fa4b9dSJohan Hedberg 
2453ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2454ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2455ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2456ce85ee13SSzymon Janc 		else
2457ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2458ce85ee13SSzymon Janc 
245917fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
246017fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
246103b555e1SJohan Hedberg 	} else {
246203b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
246303b555e1SJohan Hedberg 
246403b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
246503b555e1SJohan Hedberg 		cp.reason = 0x16; /* Pairing not allowed */
246603b555e1SJohan Hedberg 
246703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
246803b555e1SJohan Hedberg 							sizeof(cp), &cp);
246903b555e1SJohan Hedberg 	}
247003b555e1SJohan Hedberg 
247103b555e1SJohan Hedberg unlock:
247203b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
247303b555e1SJohan Hedberg }
247403b555e1SJohan Hedberg 
247503b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
247603b555e1SJohan Hedberg {
247703b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
247803b555e1SJohan Hedberg 	struct hci_conn *conn;
247903b555e1SJohan Hedberg 
248003b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
248103b555e1SJohan Hedberg 
248203b555e1SJohan Hedberg 	hci_dev_lock(hdev);
248303b555e1SJohan Hedberg 
248403b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
248503b555e1SJohan Hedberg 	if (!conn)
248603b555e1SJohan Hedberg 		goto unlock;
248703b555e1SJohan Hedberg 
248803b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
248903b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
249003b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
249103b555e1SJohan Hedberg 
249203b555e1SJohan Hedberg unlock:
24930493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
24940493684eSMarcel Holtmann }
24950493684eSMarcel Holtmann 
2496a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2497a5c29683SJohan Hedberg 							struct sk_buff *skb)
2498a5c29683SJohan Hedberg {
2499a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
250055bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
25017a828908SJohan Hedberg 	struct hci_conn *conn;
2502a5c29683SJohan Hedberg 
2503a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
2504a5c29683SJohan Hedberg 
2505a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
2506a5c29683SJohan Hedberg 
25077a828908SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
25087a828908SJohan Hedberg 		goto unlock;
25097a828908SJohan Hedberg 
25107a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
25117a828908SJohan Hedberg 	if (!conn)
25127a828908SJohan Hedberg 		goto unlock;
25137a828908SJohan Hedberg 
25147a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
25157a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
25167a828908SJohan Hedberg 
25177a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
25187a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
25197a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
25207a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
25217a828908SJohan Hedberg 	 * bit set. */
25227a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
25237a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
25247a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
25257a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
25267a828908SJohan Hedberg 		goto unlock;
25277a828908SJohan Hedberg 	}
25287a828908SJohan Hedberg 
25297a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
25307a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
25317a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
253255bc1a37SJohan Hedberg 
253355bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
253455bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
253555bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
253655bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
253755bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
253855bc1a37SJohan Hedberg 			confirm_hint = 1;
253955bc1a37SJohan Hedberg 			goto confirm;
254055bc1a37SJohan Hedberg 		}
254155bc1a37SJohan Hedberg 
25429f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
25439f61656aSJohan Hedberg 						hdev->auto_accept_delay);
25449f61656aSJohan Hedberg 
25459f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
25469f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
25479f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
25489f61656aSJohan Hedberg 			goto unlock;
25499f61656aSJohan Hedberg 		}
25509f61656aSJohan Hedberg 
25517a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
25527a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
25537a828908SJohan Hedberg 		goto unlock;
25547a828908SJohan Hedberg 	}
25557a828908SJohan Hedberg 
255655bc1a37SJohan Hedberg confirm:
255755bc1a37SJohan Hedberg 	mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey,
255855bc1a37SJohan Hedberg 								confirm_hint);
2559a5c29683SJohan Hedberg 
25607a828908SJohan Hedberg unlock:
2561a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
2562a5c29683SJohan Hedberg }
2563a5c29683SJohan Hedberg 
25640493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
25650493684eSMarcel Holtmann {
25660493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
25670493684eSMarcel Holtmann 	struct hci_conn *conn;
25680493684eSMarcel Holtmann 
25690493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
25700493684eSMarcel Holtmann 
25710493684eSMarcel Holtmann 	hci_dev_lock(hdev);
25720493684eSMarcel Holtmann 
25730493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
25742a611692SJohan Hedberg 	if (!conn)
25752a611692SJohan Hedberg 		goto unlock;
25762a611692SJohan Hedberg 
25772a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
25782a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
25792a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
25802a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
25812a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
25822a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
25832a611692SJohan Hedberg 		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
25842a611692SJohan Hedberg 
25850493684eSMarcel Holtmann 	hci_conn_put(conn);
25860493684eSMarcel Holtmann 
25872a611692SJohan Hedberg unlock:
25880493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
25890493684eSMarcel Holtmann }
25900493684eSMarcel Holtmann 
259141a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
259241a96212SMarcel Holtmann {
259341a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
259441a96212SMarcel Holtmann 	struct inquiry_entry *ie;
259541a96212SMarcel Holtmann 
259641a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
259741a96212SMarcel Holtmann 
259841a96212SMarcel Holtmann 	hci_dev_lock(hdev);
259941a96212SMarcel Holtmann 
2600cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2601cc11b9c1SAndrei Emeltchenko 	if (ie)
260241a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
260341a96212SMarcel Holtmann 
260441a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
260541a96212SMarcel Holtmann }
260641a96212SMarcel Holtmann 
26072763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
26082763eda6SSzymon Janc 							struct sk_buff *skb)
26092763eda6SSzymon Janc {
26102763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
26112763eda6SSzymon Janc 	struct oob_data *data;
26122763eda6SSzymon Janc 
26132763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
26142763eda6SSzymon Janc 
26152763eda6SSzymon Janc 	hci_dev_lock(hdev);
26162763eda6SSzymon Janc 
2617e1ba1f15SSzymon Janc 	if (!test_bit(HCI_MGMT, &hdev->flags))
2618e1ba1f15SSzymon Janc 		goto unlock;
2619e1ba1f15SSzymon Janc 
26202763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
26212763eda6SSzymon Janc 	if (data) {
26222763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
26232763eda6SSzymon Janc 
26242763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
26252763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
26262763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
26272763eda6SSzymon Janc 
26282763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
26292763eda6SSzymon Janc 									&cp);
26302763eda6SSzymon Janc 	} else {
26312763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
26322763eda6SSzymon Janc 
26332763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
26342763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
26352763eda6SSzymon Janc 									&cp);
26362763eda6SSzymon Janc 	}
26372763eda6SSzymon Janc 
2638e1ba1f15SSzymon Janc unlock:
26392763eda6SSzymon Janc 	hci_dev_unlock(hdev);
26402763eda6SSzymon Janc }
26412763eda6SSzymon Janc 
2642fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2643fcd89c09SVille Tervo {
2644fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2645fcd89c09SVille Tervo 	struct hci_conn *conn;
2646fcd89c09SVille Tervo 
2647fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
2648fcd89c09SVille Tervo 
2649fcd89c09SVille Tervo 	hci_dev_lock(hdev);
2650fcd89c09SVille Tervo 
2651fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2652b62f328bSVille Tervo 	if (!conn) {
2653b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2654b62f328bSVille Tervo 		if (!conn) {
2655b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
2656b62f328bSVille Tervo 			hci_dev_unlock(hdev);
2657b62f328bSVille Tervo 			return;
2658b62f328bSVille Tervo 		}
2659b62f328bSVille Tervo 	}
2660fcd89c09SVille Tervo 
2661fcd89c09SVille Tervo 	if (ev->status) {
2662fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
2663fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
2664fcd89c09SVille Tervo 		hci_conn_del(conn);
2665fcd89c09SVille Tervo 		goto unlock;
2666fcd89c09SVille Tervo 	}
2667fcd89c09SVille Tervo 
2668fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
2669fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
2670fcd89c09SVille Tervo 
2671fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
2672fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
2673fcd89c09SVille Tervo 
2674fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
2675fcd89c09SVille Tervo 
2676fcd89c09SVille Tervo unlock:
2677fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
2678fcd89c09SVille Tervo }
2679fcd89c09SVille Tervo 
2680fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2681fcd89c09SVille Tervo {
2682fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
2683fcd89c09SVille Tervo 
2684fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
2685fcd89c09SVille Tervo 
2686fcd89c09SVille Tervo 	switch (le_ev->subevent) {
2687fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
2688fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
2689fcd89c09SVille Tervo 		break;
2690fcd89c09SVille Tervo 
2691fcd89c09SVille Tervo 	default:
2692fcd89c09SVille Tervo 		break;
2693fcd89c09SVille Tervo 	}
2694fcd89c09SVille Tervo }
2695fcd89c09SVille Tervo 
26961da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
26971da177e4SLinus Torvalds {
2698a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
2699a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
27001da177e4SLinus Torvalds 
27011da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
27021da177e4SLinus Torvalds 
2703a9de9248SMarcel Holtmann 	switch (event) {
27041da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
27051da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
27061da177e4SLinus Torvalds 		break;
27071da177e4SLinus Torvalds 
27081da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
27091da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
27101da177e4SLinus Torvalds 		break;
27111da177e4SLinus Torvalds 
2712a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
2713a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
271421d9e30eSMarcel Holtmann 		break;
271521d9e30eSMarcel Holtmann 
27161da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
27171da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
27181da177e4SLinus Torvalds 		break;
27191da177e4SLinus Torvalds 
27201da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
27211da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
27221da177e4SLinus Torvalds 		break;
27231da177e4SLinus Torvalds 
27241da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
27251da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
27261da177e4SLinus Torvalds 		break;
27271da177e4SLinus Torvalds 
2728a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
2729a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
2730a9de9248SMarcel Holtmann 		break;
2731a9de9248SMarcel Holtmann 
27321da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
27331da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
27341da177e4SLinus Torvalds 		break;
27351da177e4SLinus Torvalds 
2736a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
2737a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
2738a9de9248SMarcel Holtmann 		break;
2739a9de9248SMarcel Holtmann 
2740a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
2741a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
2742a9de9248SMarcel Holtmann 		break;
2743a9de9248SMarcel Holtmann 
2744a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
2745a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
2746a9de9248SMarcel Holtmann 		break;
2747a9de9248SMarcel Holtmann 
2748a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
2749a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
2750a9de9248SMarcel Holtmann 		break;
2751a9de9248SMarcel Holtmann 
2752a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
2753a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
2754a9de9248SMarcel Holtmann 		break;
2755a9de9248SMarcel Holtmann 
2756a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
2757a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
2758a9de9248SMarcel Holtmann 		break;
2759a9de9248SMarcel Holtmann 
2760a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
2761a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
2762a9de9248SMarcel Holtmann 		break;
2763a9de9248SMarcel Holtmann 
2764a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
2765a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
2766a9de9248SMarcel Holtmann 		break;
2767a9de9248SMarcel Holtmann 
2768a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
2769a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
27701da177e4SLinus Torvalds 		break;
27711da177e4SLinus Torvalds 
27721da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
27731da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
27741da177e4SLinus Torvalds 		break;
27751da177e4SLinus Torvalds 
27761da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
27771da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
27781da177e4SLinus Torvalds 		break;
27791da177e4SLinus Torvalds 
27801da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
27811da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
27821da177e4SLinus Torvalds 		break;
27831da177e4SLinus Torvalds 
27841da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
27851da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
27861da177e4SLinus Torvalds 		break;
27871da177e4SLinus Torvalds 
2788a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
2789a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
2790a8746417SMarcel Holtmann 		break;
2791a8746417SMarcel Holtmann 
279285a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
279385a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
279485a1e930SMarcel Holtmann 		break;
279585a1e930SMarcel Holtmann 
2796a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
2797a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
2798a9de9248SMarcel Holtmann 		break;
2799a9de9248SMarcel Holtmann 
2800a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
2801a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
2802a9de9248SMarcel Holtmann 		break;
2803a9de9248SMarcel Holtmann 
2804a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
2805a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
2806a9de9248SMarcel Holtmann 		break;
2807a9de9248SMarcel Holtmann 
2808a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
2809a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
2810a9de9248SMarcel Holtmann 		break;
2811a9de9248SMarcel Holtmann 
281204837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
281304837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
281404837f64SMarcel Holtmann 		break;
281504837f64SMarcel Holtmann 
2816a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
2817a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
28181da177e4SLinus Torvalds 		break;
28191da177e4SLinus Torvalds 
28200493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
28210493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
28220493684eSMarcel Holtmann 		break;
28230493684eSMarcel Holtmann 
282403b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
282503b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
282603b555e1SJohan Hedberg 		break;
282703b555e1SJohan Hedberg 
2828a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
2829a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
2830a5c29683SJohan Hedberg 		break;
2831a5c29683SJohan Hedberg 
28320493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
28330493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
28340493684eSMarcel Holtmann 		break;
28350493684eSMarcel Holtmann 
283641a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
283741a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
283841a96212SMarcel Holtmann 		break;
283941a96212SMarcel Holtmann 
2840fcd89c09SVille Tervo 	case HCI_EV_LE_META:
2841fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
2842fcd89c09SVille Tervo 		break;
2843fcd89c09SVille Tervo 
28442763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
28452763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
28462763eda6SSzymon Janc 		break;
28472763eda6SSzymon Janc 
28481da177e4SLinus Torvalds 	default:
2849a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
28501da177e4SLinus Torvalds 		break;
28511da177e4SLinus Torvalds 	}
28521da177e4SLinus Torvalds 
28531da177e4SLinus Torvalds 	kfree_skb(skb);
28541da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
28551da177e4SLinus Torvalds }
28561da177e4SLinus Torvalds 
28571da177e4SLinus Torvalds /* Generate internal stack event */
28581da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
28591da177e4SLinus Torvalds {
28601da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
28611da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
28621da177e4SLinus Torvalds 	struct sk_buff *skb;
28631da177e4SLinus Torvalds 
28641da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
28651da177e4SLinus Torvalds 	if (!skb)
28661da177e4SLinus Torvalds 		return;
28671da177e4SLinus Torvalds 
28681da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
28691da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
28701da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
28711da177e4SLinus Torvalds 
28721da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
28731da177e4SLinus Torvalds 	ev->type = type;
28741da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
28751da177e4SLinus Torvalds 
2876576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
2877a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
2878576c7d85SMarcel Holtmann 
28790d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
28801da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
2881eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
28821da177e4SLinus Torvalds 	kfree_skb(skb);
28831da177e4SLinus Torvalds }
2884