xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 726b4ffc)
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 
48e6100a25SAndre Guedes static int enable_le;
49e6100a25SAndre Guedes 
501da177e4SLinus Torvalds /* Handle HCI Event packets */
511da177e4SLinus Torvalds 
52a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
531da177e4SLinus Torvalds {
54a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
551da177e4SLinus Torvalds 
56a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
571da177e4SLinus Torvalds 
58a9de9248SMarcel Holtmann 	if (status)
59a9de9248SMarcel Holtmann 		return;
601da177e4SLinus Torvalds 
61314b2381SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags) &&
62314b2381SJohan Hedberg 				test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
63314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 0);
64a9de9248SMarcel Holtmann 
6523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
66a9de9248SMarcel Holtmann 
67a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
681da177e4SLinus Torvalds }
696bd57416SMarcel Holtmann 
70a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
711da177e4SLinus Torvalds {
72a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
73a9de9248SMarcel Holtmann 
74a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
75a9de9248SMarcel Holtmann 
76a9de9248SMarcel Holtmann 	if (status)
77a9de9248SMarcel Holtmann 		return;
78a9de9248SMarcel Holtmann 
79314b2381SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags) &&
80314b2381SJohan Hedberg 				test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
81314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 0);
82a9de9248SMarcel Holtmann 
83a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
84a9de9248SMarcel Holtmann }
85a9de9248SMarcel Holtmann 
86a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
87a9de9248SMarcel Holtmann {
88a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
89a9de9248SMarcel Holtmann }
90a9de9248SMarcel Holtmann 
91a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
92a9de9248SMarcel Holtmann {
93a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
941da177e4SLinus Torvalds 	struct hci_conn *conn;
951da177e4SLinus Torvalds 
96a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
971da177e4SLinus Torvalds 
98a9de9248SMarcel Holtmann 	if (rp->status)
99a9de9248SMarcel Holtmann 		return;
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1021da177e4SLinus Torvalds 
103a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1041da177e4SLinus Torvalds 	if (conn) {
105a9de9248SMarcel Holtmann 		if (rp->role)
1061da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1071da177e4SLinus Torvalds 		else
1081da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1091da177e4SLinus Torvalds 	}
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
112a9de9248SMarcel Holtmann }
1131da177e4SLinus Torvalds 
114e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
115e4e8e37cSMarcel Holtmann {
116e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
117e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
118e4e8e37cSMarcel Holtmann 
119e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
120e4e8e37cSMarcel Holtmann 
121e4e8e37cSMarcel Holtmann 	if (rp->status)
122e4e8e37cSMarcel Holtmann 		return;
123e4e8e37cSMarcel Holtmann 
124e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
125e4e8e37cSMarcel Holtmann 
126e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
127e4e8e37cSMarcel Holtmann 	if (conn)
128e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
129e4e8e37cSMarcel Holtmann 
130e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
131e4e8e37cSMarcel Holtmann }
132e4e8e37cSMarcel Holtmann 
133a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
134a9de9248SMarcel Holtmann {
135a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
136a9de9248SMarcel Holtmann 	struct hci_conn *conn;
137a9de9248SMarcel Holtmann 	void *sent;
138a9de9248SMarcel Holtmann 
139a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
140a9de9248SMarcel Holtmann 
141a9de9248SMarcel Holtmann 	if (rp->status)
142a9de9248SMarcel Holtmann 		return;
143a9de9248SMarcel Holtmann 
144a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14504837f64SMarcel Holtmann 	if (!sent)
146a9de9248SMarcel Holtmann 		return;
14704837f64SMarcel Holtmann 
14804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14904837f64SMarcel Holtmann 
150a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
151e4e8e37cSMarcel Holtmann 	if (conn)
15283985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15304837f64SMarcel Holtmann 
15404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1551da177e4SLinus Torvalds }
1561da177e4SLinus Torvalds 
157e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
158e4e8e37cSMarcel Holtmann {
159e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
160e4e8e37cSMarcel Holtmann 
161e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
162e4e8e37cSMarcel Holtmann 
163e4e8e37cSMarcel Holtmann 	if (rp->status)
164e4e8e37cSMarcel Holtmann 		return;
165e4e8e37cSMarcel Holtmann 
166e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
167e4e8e37cSMarcel Holtmann }
168e4e8e37cSMarcel Holtmann 
169e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
170e4e8e37cSMarcel Holtmann {
171e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
172e4e8e37cSMarcel Holtmann 	void *sent;
173e4e8e37cSMarcel Holtmann 
174e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
175e4e8e37cSMarcel Holtmann 
176e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
177e4e8e37cSMarcel Holtmann 	if (!sent)
178e4e8e37cSMarcel Holtmann 		return;
179e4e8e37cSMarcel Holtmann 
180e4e8e37cSMarcel Holtmann 	if (!status)
181e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
182e4e8e37cSMarcel Holtmann 
18323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
184e4e8e37cSMarcel Holtmann }
185e4e8e37cSMarcel Holtmann 
186a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1871da177e4SLinus Torvalds {
188a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
189a9de9248SMarcel Holtmann 
190a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
191a9de9248SMarcel Holtmann 
19210572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19310572132SGustavo F. Padovan 
19423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
195a9de9248SMarcel Holtmann }
196a9de9248SMarcel Holtmann 
197a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
198a9de9248SMarcel Holtmann {
199a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2001da177e4SLinus Torvalds 	void *sent;
2011da177e4SLinus Torvalds 
202a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2031da177e4SLinus Torvalds 
204a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2051da177e4SLinus Torvalds 	if (!sent)
206a9de9248SMarcel Holtmann 		return;
2071da177e4SLinus Torvalds 
208b312b161SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
209b312b161SJohan Hedberg 		mgmt_set_local_name_complete(hdev->id, sent, status);
210b312b161SJohan Hedberg 
211b312b161SJohan Hedberg 	if (status)
212b312b161SJohan Hedberg 		return;
213b312b161SJohan Hedberg 
2141f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
215a9de9248SMarcel Holtmann }
216a9de9248SMarcel Holtmann 
217a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
218a9de9248SMarcel Holtmann {
219a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
220a9de9248SMarcel Holtmann 
221a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
222a9de9248SMarcel Holtmann 
223a9de9248SMarcel Holtmann 	if (rp->status)
224a9de9248SMarcel Holtmann 		return;
225a9de9248SMarcel Holtmann 
2261f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
227a9de9248SMarcel Holtmann }
228a9de9248SMarcel Holtmann 
229a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
230a9de9248SMarcel Holtmann {
231a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
232a9de9248SMarcel Holtmann 	void *sent;
233a9de9248SMarcel Holtmann 
234a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
235a9de9248SMarcel Holtmann 
236a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
237a9de9248SMarcel Holtmann 	if (!sent)
238a9de9248SMarcel Holtmann 		return;
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds 	if (!status) {
241a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
242a9de9248SMarcel Holtmann 
2431da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2441da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2451da177e4SLinus Torvalds 		else
2461da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2471da177e4SLinus Torvalds 	}
248a9de9248SMarcel Holtmann 
24923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
250a9de9248SMarcel Holtmann }
2511da177e4SLinus Torvalds 
252a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
253a9de9248SMarcel Holtmann {
254a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
255a9de9248SMarcel Holtmann 	void *sent;
256a9de9248SMarcel Holtmann 
257a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
258a9de9248SMarcel Holtmann 
259a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2601da177e4SLinus Torvalds 	if (!sent)
261a9de9248SMarcel Holtmann 		return;
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 	if (!status) {
264a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
265a9de9248SMarcel Holtmann 
2661da177e4SLinus Torvalds 		if (param)
2671da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2681da177e4SLinus Torvalds 		else
2691da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2701da177e4SLinus Torvalds 	}
271a9de9248SMarcel Holtmann 
27223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2731da177e4SLinus Torvalds }
2741da177e4SLinus Torvalds 
275a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
276a9de9248SMarcel Holtmann {
277a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
278a9de9248SMarcel Holtmann 	void *sent;
2791da177e4SLinus Torvalds 
280a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
281a9de9248SMarcel Holtmann 
282a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2831da177e4SLinus Torvalds 	if (!sent)
284a9de9248SMarcel Holtmann 		return;
2851da177e4SLinus Torvalds 
2861da177e4SLinus Torvalds 	if (!status) {
287a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
2889fbcbb45SJohan Hedberg 		int old_pscan, old_iscan;
289a9de9248SMarcel Holtmann 
2909fbcbb45SJohan Hedberg 		old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
2919fbcbb45SJohan Hedberg 		old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
292a9de9248SMarcel Holtmann 
29373f22f62SJohan Hedberg 		if (param & SCAN_INQUIRY) {
2941da177e4SLinus Torvalds 			set_bit(HCI_ISCAN, &hdev->flags);
2959fbcbb45SJohan Hedberg 			if (!old_iscan)
29673f22f62SJohan Hedberg 				mgmt_discoverable(hdev->id, 1);
2979fbcbb45SJohan Hedberg 		} else if (old_iscan)
29873f22f62SJohan Hedberg 			mgmt_discoverable(hdev->id, 0);
2991da177e4SLinus Torvalds 
3009fbcbb45SJohan Hedberg 		if (param & SCAN_PAGE) {
3011da177e4SLinus Torvalds 			set_bit(HCI_PSCAN, &hdev->flags);
3029fbcbb45SJohan Hedberg 			if (!old_pscan)
3039fbcbb45SJohan Hedberg 				mgmt_connectable(hdev->id, 1);
3049fbcbb45SJohan Hedberg 		} else if (old_pscan)
3059fbcbb45SJohan Hedberg 			mgmt_connectable(hdev->id, 0);
3061da177e4SLinus Torvalds 	}
307a9de9248SMarcel Holtmann 
30823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3091da177e4SLinus Torvalds }
3101da177e4SLinus Torvalds 
311a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
312a9de9248SMarcel Holtmann {
313a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
314a9de9248SMarcel Holtmann 
315a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
316a9de9248SMarcel Holtmann 
317a9de9248SMarcel Holtmann 	if (rp->status)
318a9de9248SMarcel Holtmann 		return;
319a9de9248SMarcel Holtmann 
320a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
321a9de9248SMarcel Holtmann 
322a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
323a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
324a9de9248SMarcel Holtmann }
325a9de9248SMarcel Holtmann 
326a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
327a9de9248SMarcel Holtmann {
328a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
329a9de9248SMarcel Holtmann 	void *sent;
330a9de9248SMarcel Holtmann 
331a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
332a9de9248SMarcel Holtmann 
333f383f275SMarcel Holtmann 	if (status)
334f383f275SMarcel Holtmann 		return;
335f383f275SMarcel Holtmann 
336a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
337a9de9248SMarcel Holtmann 	if (!sent)
338a9de9248SMarcel Holtmann 		return;
339a9de9248SMarcel Holtmann 
340a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
341a9de9248SMarcel Holtmann }
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
344a9de9248SMarcel Holtmann {
345a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
346a9de9248SMarcel Holtmann 	__u16 setting;
347a9de9248SMarcel Holtmann 
348a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
349a9de9248SMarcel Holtmann 
350a9de9248SMarcel Holtmann 	if (rp->status)
351a9de9248SMarcel Holtmann 		return;
352a9de9248SMarcel Holtmann 
353a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
354a9de9248SMarcel Holtmann 
355a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
356a9de9248SMarcel Holtmann 		return;
357a9de9248SMarcel Holtmann 
358a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
359a9de9248SMarcel Holtmann 
360a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
361a9de9248SMarcel Holtmann 
362a9de9248SMarcel Holtmann 	if (hdev->notify) {
363a9de9248SMarcel Holtmann 		tasklet_disable(&hdev->tx_task);
364a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
365a9de9248SMarcel Holtmann 		tasklet_enable(&hdev->tx_task);
366a9de9248SMarcel Holtmann 	}
367a9de9248SMarcel Holtmann }
368a9de9248SMarcel Holtmann 
369a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
370a9de9248SMarcel Holtmann {
371a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
372f383f275SMarcel Holtmann 	__u16 setting;
373a9de9248SMarcel Holtmann 	void *sent;
374a9de9248SMarcel Holtmann 
375a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
376a9de9248SMarcel Holtmann 
377f383f275SMarcel Holtmann 	if (status)
378f383f275SMarcel Holtmann 		return;
379f383f275SMarcel Holtmann 
380a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
381a9de9248SMarcel Holtmann 	if (!sent)
382a9de9248SMarcel Holtmann 		return;
383a9de9248SMarcel Holtmann 
384f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
3851da177e4SLinus Torvalds 
386f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
387f383f275SMarcel Holtmann 		return;
388f383f275SMarcel Holtmann 
3891da177e4SLinus Torvalds 	hdev->voice_setting = setting;
3901da177e4SLinus Torvalds 
391a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
3921da177e4SLinus Torvalds 
3931da177e4SLinus Torvalds 	if (hdev->notify) {
3941da177e4SLinus Torvalds 		tasklet_disable(&hdev->tx_task);
3951da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
3961da177e4SLinus Torvalds 		tasklet_enable(&hdev->tx_task);
3971da177e4SLinus Torvalds 	}
3981da177e4SLinus Torvalds }
3991da177e4SLinus Torvalds 
400a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4011da177e4SLinus Torvalds {
402a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4031da177e4SLinus Torvalds 
404a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4051da177e4SLinus Torvalds 
40623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4071143e5a6SMarcel Holtmann }
4081143e5a6SMarcel Holtmann 
409333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
410333140b5SMarcel Holtmann {
411333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
412333140b5SMarcel Holtmann 
413333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
414333140b5SMarcel Holtmann 
415333140b5SMarcel Holtmann 	if (rp->status)
416333140b5SMarcel Holtmann 		return;
417333140b5SMarcel Holtmann 
418333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
419333140b5SMarcel Holtmann }
420333140b5SMarcel Holtmann 
421333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
422333140b5SMarcel Holtmann {
423333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
424333140b5SMarcel Holtmann 	void *sent;
425333140b5SMarcel Holtmann 
426333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
427333140b5SMarcel Holtmann 
428333140b5SMarcel Holtmann 	if (status)
429333140b5SMarcel Holtmann 		return;
430333140b5SMarcel Holtmann 
431333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
432333140b5SMarcel Holtmann 	if (!sent)
433333140b5SMarcel Holtmann 		return;
434333140b5SMarcel Holtmann 
435333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
436333140b5SMarcel Holtmann }
437333140b5SMarcel Holtmann 
438d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
439d5859e22SJohan Hedberg {
440d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
441d5859e22SJohan Hedberg 		return 2;
442d5859e22SJohan Hedberg 
443d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
444d5859e22SJohan Hedberg 		return 1;
445d5859e22SJohan Hedberg 
446d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
447d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
448d5859e22SJohan Hedberg 		return 1;
449d5859e22SJohan Hedberg 
450d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
451d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
452d5859e22SJohan Hedberg 			return 1;
453d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
454d5859e22SJohan Hedberg 			return 1;
455d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
456d5859e22SJohan Hedberg 			return 1;
457d5859e22SJohan Hedberg 	}
458d5859e22SJohan Hedberg 
459d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
460d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
461d5859e22SJohan Hedberg 		return 1;
462d5859e22SJohan Hedberg 
463d5859e22SJohan Hedberg 	return 0;
464d5859e22SJohan Hedberg }
465d5859e22SJohan Hedberg 
466d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
467d5859e22SJohan Hedberg {
468d5859e22SJohan Hedberg 	u8 mode;
469d5859e22SJohan Hedberg 
470d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
471d5859e22SJohan Hedberg 
472d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
473d5859e22SJohan Hedberg }
474d5859e22SJohan Hedberg 
475d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
476d5859e22SJohan Hedberg {
477d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
478d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
479d5859e22SJohan Hedberg 	 * command otherwise */
480d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
481d5859e22SJohan Hedberg 
4826de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
4836de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
4846de6c18dSVille Tervo 	if (hdev->lmp_ver <= 1)
4856de6c18dSVille Tervo 		return;
4866de6c18dSVille Tervo 
487d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
488d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
489d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
490d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
491d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
492d5859e22SJohan Hedberg 
493d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
494d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
495d5859e22SJohan Hedberg 
496d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
497d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
498d5859e22SJohan Hedberg 
499d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
500d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
501d5859e22SJohan Hedberg 
502d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
503d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
504d5859e22SJohan Hedberg 
505d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
506d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
507d5859e22SJohan Hedberg 
508d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
509d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
510d5859e22SJohan Hedberg 
511d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
512d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
513d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
514d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
515d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
516d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
517d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
518d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
519d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
520d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
521d5859e22SJohan Hedberg 					 * Features Notification */
522d5859e22SJohan Hedberg 	}
523d5859e22SJohan Hedberg 
524d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
525d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
526d5859e22SJohan Hedberg 
527d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
528d5859e22SJohan Hedberg }
529d5859e22SJohan Hedberg 
530e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
531e6100a25SAndre Guedes {
532e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
533e6100a25SAndre Guedes 
534e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
535e6100a25SAndre Guedes 
536e6100a25SAndre Guedes 	if (enable_le) {
537e6100a25SAndre Guedes 		cp.le = 1;
538e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
539e6100a25SAndre Guedes 	}
540e6100a25SAndre Guedes 
541e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
542e6100a25SAndre Guedes }
543e6100a25SAndre Guedes 
544d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
545d5859e22SJohan Hedberg {
546d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
547d5859e22SJohan Hedberg 
548d5859e22SJohan Hedberg 	if (hdev->lmp_ver > 1)
549d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
550d5859e22SJohan Hedberg 
551d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
552d5859e22SJohan Hedberg 		u8 mode = 0x01;
553d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
554d5859e22SJohan Hedberg 	}
555d5859e22SJohan Hedberg 
556d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
557d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
558d5859e22SJohan Hedberg 
559d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
560d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
561971e3a4bSAndre Guedes 
562971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
563971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
564971e3a4bSAndre Guedes 
565971e3a4bSAndre Guedes 		cp.page = 0x01;
566971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
567971e3a4bSAndre Guedes 							sizeof(cp), &cp);
568971e3a4bSAndre Guedes 	}
569e6100a25SAndre Guedes 
570e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
571e6100a25SAndre Guedes 		hci_set_le_support(hdev);
572d5859e22SJohan Hedberg }
573d5859e22SJohan Hedberg 
574a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
575a9de9248SMarcel Holtmann {
576a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5771143e5a6SMarcel Holtmann 
578a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5791143e5a6SMarcel Holtmann 
580a9de9248SMarcel Holtmann 	if (rp->status)
581a9de9248SMarcel Holtmann 		return;
5821143e5a6SMarcel Holtmann 
583a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
584e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
585d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
586e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
587d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5881da177e4SLinus Torvalds 
589a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
590a9de9248SMarcel Holtmann 					hdev->manufacturer,
591a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
592d5859e22SJohan Hedberg 
593d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
594d5859e22SJohan Hedberg 		hci_setup(hdev);
595d5859e22SJohan Hedberg }
596d5859e22SJohan Hedberg 
597d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
598d5859e22SJohan Hedberg {
599d5859e22SJohan Hedberg 	u16 link_policy = 0;
600d5859e22SJohan Hedberg 
601d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
602d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
603d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
604d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
605d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
606d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
607d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
608d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
609d5859e22SJohan Hedberg 
610d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
611d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
612d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6131da177e4SLinus Torvalds }
6141da177e4SLinus Torvalds 
615a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
616a9de9248SMarcel Holtmann {
617a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
618a9de9248SMarcel Holtmann 
619a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
620a9de9248SMarcel Holtmann 
621a9de9248SMarcel Holtmann 	if (rp->status)
622d5859e22SJohan Hedberg 		goto done;
623a9de9248SMarcel Holtmann 
624a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
625d5859e22SJohan Hedberg 
626d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
627d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
628d5859e22SJohan Hedberg 
629d5859e22SJohan Hedberg done:
630d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
631a9de9248SMarcel Holtmann }
632a9de9248SMarcel Holtmann 
633a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
634a9de9248SMarcel Holtmann {
635a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
636a9de9248SMarcel Holtmann 
637a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
638a9de9248SMarcel Holtmann 
639a9de9248SMarcel Holtmann 	if (rp->status)
640a9de9248SMarcel Holtmann 		return;
641a9de9248SMarcel Holtmann 
642a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6431da177e4SLinus Torvalds 
6441da177e4SLinus Torvalds 	/* Adjust default settings according to features
6451da177e4SLinus Torvalds 	 * supported by device. */
646a9de9248SMarcel Holtmann 
6471da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6481da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6491da177e4SLinus Torvalds 
6501da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6511da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6521da177e4SLinus Torvalds 
6535b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6541da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6555b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6565b7f9909SMarcel Holtmann 	}
6571da177e4SLinus Torvalds 
6585b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6591da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6605b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6615b7f9909SMarcel Holtmann 	}
6625b7f9909SMarcel Holtmann 
6635b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6645b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6655b7f9909SMarcel Holtmann 
6665b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6675b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6685b7f9909SMarcel Holtmann 
6695b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6705b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6711da177e4SLinus Torvalds 
672efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
673efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
674efc7688bSMarcel Holtmann 
675efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
676efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
677efc7688bSMarcel Holtmann 
678efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
679efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
680efc7688bSMarcel Holtmann 
681a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
682a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
683a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
684a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
685a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
6861da177e4SLinus Torvalds }
6871da177e4SLinus Torvalds 
688971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
689971e3a4bSAndre Guedes 							struct sk_buff *skb)
690971e3a4bSAndre Guedes {
691971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
692971e3a4bSAndre Guedes 
693971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
694971e3a4bSAndre Guedes 
695971e3a4bSAndre Guedes 	if (rp->status)
696971e3a4bSAndre Guedes 		return;
697971e3a4bSAndre Guedes 
698971e3a4bSAndre Guedes 	memcpy(hdev->extfeatures, rp->features, 8);
699971e3a4bSAndre Guedes 
700971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
701971e3a4bSAndre Guedes }
702971e3a4bSAndre Guedes 
703a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
704a9de9248SMarcel Holtmann {
705a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
706a9de9248SMarcel Holtmann 
707a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
708a9de9248SMarcel Holtmann 
709a9de9248SMarcel Holtmann 	if (rp->status)
710a9de9248SMarcel Holtmann 		return;
711a9de9248SMarcel Holtmann 
712a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
713a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
714a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
715a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
716da1f5198SMarcel Holtmann 
717da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
718da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
719da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
720da1f5198SMarcel Holtmann 	}
721da1f5198SMarcel Holtmann 
722da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
723da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7241da177e4SLinus Torvalds 
725a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
726a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
727a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7281da177e4SLinus Torvalds }
7291da177e4SLinus Torvalds 
730a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
731a9de9248SMarcel Holtmann {
732a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7331da177e4SLinus Torvalds 
734a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
735a9de9248SMarcel Holtmann 
736a9de9248SMarcel Holtmann 	if (!rp->status)
737a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
738a9de9248SMarcel Holtmann 
73923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
74023bb5763SJohan Hedberg }
74123bb5763SJohan Hedberg 
74223bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
74323bb5763SJohan Hedberg {
74423bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
74523bb5763SJohan Hedberg 
74623bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
74723bb5763SJohan Hedberg 
74823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
7491da177e4SLinus Torvalds }
7501da177e4SLinus Torvalds 
751b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
752b0916ea0SJohan Hedberg 							struct sk_buff *skb)
753b0916ea0SJohan Hedberg {
754b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
755b0916ea0SJohan Hedberg 
756b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
757b0916ea0SJohan Hedberg 
758b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
759b0916ea0SJohan Hedberg }
760b0916ea0SJohan Hedberg 
761d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
762d5859e22SJohan Hedberg {
763d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
764d5859e22SJohan Hedberg 
765d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
766d5859e22SJohan Hedberg 
767d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
768d5859e22SJohan Hedberg }
769d5859e22SJohan Hedberg 
770d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
771d5859e22SJohan Hedberg 							struct sk_buff *skb)
772d5859e22SJohan Hedberg {
773d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
774d5859e22SJohan Hedberg 
775d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
776d5859e22SJohan Hedberg 
777d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
778d5859e22SJohan Hedberg }
779d5859e22SJohan Hedberg 
780d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
781d5859e22SJohan Hedberg 							struct sk_buff *skb)
782d5859e22SJohan Hedberg {
783d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
784d5859e22SJohan Hedberg 
785d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
786d5859e22SJohan Hedberg 
787d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
788d5859e22SJohan Hedberg }
789d5859e22SJohan Hedberg 
790d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
791d5859e22SJohan Hedberg {
792d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
793d5859e22SJohan Hedberg 
794d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
795d5859e22SJohan Hedberg 
796d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
797d5859e22SJohan Hedberg }
798d5859e22SJohan Hedberg 
799980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
800980e1a53SJohan Hedberg {
801980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
802980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
803980e1a53SJohan Hedberg 	struct hci_conn *conn;
804980e1a53SJohan Hedberg 
805980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
806980e1a53SJohan Hedberg 
807980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
808980e1a53SJohan Hedberg 		mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);
809980e1a53SJohan Hedberg 
810980e1a53SJohan Hedberg 	if (rp->status != 0)
811980e1a53SJohan Hedberg 		return;
812980e1a53SJohan Hedberg 
813980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
814980e1a53SJohan Hedberg 	if (!cp)
815980e1a53SJohan Hedberg 		return;
816980e1a53SJohan Hedberg 
817980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
818980e1a53SJohan Hedberg 	if (conn)
819980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
820980e1a53SJohan Hedberg }
821980e1a53SJohan Hedberg 
822980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
823980e1a53SJohan Hedberg {
824980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
825980e1a53SJohan Hedberg 
826980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
827980e1a53SJohan Hedberg 
828980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
829980e1a53SJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
830980e1a53SJohan Hedberg 								rp->status);
831980e1a53SJohan Hedberg }
8326ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8336ed58ec5SVille Tervo 				       struct sk_buff *skb)
8346ed58ec5SVille Tervo {
8356ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
8366ed58ec5SVille Tervo 
8376ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
8386ed58ec5SVille Tervo 
8396ed58ec5SVille Tervo 	if (rp->status)
8406ed58ec5SVille Tervo 		return;
8416ed58ec5SVille Tervo 
8426ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
8436ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8446ed58ec5SVille Tervo 
8456ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8466ed58ec5SVille Tervo 
8476ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8486ed58ec5SVille Tervo 
8496ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
8506ed58ec5SVille Tervo }
851980e1a53SJohan Hedberg 
852a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
853a5c29683SJohan Hedberg {
854a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
855a5c29683SJohan Hedberg 
856a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
857a5c29683SJohan Hedberg 
858a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
859a5c29683SJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr,
860a5c29683SJohan Hedberg 								rp->status);
861a5c29683SJohan Hedberg }
862a5c29683SJohan Hedberg 
863a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
864a5c29683SJohan Hedberg 							struct sk_buff *skb)
865a5c29683SJohan Hedberg {
866a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
867a5c29683SJohan Hedberg 
868a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
869a5c29683SJohan Hedberg 
870a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
871a5c29683SJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr,
872a5c29683SJohan Hedberg 								rp->status);
873a5c29683SJohan Hedberg }
874a5c29683SJohan Hedberg 
875c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
876c35938b2SSzymon Janc 							struct sk_buff *skb)
877c35938b2SSzymon Janc {
878c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
879c35938b2SSzymon Janc 
880c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
881c35938b2SSzymon Janc 
882c35938b2SSzymon Janc 	mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash,
883c35938b2SSzymon Janc 						rp->randomizer, rp->status);
884c35938b2SSzymon Janc }
885c35938b2SSzymon Janc 
886eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
887eb9d91f5SAndre Guedes 					struct sk_buff *skb)
888eb9d91f5SAndre Guedes {
889eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
890eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
891eb9d91f5SAndre Guedes 
892eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
893eb9d91f5SAndre Guedes 
894eb9d91f5SAndre Guedes 	if (status)
895eb9d91f5SAndre Guedes 		return;
896eb9d91f5SAndre Guedes 
897eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
898eb9d91f5SAndre Guedes 	if (!cp)
899eb9d91f5SAndre Guedes 		return;
900eb9d91f5SAndre Guedes 
901eb9d91f5SAndre Guedes 	hci_dev_lock(hdev);
902eb9d91f5SAndre Guedes 
90335815085SAndre Guedes 	if (cp->enable == 0x01) {
90435815085SAndre Guedes 		del_timer(&hdev->adv_timer);
905eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
90635815085SAndre Guedes 	} else if (cp->enable == 0x00) {
90735815085SAndre Guedes 		mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
90835815085SAndre Guedes 	}
909eb9d91f5SAndre Guedes 
910eb9d91f5SAndre Guedes 	hci_dev_unlock(hdev);
911eb9d91f5SAndre Guedes }
912eb9d91f5SAndre Guedes 
913a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
914a7a595f6SVinicius Costa Gomes {
915a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
916a7a595f6SVinicius Costa Gomes 
917a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
918a7a595f6SVinicius Costa Gomes 
919a7a595f6SVinicius Costa Gomes 	if (rp->status)
920a7a595f6SVinicius Costa Gomes 		return;
921a7a595f6SVinicius Costa Gomes 
922a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
923a7a595f6SVinicius Costa Gomes }
924a7a595f6SVinicius Costa Gomes 
925a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
926a7a595f6SVinicius Costa Gomes {
927a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
928a7a595f6SVinicius Costa Gomes 
929a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
930a7a595f6SVinicius Costa Gomes 
931a7a595f6SVinicius Costa Gomes 	if (rp->status)
932a7a595f6SVinicius Costa Gomes 		return;
933a7a595f6SVinicius Costa Gomes 
934a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
935a7a595f6SVinicius Costa Gomes }
936a7a595f6SVinicius Costa Gomes 
937f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
938f9b49306SAndre Guedes 							struct sk_buff *skb)
939f9b49306SAndre Guedes {
940f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
941f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
942f9b49306SAndre Guedes 
943f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
944f9b49306SAndre Guedes 
945f9b49306SAndre Guedes 	if (status)
946f9b49306SAndre Guedes 		return;
947f9b49306SAndre Guedes 
948f9b49306SAndre Guedes 	cp.page = 0x01;
949f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
950f9b49306SAndre Guedes }
951f9b49306SAndre Guedes 
952a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
953a9de9248SMarcel Holtmann {
954a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
955a9de9248SMarcel Holtmann 
956a9de9248SMarcel Holtmann 	if (status) {
95723bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
958a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
959314b2381SJohan Hedberg 		return;
960314b2381SJohan Hedberg 	}
961314b2381SJohan Hedberg 
962314b2381SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags) &&
963314b2381SJohan Hedberg 					!test_and_set_bit(HCI_INQUIRY,
964314b2381SJohan Hedberg 							&hdev->flags))
965314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 1);
966a9de9248SMarcel Holtmann }
967a9de9248SMarcel Holtmann 
9681da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
9691da177e4SLinus Torvalds {
970a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
9711da177e4SLinus Torvalds 	struct hci_conn *conn;
9721da177e4SLinus Torvalds 
973a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
974a9de9248SMarcel Holtmann 
975a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
9761da177e4SLinus Torvalds 	if (!cp)
9771da177e4SLinus Torvalds 		return;
9781da177e4SLinus Torvalds 
9791da177e4SLinus Torvalds 	hci_dev_lock(hdev);
9801da177e4SLinus Torvalds 
9811da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
9821da177e4SLinus Torvalds 
983a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
9841da177e4SLinus Torvalds 
9851da177e4SLinus Torvalds 	if (status) {
9861da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
9874c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
9881da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
9891da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
9901da177e4SLinus Torvalds 				hci_conn_del(conn);
9914c67bc74SMarcel Holtmann 			} else
9924c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
9931da177e4SLinus Torvalds 		}
9941da177e4SLinus Torvalds 	} else {
9951da177e4SLinus Torvalds 		if (!conn) {
9961da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
9971da177e4SLinus Torvalds 			if (conn) {
9981da177e4SLinus Torvalds 				conn->out = 1;
9991da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
10001da177e4SLinus Torvalds 			} else
1001893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
10021da177e4SLinus Torvalds 		}
10031da177e4SLinus Torvalds 	}
10041da177e4SLinus Torvalds 
10051da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10061da177e4SLinus Torvalds }
10071da177e4SLinus Torvalds 
1008a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
10091da177e4SLinus Torvalds {
1010a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
10111da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
10121da177e4SLinus Torvalds 	__u16 handle;
10131da177e4SLinus Torvalds 
1014b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1015b6a0dc82SMarcel Holtmann 
1016a9de9248SMarcel Holtmann 	if (!status)
1017a9de9248SMarcel Holtmann 		return;
1018a9de9248SMarcel Holtmann 
1019a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
10201da177e4SLinus Torvalds 	if (!cp)
1021a9de9248SMarcel Holtmann 		return;
10221da177e4SLinus Torvalds 
10231da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
10241da177e4SLinus Torvalds 
1025a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
10261da177e4SLinus Torvalds 
10271da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10281da177e4SLinus Torvalds 
10291da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
10305a08ecceSAndrei Emeltchenko 	if (acl) {
10315a08ecceSAndrei Emeltchenko 		sco = acl->link;
10325a08ecceSAndrei Emeltchenko 		if (sco) {
10331da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
10341da177e4SLinus Torvalds 
10351da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
10361da177e4SLinus Torvalds 			hci_conn_del(sco);
10371da177e4SLinus Torvalds 		}
10385a08ecceSAndrei Emeltchenko 	}
10391da177e4SLinus Torvalds 
10401da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10411da177e4SLinus Torvalds }
10421da177e4SLinus Torvalds 
1043f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1044f8558555SMarcel Holtmann {
1045f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1046f8558555SMarcel Holtmann 	struct hci_conn *conn;
1047f8558555SMarcel Holtmann 
1048f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1049f8558555SMarcel Holtmann 
1050f8558555SMarcel Holtmann 	if (!status)
1051f8558555SMarcel Holtmann 		return;
1052f8558555SMarcel Holtmann 
1053f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1054f8558555SMarcel Holtmann 	if (!cp)
1055f8558555SMarcel Holtmann 		return;
1056f8558555SMarcel Holtmann 
1057f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1058f8558555SMarcel Holtmann 
1059f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1060f8558555SMarcel Holtmann 	if (conn) {
1061f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1062f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1063f8558555SMarcel Holtmann 			hci_conn_put(conn);
1064f8558555SMarcel Holtmann 		}
1065f8558555SMarcel Holtmann 	}
1066f8558555SMarcel Holtmann 
1067f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1068f8558555SMarcel Holtmann }
1069f8558555SMarcel Holtmann 
1070f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1071f8558555SMarcel Holtmann {
1072f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1073f8558555SMarcel Holtmann 	struct hci_conn *conn;
1074f8558555SMarcel Holtmann 
1075f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1076f8558555SMarcel Holtmann 
1077f8558555SMarcel Holtmann 	if (!status)
1078f8558555SMarcel Holtmann 		return;
1079f8558555SMarcel Holtmann 
1080f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1081f8558555SMarcel Holtmann 	if (!cp)
1082f8558555SMarcel Holtmann 		return;
1083f8558555SMarcel Holtmann 
1084f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1085f8558555SMarcel Holtmann 
1086f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1087f8558555SMarcel Holtmann 	if (conn) {
1088f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1089f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1090f8558555SMarcel Holtmann 			hci_conn_put(conn);
1091f8558555SMarcel Holtmann 		}
1092f8558555SMarcel Holtmann 	}
1093f8558555SMarcel Holtmann 
1094f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1095f8558555SMarcel Holtmann }
1096f8558555SMarcel Holtmann 
1097127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1098392599b9SJohan Hedberg 							struct hci_conn *conn)
1099392599b9SJohan Hedberg {
1100392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1101392599b9SJohan Hedberg 		return 0;
1102392599b9SJohan Hedberg 
1103765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1104392599b9SJohan Hedberg 		return 0;
1105392599b9SJohan Hedberg 
1106392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1107392599b9SJohan Hedberg 	 * devices with sec_level HIGH */
1108392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1109765c2a96SJohan Hedberg 				conn->pending_sec_level != BT_SECURITY_HIGH)
1110392599b9SJohan Hedberg 		return 0;
1111392599b9SJohan Hedberg 
1112392599b9SJohan Hedberg 	return 1;
1113392599b9SJohan Hedberg }
1114392599b9SJohan Hedberg 
1115a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
11161da177e4SLinus Torvalds {
1117127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1118127178d2SJohan Hedberg 	struct hci_conn *conn;
1119127178d2SJohan Hedberg 
1120a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1121127178d2SJohan Hedberg 
1122127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1123127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1124127178d2SJohan Hedberg 	if (!status)
1125127178d2SJohan Hedberg 		return;
1126127178d2SJohan Hedberg 
1127127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1128127178d2SJohan Hedberg 	if (!cp)
1129127178d2SJohan Hedberg 		return;
1130127178d2SJohan Hedberg 
1131127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1132127178d2SJohan Hedberg 
1133127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
113479c6c70cSJohan Hedberg 	if (!conn)
113579c6c70cSJohan Hedberg 		goto unlock;
113679c6c70cSJohan Hedberg 
113779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
113879c6c70cSJohan Hedberg 		goto unlock;
113979c6c70cSJohan Hedberg 
114079c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1141127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1142127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1143127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1144127178d2SJohan Hedberg 	}
1145127178d2SJohan Hedberg 
114679c6c70cSJohan Hedberg unlock:
1147127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1148a9de9248SMarcel Holtmann }
11491da177e4SLinus Torvalds 
1150769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1151769be974SMarcel Holtmann {
1152769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1153769be974SMarcel Holtmann 	struct hci_conn *conn;
1154769be974SMarcel Holtmann 
1155769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1156769be974SMarcel Holtmann 
1157769be974SMarcel Holtmann 	if (!status)
1158769be974SMarcel Holtmann 		return;
1159769be974SMarcel Holtmann 
1160769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1161769be974SMarcel Holtmann 	if (!cp)
1162769be974SMarcel Holtmann 		return;
1163769be974SMarcel Holtmann 
1164769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1165769be974SMarcel Holtmann 
1166769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1167769be974SMarcel Holtmann 	if (conn) {
1168769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1169769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1170769be974SMarcel Holtmann 			hci_conn_put(conn);
1171769be974SMarcel Holtmann 		}
1172769be974SMarcel Holtmann 	}
1173769be974SMarcel Holtmann 
1174769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1175769be974SMarcel Holtmann }
1176769be974SMarcel Holtmann 
1177769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1178769be974SMarcel Holtmann {
1179769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1180769be974SMarcel Holtmann 	struct hci_conn *conn;
1181769be974SMarcel Holtmann 
1182769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1183769be974SMarcel Holtmann 
1184769be974SMarcel Holtmann 	if (!status)
1185769be974SMarcel Holtmann 		return;
1186769be974SMarcel Holtmann 
1187769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1188769be974SMarcel Holtmann 	if (!cp)
1189769be974SMarcel Holtmann 		return;
1190769be974SMarcel Holtmann 
1191769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1192769be974SMarcel Holtmann 
1193769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1194769be974SMarcel Holtmann 	if (conn) {
1195769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1196769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1197769be974SMarcel Holtmann 			hci_conn_put(conn);
1198769be974SMarcel Holtmann 		}
1199769be974SMarcel Holtmann 	}
1200769be974SMarcel Holtmann 
1201769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1202769be974SMarcel Holtmann }
1203769be974SMarcel Holtmann 
1204a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1205a9de9248SMarcel Holtmann {
1206b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1207b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1208b6a0dc82SMarcel Holtmann 	__u16 handle;
1209b6a0dc82SMarcel Holtmann 
1210a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1211b6a0dc82SMarcel Holtmann 
1212b6a0dc82SMarcel Holtmann 	if (!status)
1213b6a0dc82SMarcel Holtmann 		return;
1214b6a0dc82SMarcel Holtmann 
1215b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1216b6a0dc82SMarcel Holtmann 	if (!cp)
1217b6a0dc82SMarcel Holtmann 		return;
1218b6a0dc82SMarcel Holtmann 
1219b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1220b6a0dc82SMarcel Holtmann 
1221b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1222b6a0dc82SMarcel Holtmann 
1223b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1224b6a0dc82SMarcel Holtmann 
1225b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12265a08ecceSAndrei Emeltchenko 	if (acl) {
12275a08ecceSAndrei Emeltchenko 		sco = acl->link;
12285a08ecceSAndrei Emeltchenko 		if (sco) {
1229b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1230b6a0dc82SMarcel Holtmann 
1231b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1232b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1233b6a0dc82SMarcel Holtmann 		}
12345a08ecceSAndrei Emeltchenko 	}
1235b6a0dc82SMarcel Holtmann 
1236b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1237a9de9248SMarcel Holtmann }
1238a9de9248SMarcel Holtmann 
1239a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1240a9de9248SMarcel Holtmann {
1241a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
124204837f64SMarcel Holtmann 	struct hci_conn *conn;
124304837f64SMarcel Holtmann 
1244a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1245a9de9248SMarcel Holtmann 
1246a9de9248SMarcel Holtmann 	if (!status)
1247a9de9248SMarcel Holtmann 		return;
1248a9de9248SMarcel Holtmann 
1249a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
125004837f64SMarcel Holtmann 	if (!cp)
1251a9de9248SMarcel Holtmann 		return;
125204837f64SMarcel Holtmann 
125304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
125404837f64SMarcel Holtmann 
125504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1256e73439d8SMarcel Holtmann 	if (conn) {
125704837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
125804837f64SMarcel Holtmann 
1259e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1260e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1261e73439d8SMarcel Holtmann 	}
1262e73439d8SMarcel Holtmann 
126304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
126404837f64SMarcel Holtmann }
126504837f64SMarcel Holtmann 
1266a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1267a9de9248SMarcel Holtmann {
1268a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
126904837f64SMarcel Holtmann 	struct hci_conn *conn;
127004837f64SMarcel Holtmann 
1271a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1272a9de9248SMarcel Holtmann 
1273a9de9248SMarcel Holtmann 	if (!status)
1274a9de9248SMarcel Holtmann 		return;
1275a9de9248SMarcel Holtmann 
1276a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
127704837f64SMarcel Holtmann 	if (!cp)
1278a9de9248SMarcel Holtmann 		return;
127904837f64SMarcel Holtmann 
128004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
128104837f64SMarcel Holtmann 
128204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1283e73439d8SMarcel Holtmann 	if (conn) {
128404837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
128504837f64SMarcel Holtmann 
1286e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1287e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1288e73439d8SMarcel Holtmann 	}
1289e73439d8SMarcel Holtmann 
129004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
129104837f64SMarcel Holtmann }
129204837f64SMarcel Holtmann 
1293fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1294fcd89c09SVille Tervo {
1295fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1296fcd89c09SVille Tervo 	struct hci_conn *conn;
1297fcd89c09SVille Tervo 
1298fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1299fcd89c09SVille Tervo 
1300fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1301fcd89c09SVille Tervo 	if (!cp)
1302fcd89c09SVille Tervo 		return;
1303fcd89c09SVille Tervo 
1304fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1305fcd89c09SVille Tervo 
1306fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1307fcd89c09SVille Tervo 
1308fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1309fcd89c09SVille Tervo 		conn);
1310fcd89c09SVille Tervo 
1311fcd89c09SVille Tervo 	if (status) {
1312fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1313fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1314fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1315fcd89c09SVille Tervo 			hci_conn_del(conn);
1316fcd89c09SVille Tervo 		}
1317fcd89c09SVille Tervo 	} else {
1318fcd89c09SVille Tervo 		if (!conn) {
1319fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
132029b7988aSAndre Guedes 			if (conn) {
132129b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1322fcd89c09SVille Tervo 				conn->out = 1;
132329b7988aSAndre Guedes 			} else {
1324fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1325fcd89c09SVille Tervo 			}
1326fcd89c09SVille Tervo 		}
132729b7988aSAndre Guedes 	}
1328fcd89c09SVille Tervo 
1329fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1330fcd89c09SVille Tervo }
1331fcd89c09SVille Tervo 
1332a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1333a7a595f6SVinicius Costa Gomes {
1334a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1335a7a595f6SVinicius Costa Gomes }
1336a7a595f6SVinicius Costa Gomes 
13371da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
13381da177e4SLinus Torvalds {
13391da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
13401da177e4SLinus Torvalds 
13411da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
13421da177e4SLinus Torvalds 
1343314b2381SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags) &&
1344314b2381SJohan Hedberg 				test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
1345314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 0);
1346a9de9248SMarcel Holtmann 
134723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
13486bd57416SMarcel Holtmann 
1349a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
13501da177e4SLinus Torvalds }
13511da177e4SLinus Torvalds 
13521da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
13531da177e4SLinus Torvalds {
135445bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1355a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
13561da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
13571da177e4SLinus Torvalds 
13581da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
13591da177e4SLinus Torvalds 
136045bb4bf0SMarcel Holtmann 	if (!num_rsp)
136145bb4bf0SMarcel Holtmann 		return;
136245bb4bf0SMarcel Holtmann 
13631da177e4SLinus Torvalds 	hci_dev_lock(hdev);
136445bb4bf0SMarcel Holtmann 
1365314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
1366314b2381SJohan Hedberg 
1367314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
1368314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
1369314b2381SJohan Hedberg 	}
1370314b2381SJohan Hedberg 
1371e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
13721da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
13731da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
13741da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
13751da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
13761da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
13771da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
13781da177e4SLinus Torvalds 		data.rssi		= 0x00;
137941a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
13801da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
1381e17acd40SJohan Hedberg 		mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0,
1382e17acd40SJohan Hedberg 									NULL);
13831da177e4SLinus Torvalds 	}
138445bb4bf0SMarcel Holtmann 
13851da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
13861da177e4SLinus Torvalds }
13871da177e4SLinus Torvalds 
1388a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
13891da177e4SLinus Torvalds {
1390a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1391a9de9248SMarcel Holtmann 	struct hci_conn *conn;
13921da177e4SLinus Torvalds 
1393a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
139445bb4bf0SMarcel Holtmann 
13951da177e4SLinus Torvalds 	hci_dev_lock(hdev);
139645bb4bf0SMarcel Holtmann 
1397a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
13989499237aSMarcel Holtmann 	if (!conn) {
13999499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
14009499237aSMarcel Holtmann 			goto unlock;
14019499237aSMarcel Holtmann 
14029499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1403a9de9248SMarcel Holtmann 		if (!conn)
1404a9de9248SMarcel Holtmann 			goto unlock;
140545bb4bf0SMarcel Holtmann 
14069499237aSMarcel Holtmann 		conn->type = SCO_LINK;
14079499237aSMarcel Holtmann 	}
14089499237aSMarcel Holtmann 
1409a9de9248SMarcel Holtmann 	if (!ev->status) {
1410a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1411769be974SMarcel Holtmann 
1412769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1413769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1414769be974SMarcel Holtmann 			hci_conn_hold(conn);
1415052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1416f7520543SJohan Hedberg 			mgmt_connected(hdev->id, &ev->bdaddr);
1417769be974SMarcel Holtmann 		} else
1418a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1419a9de9248SMarcel Holtmann 
14209eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
14217d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
14227d0db0a3SMarcel Holtmann 
1423a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1424a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1425a9de9248SMarcel Holtmann 
1426a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1427a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1428a9de9248SMarcel Holtmann 
1429a9de9248SMarcel Holtmann 		/* Get remote features */
1430a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1431a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1432a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1433769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1434769be974SMarcel Holtmann 							sizeof(cp), &cp);
143545bb4bf0SMarcel Holtmann 		}
1436a9de9248SMarcel Holtmann 
1437a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1438a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
1439a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1440a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1441a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1442a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1443a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1444a9de9248SMarcel Holtmann 		}
144517d5c04cSJohan Hedberg 	} else {
1446a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
144717d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
144817d5c04cSJohan Hedberg 			mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
144917d5c04cSJohan Hedberg 	}
145045bb4bf0SMarcel Holtmann 
1451e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1452e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
145345bb4bf0SMarcel Holtmann 
1454769be974SMarcel Holtmann 	if (ev->status) {
1455a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1456a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1457c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1458c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1459a9de9248SMarcel Holtmann 
1460a9de9248SMarcel Holtmann unlock:
14611da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1462a9de9248SMarcel Holtmann 
1463a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
14641da177e4SLinus Torvalds }
14651da177e4SLinus Torvalds 
14661da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
14671da177e4SLinus Torvalds {
1468a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
14691da177e4SLinus Torvalds 	int mask = hdev->link_mode;
14701da177e4SLinus Torvalds 
1471a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
14721da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
14731da177e4SLinus Torvalds 
14741da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
14751da177e4SLinus Torvalds 
1476138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1477138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
14781da177e4SLinus Torvalds 		/* Connection accepted */
1479c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
14801da177e4SLinus Torvalds 		struct hci_conn *conn;
14811da177e4SLinus Torvalds 
14821da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1483b6a0dc82SMarcel Holtmann 
1484cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1485cc11b9c1SAndrei Emeltchenko 		if (ie)
1486c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1487c7bdd502SMarcel Holtmann 
14881da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
14891da177e4SLinus Torvalds 		if (!conn) {
1490cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1491cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1492893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
14931da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
14941da177e4SLinus Torvalds 				return;
14951da177e4SLinus Torvalds 			}
14961da177e4SLinus Torvalds 		}
1497b6a0dc82SMarcel Holtmann 
14981da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
14991da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1500b6a0dc82SMarcel Holtmann 
15011da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
15021da177e4SLinus Torvalds 
1503b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1504b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1505b6a0dc82SMarcel Holtmann 
15061da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
15071da177e4SLinus Torvalds 
15081da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
15091da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
15101da177e4SLinus Torvalds 			else
15111da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
15121da177e4SLinus Torvalds 
1513b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1514b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1515b6a0dc82SMarcel Holtmann 		} else {
1516b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1517b6a0dc82SMarcel Holtmann 
1518b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1519a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1520b6a0dc82SMarcel Holtmann 
1521b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1522b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1523b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1524b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1525b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1526b6a0dc82SMarcel Holtmann 
1527b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1528b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1529b6a0dc82SMarcel Holtmann 		}
15301da177e4SLinus Torvalds 	} else {
15311da177e4SLinus Torvalds 		/* Connection rejected */
15321da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
15331da177e4SLinus Torvalds 
15341da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
15351da177e4SLinus Torvalds 		cp.reason = 0x0f;
1536a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
15371da177e4SLinus Torvalds 	}
15381da177e4SLinus Torvalds }
15391da177e4SLinus Torvalds 
15401da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15411da177e4SLinus Torvalds {
1542a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
154304837f64SMarcel Holtmann 	struct hci_conn *conn;
15441da177e4SLinus Torvalds 
15451da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
15461da177e4SLinus Torvalds 
15478962ee74SJohan Hedberg 	if (ev->status) {
15488962ee74SJohan Hedberg 		mgmt_disconnect_failed(hdev->id);
15491da177e4SLinus Torvalds 		return;
15508962ee74SJohan Hedberg 	}
15511da177e4SLinus Torvalds 
15521da177e4SLinus Torvalds 	hci_dev_lock(hdev);
15531da177e4SLinus Torvalds 
155404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1555f7520543SJohan Hedberg 	if (!conn)
1556f7520543SJohan Hedberg 		goto unlock;
1557f7520543SJohan Hedberg 
15581da177e4SLinus Torvalds 	conn->state = BT_CLOSED;
15597d0db0a3SMarcel Holtmann 
156083bc71b4SVinicius Costa Gomes 	if (conn->type == ACL_LINK || conn->type == LE_LINK)
1561f7520543SJohan Hedberg 		mgmt_disconnected(hdev->id, &conn->dst);
1562f7520543SJohan Hedberg 
15632950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
15641da177e4SLinus Torvalds 	hci_conn_del(conn);
15651da177e4SLinus Torvalds 
1566f7520543SJohan Hedberg unlock:
15671da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15681da177e4SLinus Torvalds }
15691da177e4SLinus Torvalds 
1570a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1571a9de9248SMarcel Holtmann {
1572a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1573a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1574a9de9248SMarcel Holtmann 
1575a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1576a9de9248SMarcel Holtmann 
1577a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1578a9de9248SMarcel Holtmann 
1579a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1580d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1581d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1582d7556e20SWaldemar Rymarkiewicz 
1583765c2a96SJohan Hedberg 	if (!ev->status) {
158419f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1585d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1586d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
158719f8def0SWaldemar Rymarkiewicz 		} else {
1588a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1589765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
159019f8def0SWaldemar Rymarkiewicz 		}
15912a611692SJohan Hedberg 	} else {
15922a611692SJohan Hedberg 		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
15932a611692SJohan Hedberg 	}
1594a9de9248SMarcel Holtmann 
1595a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
159619f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1597a9de9248SMarcel Holtmann 
1598f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1599d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1600f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1601f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1602f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1603d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1604d7556e20SWaldemar Rymarkiewicz 									&cp);
1605f8558555SMarcel Holtmann 		} else {
1606f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1607f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1608f8558555SMarcel Holtmann 			hci_conn_put(conn);
1609f8558555SMarcel Holtmann 		}
1610052b30b0SMarcel Holtmann 	} else {
1611a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1612a9de9248SMarcel Holtmann 
1613052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1614052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1615052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1616052b30b0SMarcel Holtmann 	}
1617052b30b0SMarcel Holtmann 
1618a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1619a9de9248SMarcel Holtmann 		if (!ev->status) {
1620a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1621f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1622f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1623d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1624d7556e20SWaldemar Rymarkiewicz 									&cp);
1625a9de9248SMarcel Holtmann 		} else {
1626a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1627a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1628a9de9248SMarcel Holtmann 		}
1629a9de9248SMarcel Holtmann 	}
1630a9de9248SMarcel Holtmann 
1631d7556e20SWaldemar Rymarkiewicz unlock:
1632a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1633a9de9248SMarcel Holtmann }
1634a9de9248SMarcel Holtmann 
1635a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1636a9de9248SMarcel Holtmann {
1637127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1638127178d2SJohan Hedberg 	struct hci_conn *conn;
1639127178d2SJohan Hedberg 
1640a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1641a9de9248SMarcel Holtmann 
1642a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1643127178d2SJohan Hedberg 
1644127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1645127178d2SJohan Hedberg 
1646a88a9652SJohan Hedberg 	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
1647a88a9652SJohan Hedberg 		mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name);
1648a88a9652SJohan Hedberg 
1649127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
165079c6c70cSJohan Hedberg 	if (!conn)
165179c6c70cSJohan Hedberg 		goto unlock;
165279c6c70cSJohan Hedberg 
165379c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
165479c6c70cSJohan Hedberg 		goto unlock;
165579c6c70cSJohan Hedberg 
165679c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1657127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1658127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1659127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1660127178d2SJohan Hedberg 	}
1661127178d2SJohan Hedberg 
166279c6c70cSJohan Hedberg unlock:
1663127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1664a9de9248SMarcel Holtmann }
1665a9de9248SMarcel Holtmann 
1666a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1667a9de9248SMarcel Holtmann {
1668a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1669a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1670a9de9248SMarcel Holtmann 
1671a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1672a9de9248SMarcel Holtmann 
1673a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1674a9de9248SMarcel Holtmann 
1675a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1676a9de9248SMarcel Holtmann 	if (conn) {
1677a9de9248SMarcel Holtmann 		if (!ev->status) {
1678ae293196SMarcel Holtmann 			if (ev->encrypt) {
1679ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1680ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1681a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1682da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1683ae293196SMarcel Holtmann 			} else
1684a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1685a9de9248SMarcel Holtmann 		}
1686a9de9248SMarcel Holtmann 
1687a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1688a9de9248SMarcel Holtmann 
1689f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1690f8558555SMarcel Holtmann 			if (!ev->status)
1691f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1692f8558555SMarcel Holtmann 
1693f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1694f8558555SMarcel Holtmann 			hci_conn_put(conn);
1695f8558555SMarcel Holtmann 		} else
1696a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1697a9de9248SMarcel Holtmann 	}
1698a9de9248SMarcel Holtmann 
1699a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1700a9de9248SMarcel Holtmann }
1701a9de9248SMarcel Holtmann 
1702a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1703a9de9248SMarcel Holtmann {
1704a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1705a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1706a9de9248SMarcel Holtmann 
1707a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1708a9de9248SMarcel Holtmann 
1709a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1710a9de9248SMarcel Holtmann 
1711a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1712a9de9248SMarcel Holtmann 	if (conn) {
1713a9de9248SMarcel Holtmann 		if (!ev->status)
1714a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1715a9de9248SMarcel Holtmann 
1716a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1717a9de9248SMarcel Holtmann 
1718a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1719a9de9248SMarcel Holtmann 	}
1720a9de9248SMarcel Holtmann 
1721a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1722a9de9248SMarcel Holtmann }
1723a9de9248SMarcel Holtmann 
1724a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1725a9de9248SMarcel Holtmann {
1726a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1727a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1728a9de9248SMarcel Holtmann 
1729a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1730a9de9248SMarcel Holtmann 
1731a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1732a9de9248SMarcel Holtmann 
1733a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1734ccd556feSJohan Hedberg 	if (!conn)
1735ccd556feSJohan Hedberg 		goto unlock;
1736ccd556feSJohan Hedberg 
1737769be974SMarcel Holtmann 	if (!ev->status)
1738a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1739a9de9248SMarcel Holtmann 
1740ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1741ccd556feSJohan Hedberg 		goto unlock;
1742ccd556feSJohan Hedberg 
1743ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1744769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1745769be974SMarcel Holtmann 		cp.handle = ev->handle;
1746769be974SMarcel Holtmann 		cp.page = 0x01;
1747ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1748769be974SMarcel Holtmann 							sizeof(cp), &cp);
1749392599b9SJohan Hedberg 		goto unlock;
1750392599b9SJohan Hedberg 	}
1751392599b9SJohan Hedberg 
1752127178d2SJohan Hedberg 	if (!ev->status) {
1753127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1754127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1755127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1756127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1757127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1758127178d2SJohan Hedberg 	}
1759392599b9SJohan Hedberg 
1760127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1761769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1762769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1763769be974SMarcel Holtmann 		hci_conn_put(conn);
1764769be974SMarcel Holtmann 	}
1765769be974SMarcel Holtmann 
1766ccd556feSJohan Hedberg unlock:
1767a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1768a9de9248SMarcel Holtmann }
1769a9de9248SMarcel Holtmann 
1770a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1771a9de9248SMarcel Holtmann {
1772a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1773a9de9248SMarcel Holtmann }
1774a9de9248SMarcel Holtmann 
1775a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1776a9de9248SMarcel Holtmann {
1777a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1778a9de9248SMarcel Holtmann }
1779a9de9248SMarcel Holtmann 
1780a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1781a9de9248SMarcel Holtmann {
1782a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1783a9de9248SMarcel Holtmann 	__u16 opcode;
1784a9de9248SMarcel Holtmann 
1785a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1786a9de9248SMarcel Holtmann 
1787a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1788a9de9248SMarcel Holtmann 
1789a9de9248SMarcel Holtmann 	switch (opcode) {
1790a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1791a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1792a9de9248SMarcel Holtmann 		break;
1793a9de9248SMarcel Holtmann 
1794a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1795a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1796a9de9248SMarcel Holtmann 		break;
1797a9de9248SMarcel Holtmann 
1798a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1799a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1800a9de9248SMarcel Holtmann 		break;
1801a9de9248SMarcel Holtmann 
1802a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1803a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1804a9de9248SMarcel Holtmann 		break;
1805a9de9248SMarcel Holtmann 
1806e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1807e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1808e4e8e37cSMarcel Holtmann 		break;
1809e4e8e37cSMarcel Holtmann 
1810a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1811a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1812a9de9248SMarcel Holtmann 		break;
1813a9de9248SMarcel Holtmann 
1814e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1815e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1816e4e8e37cSMarcel Holtmann 		break;
1817e4e8e37cSMarcel Holtmann 
1818e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1819e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1820e4e8e37cSMarcel Holtmann 		break;
1821e4e8e37cSMarcel Holtmann 
1822a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1823a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1824a9de9248SMarcel Holtmann 		break;
1825a9de9248SMarcel Holtmann 
1826a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1827a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1828a9de9248SMarcel Holtmann 		break;
1829a9de9248SMarcel Holtmann 
1830a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1831a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1832a9de9248SMarcel Holtmann 		break;
1833a9de9248SMarcel Holtmann 
1834a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1835a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1836a9de9248SMarcel Holtmann 		break;
1837a9de9248SMarcel Holtmann 
1838a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1839a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1840a9de9248SMarcel Holtmann 		break;
1841a9de9248SMarcel Holtmann 
1842a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1843a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1844a9de9248SMarcel Holtmann 		break;
1845a9de9248SMarcel Holtmann 
1846a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1847a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1848a9de9248SMarcel Holtmann 		break;
1849a9de9248SMarcel Holtmann 
1850a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1851a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1852a9de9248SMarcel Holtmann 		break;
1853a9de9248SMarcel Holtmann 
1854a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1855a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1856a9de9248SMarcel Holtmann 		break;
1857a9de9248SMarcel Holtmann 
1858a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1859a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1860a9de9248SMarcel Holtmann 		break;
1861a9de9248SMarcel Holtmann 
1862a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1863a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1864a9de9248SMarcel Holtmann 		break;
1865a9de9248SMarcel Holtmann 
1866333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1867333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1868333140b5SMarcel Holtmann 		break;
1869333140b5SMarcel Holtmann 
1870333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1871333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1872333140b5SMarcel Holtmann 		break;
1873333140b5SMarcel Holtmann 
1874a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1875a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1876a9de9248SMarcel Holtmann 		break;
1877a9de9248SMarcel Holtmann 
1878a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1879a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1880a9de9248SMarcel Holtmann 		break;
1881a9de9248SMarcel Holtmann 
1882a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1883a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1884a9de9248SMarcel Holtmann 		break;
1885a9de9248SMarcel Holtmann 
1886971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
1887971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
1888971e3a4bSAndre Guedes 		break;
1889971e3a4bSAndre Guedes 
1890a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
1891a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
1892a9de9248SMarcel Holtmann 		break;
1893a9de9248SMarcel Holtmann 
1894a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
1895a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
1896a9de9248SMarcel Holtmann 		break;
1897a9de9248SMarcel Holtmann 
189823bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
189923bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
190023bb5763SJohan Hedberg 		break;
190123bb5763SJohan Hedberg 
1902b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
1903b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
1904b0916ea0SJohan Hedberg 		break;
1905b0916ea0SJohan Hedberg 
1906d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
1907d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
1908d5859e22SJohan Hedberg 		break;
1909d5859e22SJohan Hedberg 
1910d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
1911d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
1912d5859e22SJohan Hedberg 		break;
1913d5859e22SJohan Hedberg 
1914d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
1915d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
1916d5859e22SJohan Hedberg 		break;
1917d5859e22SJohan Hedberg 
1918d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
1919d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
1920d5859e22SJohan Hedberg 		break;
1921d5859e22SJohan Hedberg 
1922980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
1923980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
1924980e1a53SJohan Hedberg 		break;
1925980e1a53SJohan Hedberg 
1926980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
1927980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
1928980e1a53SJohan Hedberg 		break;
1929980e1a53SJohan Hedberg 
1930c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
1931c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
1932c35938b2SSzymon Janc 		break;
1933c35938b2SSzymon Janc 
19346ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
19356ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
19366ed58ec5SVille Tervo 		break;
19376ed58ec5SVille Tervo 
1938a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
1939a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
1940a5c29683SJohan Hedberg 		break;
1941a5c29683SJohan Hedberg 
1942a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
1943a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
1944a5c29683SJohan Hedberg 		break;
1945a5c29683SJohan Hedberg 
1946eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
1947eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
1948eb9d91f5SAndre Guedes 		break;
1949eb9d91f5SAndre Guedes 
1950a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
1951a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
1952a7a595f6SVinicius Costa Gomes 		break;
1953a7a595f6SVinicius Costa Gomes 
1954a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
1955a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
1956a7a595f6SVinicius Costa Gomes 		break;
1957a7a595f6SVinicius Costa Gomes 
1958f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
1959f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
1960f9b49306SAndre Guedes 		break;
1961f9b49306SAndre Guedes 
1962a9de9248SMarcel Holtmann 	default:
1963a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1964a9de9248SMarcel Holtmann 		break;
1965a9de9248SMarcel Holtmann 	}
1966a9de9248SMarcel Holtmann 
19676bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
19686bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
19696bd32326SVille Tervo 
1970a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1971a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1972a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1973c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
1974a9de9248SMarcel Holtmann 	}
1975a9de9248SMarcel Holtmann }
1976a9de9248SMarcel Holtmann 
1977a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1978a9de9248SMarcel Holtmann {
1979a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
1980a9de9248SMarcel Holtmann 	__u16 opcode;
1981a9de9248SMarcel Holtmann 
1982a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1983a9de9248SMarcel Holtmann 
1984a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1985a9de9248SMarcel Holtmann 
1986a9de9248SMarcel Holtmann 	switch (opcode) {
1987a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
1988a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
1989a9de9248SMarcel Holtmann 		break;
1990a9de9248SMarcel Holtmann 
1991a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
1992a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
1993a9de9248SMarcel Holtmann 		break;
1994a9de9248SMarcel Holtmann 
1995a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
1996a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
1997a9de9248SMarcel Holtmann 		break;
1998a9de9248SMarcel Holtmann 
1999f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2000f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2001f8558555SMarcel Holtmann 		break;
2002f8558555SMarcel Holtmann 
2003f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2004f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2005f8558555SMarcel Holtmann 		break;
2006f8558555SMarcel Holtmann 
2007a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2008a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2009a9de9248SMarcel Holtmann 		break;
2010a9de9248SMarcel Holtmann 
2011769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2012769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2013769be974SMarcel Holtmann 		break;
2014769be974SMarcel Holtmann 
2015769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2016769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2017769be974SMarcel Holtmann 		break;
2018769be974SMarcel Holtmann 
2019a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2020a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2021a9de9248SMarcel Holtmann 		break;
2022a9de9248SMarcel Holtmann 
2023a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2024a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2025a9de9248SMarcel Holtmann 		break;
2026a9de9248SMarcel Holtmann 
2027a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2028a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2029a9de9248SMarcel Holtmann 		break;
2030a9de9248SMarcel Holtmann 
20318962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
20328962ee74SJohan Hedberg 		if (ev->status != 0)
20338962ee74SJohan Hedberg 			mgmt_disconnect_failed(hdev->id);
20348962ee74SJohan Hedberg 		break;
20358962ee74SJohan Hedberg 
2036fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2037fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2038fcd89c09SVille Tervo 		break;
2039fcd89c09SVille Tervo 
2040a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2041a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2042a7a595f6SVinicius Costa Gomes 		break;
2043a7a595f6SVinicius Costa Gomes 
2044a9de9248SMarcel Holtmann 	default:
2045a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2046a9de9248SMarcel Holtmann 		break;
2047a9de9248SMarcel Holtmann 	}
2048a9de9248SMarcel Holtmann 
20496bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
20506bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
20516bd32326SVille Tervo 
205210572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2053a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2054a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2055c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2056a9de9248SMarcel Holtmann 	}
2057a9de9248SMarcel Holtmann }
2058a9de9248SMarcel Holtmann 
2059a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2060a9de9248SMarcel Holtmann {
2061a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2062a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2063a9de9248SMarcel Holtmann 
2064a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2065a9de9248SMarcel Holtmann 
2066a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2067a9de9248SMarcel Holtmann 
2068a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2069a9de9248SMarcel Holtmann 	if (conn) {
2070a9de9248SMarcel Holtmann 		if (!ev->status) {
2071a9de9248SMarcel Holtmann 			if (ev->role)
2072a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2073a9de9248SMarcel Holtmann 			else
2074a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2075a9de9248SMarcel Holtmann 		}
2076a9de9248SMarcel Holtmann 
2077a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2078a9de9248SMarcel Holtmann 
2079a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2080a9de9248SMarcel Holtmann 	}
2081a9de9248SMarcel Holtmann 
2082a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2083a9de9248SMarcel Holtmann }
2084a9de9248SMarcel Holtmann 
20851da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
20861da177e4SLinus Torvalds {
2087a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
20881ebb9252SMarcel Holtmann 	__le16 *ptr;
20891da177e4SLinus Torvalds 	int i;
20901da177e4SLinus Torvalds 
20911da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
20921da177e4SLinus Torvalds 
20931da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
20941da177e4SLinus Torvalds 
20951da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
20961da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
20971da177e4SLinus Torvalds 		return;
20981da177e4SLinus Torvalds 	}
20991da177e4SLinus Torvalds 
21001da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
21011da177e4SLinus Torvalds 
21021ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
21031da177e4SLinus Torvalds 		struct hci_conn *conn;
21041da177e4SLinus Torvalds 		__u16  handle, count;
21051da177e4SLinus Torvalds 
210683985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
210783985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
21081da177e4SLinus Torvalds 
21091da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
21101da177e4SLinus Torvalds 		if (conn) {
21111da177e4SLinus Torvalds 			conn->sent -= count;
21121da177e4SLinus Torvalds 
21135b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
211470f23020SAndrei Emeltchenko 				hdev->acl_cnt += count;
211570f23020SAndrei Emeltchenko 				if (hdev->acl_cnt > hdev->acl_pkts)
21161da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
21176ed58ec5SVille Tervo 			} else if (conn->type == LE_LINK) {
21186ed58ec5SVille Tervo 				if (hdev->le_pkts) {
21196ed58ec5SVille Tervo 					hdev->le_cnt += count;
21206ed58ec5SVille Tervo 					if (hdev->le_cnt > hdev->le_pkts)
21216ed58ec5SVille Tervo 						hdev->le_cnt = hdev->le_pkts;
21226ed58ec5SVille Tervo 				} else {
21236ed58ec5SVille Tervo 					hdev->acl_cnt += count;
21246ed58ec5SVille Tervo 					if (hdev->acl_cnt > hdev->acl_pkts)
21256ed58ec5SVille Tervo 						hdev->acl_cnt = hdev->acl_pkts;
21266ed58ec5SVille Tervo 				}
21275b7f9909SMarcel Holtmann 			} else {
212870f23020SAndrei Emeltchenko 				hdev->sco_cnt += count;
212970f23020SAndrei Emeltchenko 				if (hdev->sco_cnt > hdev->sco_pkts)
21305b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
21311da177e4SLinus Torvalds 			}
21321da177e4SLinus Torvalds 		}
21331da177e4SLinus Torvalds 	}
2134a9de9248SMarcel Holtmann 
2135c78ae283SMarcel Holtmann 	tasklet_schedule(&hdev->tx_task);
21361da177e4SLinus Torvalds 
21371da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
21381da177e4SLinus Torvalds }
21391da177e4SLinus Torvalds 
214004837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
21411da177e4SLinus Torvalds {
2142a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
214304837f64SMarcel Holtmann 	struct hci_conn *conn;
21441da177e4SLinus Torvalds 
21451da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
21461da177e4SLinus Torvalds 
21471da177e4SLinus Torvalds 	hci_dev_lock(hdev);
21481da177e4SLinus Torvalds 
214904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
215004837f64SMarcel Holtmann 	if (conn) {
215104837f64SMarcel Holtmann 		conn->mode = ev->mode;
215204837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
215304837f64SMarcel Holtmann 
215404837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
215504837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
215604837f64SMarcel Holtmann 				conn->power_save = 1;
215704837f64SMarcel Holtmann 			else
215804837f64SMarcel Holtmann 				conn->power_save = 0;
215904837f64SMarcel Holtmann 		}
2160e73439d8SMarcel Holtmann 
2161e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2162e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
216304837f64SMarcel Holtmann 	}
216404837f64SMarcel Holtmann 
216504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
216604837f64SMarcel Holtmann }
216704837f64SMarcel Holtmann 
21681da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
21691da177e4SLinus Torvalds {
2170052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2171052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2172052b30b0SMarcel Holtmann 
2173a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2174052b30b0SMarcel Holtmann 
2175052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2176052b30b0SMarcel Holtmann 
2177052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
21783d7a9d1cSMarcel Holtmann 	if (conn && conn->state == BT_CONNECTED) {
2179052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2180052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2181052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2182052b30b0SMarcel Holtmann 	}
2183052b30b0SMarcel Holtmann 
218403b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
218503b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
218603b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2187582fbe9eSJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->flags)) {
2188a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2189a770bb5aSWaldemar Rymarkiewicz 
2190a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2191a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2192a770bb5aSWaldemar Rymarkiewicz 		else
2193a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2194a770bb5aSWaldemar Rymarkiewicz 
2195a770bb5aSWaldemar Rymarkiewicz 		mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure);
2196a770bb5aSWaldemar Rymarkiewicz 	}
2197980e1a53SJohan Hedberg 
2198052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
21991da177e4SLinus Torvalds }
22001da177e4SLinus Torvalds 
22011da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
22021da177e4SLinus Torvalds {
220355ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
220455ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
220555ed8ca1SJohan Hedberg 	struct hci_conn *conn;
220655ed8ca1SJohan Hedberg 	struct link_key *key;
220755ed8ca1SJohan Hedberg 
2208a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
220955ed8ca1SJohan Hedberg 
221055ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
221155ed8ca1SJohan Hedberg 		return;
221255ed8ca1SJohan Hedberg 
221355ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
221455ed8ca1SJohan Hedberg 
221555ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
221655ed8ca1SJohan Hedberg 	if (!key) {
221755ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
221855ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
221955ed8ca1SJohan Hedberg 		goto not_found;
222055ed8ca1SJohan Hedberg 	}
222155ed8ca1SJohan Hedberg 
222255ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
222355ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
222455ed8ca1SJohan Hedberg 
2225b6020ba0SWaldemar Rymarkiewicz 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2226b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
222755ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
222855ed8ca1SJohan Hedberg 		goto not_found;
222955ed8ca1SJohan Hedberg 	}
223055ed8ca1SJohan Hedberg 
223155ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
223260b83f57SWaldemar Rymarkiewicz 	if (conn) {
223360b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
223460b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
223560b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
223655ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
223755ed8ca1SJohan Hedberg 			goto not_found;
223855ed8ca1SJohan Hedberg 		}
223955ed8ca1SJohan Hedberg 
224060b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
224160b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
224260b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
224360b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
224460b83f57SWaldemar Rymarkiewicz 			goto not_found;
224560b83f57SWaldemar Rymarkiewicz 		}
224660b83f57SWaldemar Rymarkiewicz 
224760b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
224860b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
224960b83f57SWaldemar Rymarkiewicz 	}
225060b83f57SWaldemar Rymarkiewicz 
225155ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
225255ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
225355ed8ca1SJohan Hedberg 
225455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
225555ed8ca1SJohan Hedberg 
225655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
225755ed8ca1SJohan Hedberg 
225855ed8ca1SJohan Hedberg 	return;
225955ed8ca1SJohan Hedberg 
226055ed8ca1SJohan Hedberg not_found:
226155ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
226255ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
22631da177e4SLinus Torvalds }
22641da177e4SLinus Torvalds 
22651da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
22661da177e4SLinus Torvalds {
2267052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2268052b30b0SMarcel Holtmann 	struct hci_conn *conn;
226955ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2270052b30b0SMarcel Holtmann 
2271a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2272052b30b0SMarcel Holtmann 
2273052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2274052b30b0SMarcel Holtmann 
2275052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2276052b30b0SMarcel Holtmann 	if (conn) {
2277052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2278052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2279980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
228013d39315SWaldemar Rymarkiewicz 
228113d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
228213d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
228313d39315SWaldemar Rymarkiewicz 
2284052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2285052b30b0SMarcel Holtmann 	}
2286052b30b0SMarcel Holtmann 
228755ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2288d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
228955ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
229055ed8ca1SJohan Hedberg 
2291052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
22921da177e4SLinus Torvalds }
22931da177e4SLinus Torvalds 
229404837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
229504837f64SMarcel Holtmann {
2296a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
229704837f64SMarcel Holtmann 	struct hci_conn *conn;
229804837f64SMarcel Holtmann 
229904837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
230004837f64SMarcel Holtmann 
230104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
230204837f64SMarcel Holtmann 
230304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
23041da177e4SLinus Torvalds 	if (conn && !ev->status) {
23051da177e4SLinus Torvalds 		struct inquiry_entry *ie;
23061da177e4SLinus Torvalds 
2307cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2308cc11b9c1SAndrei Emeltchenko 		if (ie) {
23091da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
23101da177e4SLinus Torvalds 			ie->timestamp = jiffies;
23111da177e4SLinus Torvalds 		}
23121da177e4SLinus Torvalds 	}
23131da177e4SLinus Torvalds 
23141da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
23151da177e4SLinus Torvalds }
23161da177e4SLinus Torvalds 
2317a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2318a8746417SMarcel Holtmann {
2319a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2320a8746417SMarcel Holtmann 	struct hci_conn *conn;
2321a8746417SMarcel Holtmann 
2322a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2323a8746417SMarcel Holtmann 
2324a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2325a8746417SMarcel Holtmann 
2326a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2327a8746417SMarcel Holtmann 	if (conn && !ev->status)
2328a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2329a8746417SMarcel Holtmann 
2330a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2331a8746417SMarcel Holtmann }
2332a8746417SMarcel Holtmann 
233385a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
233485a1e930SMarcel Holtmann {
2335a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
233685a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
233785a1e930SMarcel Holtmann 
233885a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
233985a1e930SMarcel Holtmann 
234085a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
234185a1e930SMarcel Holtmann 
2342cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2343cc11b9c1SAndrei Emeltchenko 	if (ie) {
234485a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
234585a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
234685a1e930SMarcel Holtmann 	}
234785a1e930SMarcel Holtmann 
234885a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
234985a1e930SMarcel Holtmann }
235085a1e930SMarcel Holtmann 
2351a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2352a9de9248SMarcel Holtmann {
2353a9de9248SMarcel Holtmann 	struct inquiry_data data;
2354a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2355a9de9248SMarcel Holtmann 
2356a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2357a9de9248SMarcel Holtmann 
2358a9de9248SMarcel Holtmann 	if (!num_rsp)
2359a9de9248SMarcel Holtmann 		return;
2360a9de9248SMarcel Holtmann 
2361a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2362a9de9248SMarcel Holtmann 
2363314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
2364314b2381SJohan Hedberg 
2365314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
2366314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
2367314b2381SJohan Hedberg 	}
2368314b2381SJohan Hedberg 
2369a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2370138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2371138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2372a9de9248SMarcel Holtmann 
2373e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2374a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2375a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2376a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2377a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2378a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2379a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2380a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
238141a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2382a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
2383e17acd40SJohan Hedberg 			mgmt_device_found(hdev->id, &info->bdaddr,
2384e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2385e17acd40SJohan Hedberg 						NULL);
2386a9de9248SMarcel Holtmann 		}
2387a9de9248SMarcel Holtmann 	} else {
2388a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2389a9de9248SMarcel Holtmann 
2390e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2391a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2392a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2393a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2394a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2395a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2396a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2397a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
239841a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2399a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
2400e17acd40SJohan Hedberg 			mgmt_device_found(hdev->id, &info->bdaddr,
2401e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2402e17acd40SJohan Hedberg 						NULL);
2403a9de9248SMarcel Holtmann 		}
2404a9de9248SMarcel Holtmann 	}
2405a9de9248SMarcel Holtmann 
2406a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2407a9de9248SMarcel Holtmann }
2408a9de9248SMarcel Holtmann 
2409a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2410a9de9248SMarcel Holtmann {
241141a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
241241a96212SMarcel Holtmann 	struct hci_conn *conn;
241341a96212SMarcel Holtmann 
2414a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
241541a96212SMarcel Holtmann 
241641a96212SMarcel Holtmann 	hci_dev_lock(hdev);
241741a96212SMarcel Holtmann 
241841a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2419ccd556feSJohan Hedberg 	if (!conn)
2420ccd556feSJohan Hedberg 		goto unlock;
2421ccd556feSJohan Hedberg 
2422769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
242341a96212SMarcel Holtmann 		struct inquiry_entry *ie;
242441a96212SMarcel Holtmann 
2425cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2426cc11b9c1SAndrei Emeltchenko 		if (ie)
242741a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
242841a96212SMarcel Holtmann 
242941a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
243041a96212SMarcel Holtmann 	}
243141a96212SMarcel Holtmann 
2432ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2433ccd556feSJohan Hedberg 		goto unlock;
2434ccd556feSJohan Hedberg 
2435127178d2SJohan Hedberg 	if (!ev->status) {
2436127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2437127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2438127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2439127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2440127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2441127178d2SJohan Hedberg 	}
2442392599b9SJohan Hedberg 
2443127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2444769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2445769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2446769be974SMarcel Holtmann 		hci_conn_put(conn);
2447769be974SMarcel Holtmann 	}
2448769be974SMarcel Holtmann 
2449ccd556feSJohan Hedberg unlock:
245041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2451a9de9248SMarcel Holtmann }
2452a9de9248SMarcel Holtmann 
2453a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2454a9de9248SMarcel Holtmann {
2455b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2456b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2457b6a0dc82SMarcel Holtmann 
2458b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2459b6a0dc82SMarcel Holtmann 
2460b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2461b6a0dc82SMarcel Holtmann 
2462b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
24639dc0a3afSMarcel Holtmann 	if (!conn) {
24649dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
24659dc0a3afSMarcel Holtmann 			goto unlock;
24669dc0a3afSMarcel Holtmann 
24679dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2468b6a0dc82SMarcel Holtmann 		if (!conn)
2469b6a0dc82SMarcel Holtmann 			goto unlock;
2470b6a0dc82SMarcel Holtmann 
24719dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
24729dc0a3afSMarcel Holtmann 	}
24739dc0a3afSMarcel Holtmann 
2474732547f9SMarcel Holtmann 	switch (ev->status) {
2475732547f9SMarcel Holtmann 	case 0x00:
2476732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2477732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2478732547f9SMarcel Holtmann 
24799eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2480732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2481732547f9SMarcel Holtmann 		break;
2482732547f9SMarcel Holtmann 
2483705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2484732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
24851038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2486732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2487732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2488efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2489efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2490efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2491efc7688bSMarcel Holtmann 			goto unlock;
2492efc7688bSMarcel Holtmann 		}
2493732547f9SMarcel Holtmann 		/* fall through */
2494efc7688bSMarcel Holtmann 
2495732547f9SMarcel Holtmann 	default:
2496b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2497732547f9SMarcel Holtmann 		break;
2498732547f9SMarcel Holtmann 	}
2499b6a0dc82SMarcel Holtmann 
2500b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2501b6a0dc82SMarcel Holtmann 	if (ev->status)
2502b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2503b6a0dc82SMarcel Holtmann 
2504b6a0dc82SMarcel Holtmann unlock:
2505b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2506a9de9248SMarcel Holtmann }
2507a9de9248SMarcel Holtmann 
2508a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2509a9de9248SMarcel Holtmann {
2510a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2511a9de9248SMarcel Holtmann }
2512a9de9248SMarcel Holtmann 
251304837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
251404837f64SMarcel Holtmann {
2515a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
251604837f64SMarcel Holtmann 
251704837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
251804837f64SMarcel Holtmann }
251904837f64SMarcel Holtmann 
2520a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2521a9de9248SMarcel Holtmann {
2522a9de9248SMarcel Holtmann 	struct inquiry_data data;
2523a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2524a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2525a9de9248SMarcel Holtmann 
2526a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2527a9de9248SMarcel Holtmann 
2528a9de9248SMarcel Holtmann 	if (!num_rsp)
2529a9de9248SMarcel Holtmann 		return;
2530a9de9248SMarcel Holtmann 
2531314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
2532314b2381SJohan Hedberg 
2533314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
2534314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
2535314b2381SJohan Hedberg 	}
2536314b2381SJohan Hedberg 
2537a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2538a9de9248SMarcel Holtmann 
2539e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2540a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2541a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2542a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2543a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2544a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2545a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2546a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
254741a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2548a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
2549e17acd40SJohan Hedberg 		mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class,
2550e17acd40SJohan Hedberg 						info->rssi, info->data);
2551a9de9248SMarcel Holtmann 	}
2552a9de9248SMarcel Holtmann 
2553a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2554a9de9248SMarcel Holtmann }
2555a9de9248SMarcel Holtmann 
255617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
255717fa4b9dSJohan Hedberg {
255817fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
255917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
256017fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
256117fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
256217fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
256317fa4b9dSJohan Hedberg 			return 0x02;
256417fa4b9dSJohan Hedberg 		else
256517fa4b9dSJohan Hedberg 			return 0x03;
256617fa4b9dSJohan Hedberg 	}
256717fa4b9dSJohan Hedberg 
256817fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
256917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
257058797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
257117fa4b9dSJohan Hedberg 
257217fa4b9dSJohan Hedberg 	return conn->auth_type;
257317fa4b9dSJohan Hedberg }
257417fa4b9dSJohan Hedberg 
25750493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25760493684eSMarcel Holtmann {
25770493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
25780493684eSMarcel Holtmann 	struct hci_conn *conn;
25790493684eSMarcel Holtmann 
25800493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
25810493684eSMarcel Holtmann 
25820493684eSMarcel Holtmann 	hci_dev_lock(hdev);
25830493684eSMarcel Holtmann 
25840493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
258503b555e1SJohan Hedberg 	if (!conn)
258603b555e1SJohan Hedberg 		goto unlock;
258703b555e1SJohan Hedberg 
25880493684eSMarcel Holtmann 	hci_conn_hold(conn);
25890493684eSMarcel Holtmann 
259003b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
259103b555e1SJohan Hedberg 		goto unlock;
259203b555e1SJohan Hedberg 
259303b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
259403b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
259517fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
259617fa4b9dSJohan Hedberg 
259717fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
259817fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
25997cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
26007cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
260117fa4b9dSJohan Hedberg 
2602ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2603ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2604ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2605ce85ee13SSzymon Janc 		else
2606ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2607ce85ee13SSzymon Janc 
260817fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
260917fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
261003b555e1SJohan Hedberg 	} else {
261103b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
261203b555e1SJohan Hedberg 
261303b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
2614be77159cSJohan Hedberg 		cp.reason = 0x18; /* Pairing not allowed */
261503b555e1SJohan Hedberg 
261603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
261703b555e1SJohan Hedberg 							sizeof(cp), &cp);
261803b555e1SJohan Hedberg 	}
261903b555e1SJohan Hedberg 
262003b555e1SJohan Hedberg unlock:
262103b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
262203b555e1SJohan Hedberg }
262303b555e1SJohan Hedberg 
262403b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
262503b555e1SJohan Hedberg {
262603b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
262703b555e1SJohan Hedberg 	struct hci_conn *conn;
262803b555e1SJohan Hedberg 
262903b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
263003b555e1SJohan Hedberg 
263103b555e1SJohan Hedberg 	hci_dev_lock(hdev);
263203b555e1SJohan Hedberg 
263303b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
263403b555e1SJohan Hedberg 	if (!conn)
263503b555e1SJohan Hedberg 		goto unlock;
263603b555e1SJohan Hedberg 
263703b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
263803b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
263903b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
264003b555e1SJohan Hedberg 
264103b555e1SJohan Hedberg unlock:
26420493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
26430493684eSMarcel Holtmann }
26440493684eSMarcel Holtmann 
2645a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2646a5c29683SJohan Hedberg 							struct sk_buff *skb)
2647a5c29683SJohan Hedberg {
2648a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
264955bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
26507a828908SJohan Hedberg 	struct hci_conn *conn;
2651a5c29683SJohan Hedberg 
2652a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
2653a5c29683SJohan Hedberg 
2654a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
2655a5c29683SJohan Hedberg 
26567a828908SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
26577a828908SJohan Hedberg 		goto unlock;
26587a828908SJohan Hedberg 
26597a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
26607a828908SJohan Hedberg 	if (!conn)
26617a828908SJohan Hedberg 		goto unlock;
26627a828908SJohan Hedberg 
26637a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
26647a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
26657a828908SJohan Hedberg 
26667a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
26677a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
26687a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
26697a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
26707a828908SJohan Hedberg 	 * bit set. */
26717a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
26727a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
26737a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
26747a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
26757a828908SJohan Hedberg 		goto unlock;
26767a828908SJohan Hedberg 	}
26777a828908SJohan Hedberg 
26787a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
26797a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
26807a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
268155bc1a37SJohan Hedberg 
268255bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
268355bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
268455bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
268555bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
268655bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
268755bc1a37SJohan Hedberg 			confirm_hint = 1;
268855bc1a37SJohan Hedberg 			goto confirm;
268955bc1a37SJohan Hedberg 		}
269055bc1a37SJohan Hedberg 
26919f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
26929f61656aSJohan Hedberg 						hdev->auto_accept_delay);
26939f61656aSJohan Hedberg 
26949f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
26959f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
26969f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
26979f61656aSJohan Hedberg 			goto unlock;
26989f61656aSJohan Hedberg 		}
26999f61656aSJohan Hedberg 
27007a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
27017a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
27027a828908SJohan Hedberg 		goto unlock;
27037a828908SJohan Hedberg 	}
27047a828908SJohan Hedberg 
270555bc1a37SJohan Hedberg confirm:
270655bc1a37SJohan Hedberg 	mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey,
270755bc1a37SJohan Hedberg 								confirm_hint);
2708a5c29683SJohan Hedberg 
27097a828908SJohan Hedberg unlock:
2710a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
2711a5c29683SJohan Hedberg }
2712a5c29683SJohan Hedberg 
27130493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
27140493684eSMarcel Holtmann {
27150493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
27160493684eSMarcel Holtmann 	struct hci_conn *conn;
27170493684eSMarcel Holtmann 
27180493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
27190493684eSMarcel Holtmann 
27200493684eSMarcel Holtmann 	hci_dev_lock(hdev);
27210493684eSMarcel Holtmann 
27220493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
27232a611692SJohan Hedberg 	if (!conn)
27242a611692SJohan Hedberg 		goto unlock;
27252a611692SJohan Hedberg 
27262a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
27272a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
27282a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
27292a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
27302a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
27312a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
27322a611692SJohan Hedberg 		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
27332a611692SJohan Hedberg 
27340493684eSMarcel Holtmann 	hci_conn_put(conn);
27350493684eSMarcel Holtmann 
27362a611692SJohan Hedberg unlock:
27370493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
27380493684eSMarcel Holtmann }
27390493684eSMarcel Holtmann 
274041a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
274141a96212SMarcel Holtmann {
274241a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
274341a96212SMarcel Holtmann 	struct inquiry_entry *ie;
274441a96212SMarcel Holtmann 
274541a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
274641a96212SMarcel Holtmann 
274741a96212SMarcel Holtmann 	hci_dev_lock(hdev);
274841a96212SMarcel Holtmann 
2749cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2750cc11b9c1SAndrei Emeltchenko 	if (ie)
275141a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
275241a96212SMarcel Holtmann 
275341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
275441a96212SMarcel Holtmann }
275541a96212SMarcel Holtmann 
27562763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
27572763eda6SSzymon Janc 							struct sk_buff *skb)
27582763eda6SSzymon Janc {
27592763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
27602763eda6SSzymon Janc 	struct oob_data *data;
27612763eda6SSzymon Janc 
27622763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
27632763eda6SSzymon Janc 
27642763eda6SSzymon Janc 	hci_dev_lock(hdev);
27652763eda6SSzymon Janc 
2766e1ba1f15SSzymon Janc 	if (!test_bit(HCI_MGMT, &hdev->flags))
2767e1ba1f15SSzymon Janc 		goto unlock;
2768e1ba1f15SSzymon Janc 
27692763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
27702763eda6SSzymon Janc 	if (data) {
27712763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
27722763eda6SSzymon Janc 
27732763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
27742763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
27752763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
27762763eda6SSzymon Janc 
27772763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
27782763eda6SSzymon Janc 									&cp);
27792763eda6SSzymon Janc 	} else {
27802763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
27812763eda6SSzymon Janc 
27822763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
27832763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
27842763eda6SSzymon Janc 									&cp);
27852763eda6SSzymon Janc 	}
27862763eda6SSzymon Janc 
2787e1ba1f15SSzymon Janc unlock:
27882763eda6SSzymon Janc 	hci_dev_unlock(hdev);
27892763eda6SSzymon Janc }
27902763eda6SSzymon Janc 
2791fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2792fcd89c09SVille Tervo {
2793fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2794fcd89c09SVille Tervo 	struct hci_conn *conn;
2795fcd89c09SVille Tervo 
2796fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
2797fcd89c09SVille Tervo 
2798fcd89c09SVille Tervo 	hci_dev_lock(hdev);
2799fcd89c09SVille Tervo 
2800fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2801b62f328bSVille Tervo 	if (!conn) {
2802b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2803b62f328bSVille Tervo 		if (!conn) {
2804b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
2805b62f328bSVille Tervo 			hci_dev_unlock(hdev);
2806b62f328bSVille Tervo 			return;
2807b62f328bSVille Tervo 		}
280829b7988aSAndre Guedes 
280929b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
2810b62f328bSVille Tervo 	}
2811fcd89c09SVille Tervo 
2812fcd89c09SVille Tervo 	if (ev->status) {
281383bc71b4SVinicius Costa Gomes 		mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
2814fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
2815fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
2816fcd89c09SVille Tervo 		hci_conn_del(conn);
2817fcd89c09SVille Tervo 		goto unlock;
2818fcd89c09SVille Tervo 	}
2819fcd89c09SVille Tervo 
282083bc71b4SVinicius Costa Gomes 	mgmt_connected(hdev->id, &ev->bdaddr);
282183bc71b4SVinicius Costa Gomes 
28227b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
2823fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
2824fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
2825fcd89c09SVille Tervo 
2826fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
2827fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
2828fcd89c09SVille Tervo 
2829fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
2830fcd89c09SVille Tervo 
2831fcd89c09SVille Tervo unlock:
2832fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
2833fcd89c09SVille Tervo }
2834fcd89c09SVille Tervo 
28359aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
28369aa04c91SAndre Guedes 						struct sk_buff *skb)
28379aa04c91SAndre Guedes {
28389aa04c91SAndre Guedes 	struct hci_ev_le_advertising_info *ev;
28399aa04c91SAndre Guedes 	u8 num_reports;
28409aa04c91SAndre Guedes 
28419aa04c91SAndre Guedes 	num_reports = skb->data[0];
28429aa04c91SAndre Guedes 	ev = (void *) &skb->data[1];
28439aa04c91SAndre Guedes 
28449aa04c91SAndre Guedes 	hci_dev_lock(hdev);
28459aa04c91SAndre Guedes 
28469aa04c91SAndre Guedes 	hci_add_adv_entry(hdev, ev);
28479aa04c91SAndre Guedes 
28489aa04c91SAndre Guedes 	while (--num_reports) {
28499aa04c91SAndre Guedes 		ev = (void *) (ev->data + ev->length + 1);
28509aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
28519aa04c91SAndre Guedes 	}
28529aa04c91SAndre Guedes 
28539aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
28549aa04c91SAndre Guedes }
28559aa04c91SAndre Guedes 
2856a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
2857a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
2858a7a595f6SVinicius Costa Gomes {
2859a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
2860a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
2861bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
2862a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
2863bea710feSVinicius Costa Gomes 	struct link_key *ltk;
2864a7a595f6SVinicius Costa Gomes 
2865a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
2866a7a595f6SVinicius Costa Gomes 
2867a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
2868a7a595f6SVinicius Costa Gomes 
2869a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2870bea710feSVinicius Costa Gomes 	if (conn == NULL)
2871bea710feSVinicius Costa Gomes 		goto not_found;
2872a7a595f6SVinicius Costa Gomes 
2873bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
2874bea710feSVinicius Costa Gomes 	if (ltk == NULL)
2875bea710feSVinicius Costa Gomes 		goto not_found;
2876bea710feSVinicius Costa Gomes 
2877bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
2878a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
2879726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
2880a7a595f6SVinicius Costa Gomes 
2881a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
2882a7a595f6SVinicius Costa Gomes 
2883a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
2884bea710feSVinicius Costa Gomes 
2885bea710feSVinicius Costa Gomes 	return;
2886bea710feSVinicius Costa Gomes 
2887bea710feSVinicius Costa Gomes not_found:
2888bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
2889bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
2890bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
2891a7a595f6SVinicius Costa Gomes }
2892a7a595f6SVinicius Costa Gomes 
2893fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2894fcd89c09SVille Tervo {
2895fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
2896fcd89c09SVille Tervo 
2897fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
2898fcd89c09SVille Tervo 
2899fcd89c09SVille Tervo 	switch (le_ev->subevent) {
2900fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
2901fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
2902fcd89c09SVille Tervo 		break;
2903fcd89c09SVille Tervo 
29049aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
29059aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
29069aa04c91SAndre Guedes 		break;
29079aa04c91SAndre Guedes 
2908a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
2909a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
2910a7a595f6SVinicius Costa Gomes 		break;
2911a7a595f6SVinicius Costa Gomes 
2912fcd89c09SVille Tervo 	default:
2913fcd89c09SVille Tervo 		break;
2914fcd89c09SVille Tervo 	}
2915fcd89c09SVille Tervo }
2916fcd89c09SVille Tervo 
29171da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
29181da177e4SLinus Torvalds {
2919a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
2920a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
29211da177e4SLinus Torvalds 
29221da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
29231da177e4SLinus Torvalds 
2924a9de9248SMarcel Holtmann 	switch (event) {
29251da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
29261da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
29271da177e4SLinus Torvalds 		break;
29281da177e4SLinus Torvalds 
29291da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
29301da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
29311da177e4SLinus Torvalds 		break;
29321da177e4SLinus Torvalds 
2933a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
2934a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
293521d9e30eSMarcel Holtmann 		break;
293621d9e30eSMarcel Holtmann 
29371da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
29381da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
29391da177e4SLinus Torvalds 		break;
29401da177e4SLinus Torvalds 
29411da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
29421da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
29431da177e4SLinus Torvalds 		break;
29441da177e4SLinus Torvalds 
29451da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
29461da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
29471da177e4SLinus Torvalds 		break;
29481da177e4SLinus Torvalds 
2949a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
2950a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
2951a9de9248SMarcel Holtmann 		break;
2952a9de9248SMarcel Holtmann 
29531da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
29541da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
29551da177e4SLinus Torvalds 		break;
29561da177e4SLinus Torvalds 
2957a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
2958a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
2959a9de9248SMarcel Holtmann 		break;
2960a9de9248SMarcel Holtmann 
2961a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
2962a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
2963a9de9248SMarcel Holtmann 		break;
2964a9de9248SMarcel Holtmann 
2965a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
2966a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
2967a9de9248SMarcel Holtmann 		break;
2968a9de9248SMarcel Holtmann 
2969a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
2970a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
2971a9de9248SMarcel Holtmann 		break;
2972a9de9248SMarcel Holtmann 
2973a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
2974a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
2975a9de9248SMarcel Holtmann 		break;
2976a9de9248SMarcel Holtmann 
2977a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
2978a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
2979a9de9248SMarcel Holtmann 		break;
2980a9de9248SMarcel Holtmann 
2981a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
2982a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
2983a9de9248SMarcel Holtmann 		break;
2984a9de9248SMarcel Holtmann 
2985a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
2986a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
2987a9de9248SMarcel Holtmann 		break;
2988a9de9248SMarcel Holtmann 
2989a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
2990a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
29911da177e4SLinus Torvalds 		break;
29921da177e4SLinus Torvalds 
29931da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
29941da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
29951da177e4SLinus Torvalds 		break;
29961da177e4SLinus Torvalds 
29971da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
29981da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
29991da177e4SLinus Torvalds 		break;
30001da177e4SLinus Torvalds 
30011da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
30021da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
30031da177e4SLinus Torvalds 		break;
30041da177e4SLinus Torvalds 
30051da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
30061da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
30071da177e4SLinus Torvalds 		break;
30081da177e4SLinus Torvalds 
3009a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3010a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3011a8746417SMarcel Holtmann 		break;
3012a8746417SMarcel Holtmann 
301385a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
301485a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
301585a1e930SMarcel Holtmann 		break;
301685a1e930SMarcel Holtmann 
3017a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3018a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3019a9de9248SMarcel Holtmann 		break;
3020a9de9248SMarcel Holtmann 
3021a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3022a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3023a9de9248SMarcel Holtmann 		break;
3024a9de9248SMarcel Holtmann 
3025a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3026a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3027a9de9248SMarcel Holtmann 		break;
3028a9de9248SMarcel Holtmann 
3029a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3030a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3031a9de9248SMarcel Holtmann 		break;
3032a9de9248SMarcel Holtmann 
303304837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
303404837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
303504837f64SMarcel Holtmann 		break;
303604837f64SMarcel Holtmann 
3037a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3038a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
30391da177e4SLinus Torvalds 		break;
30401da177e4SLinus Torvalds 
30410493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
30420493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
30430493684eSMarcel Holtmann 		break;
30440493684eSMarcel Holtmann 
304503b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
304603b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
304703b555e1SJohan Hedberg 		break;
304803b555e1SJohan Hedberg 
3049a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3050a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3051a5c29683SJohan Hedberg 		break;
3052a5c29683SJohan Hedberg 
30530493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
30540493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
30550493684eSMarcel Holtmann 		break;
30560493684eSMarcel Holtmann 
305741a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
305841a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
305941a96212SMarcel Holtmann 		break;
306041a96212SMarcel Holtmann 
3061fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3062fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3063fcd89c09SVille Tervo 		break;
3064fcd89c09SVille Tervo 
30652763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
30662763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
30672763eda6SSzymon Janc 		break;
30682763eda6SSzymon Janc 
30691da177e4SLinus Torvalds 	default:
3070a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
30711da177e4SLinus Torvalds 		break;
30721da177e4SLinus Torvalds 	}
30731da177e4SLinus Torvalds 
30741da177e4SLinus Torvalds 	kfree_skb(skb);
30751da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
30761da177e4SLinus Torvalds }
30771da177e4SLinus Torvalds 
30781da177e4SLinus Torvalds /* Generate internal stack event */
30791da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
30801da177e4SLinus Torvalds {
30811da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
30821da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
30831da177e4SLinus Torvalds 	struct sk_buff *skb;
30841da177e4SLinus Torvalds 
30851da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
30861da177e4SLinus Torvalds 	if (!skb)
30871da177e4SLinus Torvalds 		return;
30881da177e4SLinus Torvalds 
30891da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
30901da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
30911da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
30921da177e4SLinus Torvalds 
30931da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
30941da177e4SLinus Torvalds 	ev->type = type;
30951da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
30961da177e4SLinus Torvalds 
3097576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3098a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3099576c7d85SMarcel Holtmann 
31000d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
31011da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3102eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
31031da177e4SLinus Torvalds 	kfree_skb(skb);
31041da177e4SLinus Torvalds }
3105e6100a25SAndre Guedes 
3106e6100a25SAndre Guedes module_param(enable_le, bool, 0444);
3107e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3108