xref: /openbmc/linux/net/bluetooth/hci_event.c (revision a8f13c8c)
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 
612d20a26aSOliver Neukum 	if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) &&
622d20a26aSOliver Neukum 			test_bit(HCI_MGMT, &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 
792d20a26aSOliver Neukum 	if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) &&
802d20a26aSOliver Neukum 				test_bit(HCI_MGMT, &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 
90135815085SAndre Guedes 	if (cp->enable == 0x01) {
90235815085SAndre Guedes 		del_timer(&hdev->adv_timer);
903a8f13c8cSAndre Guedes 
904a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
905eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
906a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
90735815085SAndre Guedes 	} else if (cp->enable == 0x00) {
90835815085SAndre Guedes 		mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
90935815085SAndre Guedes 	}
910eb9d91f5SAndre Guedes }
911eb9d91f5SAndre Guedes 
912a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
913a7a595f6SVinicius Costa Gomes {
914a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
915a7a595f6SVinicius Costa Gomes 
916a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
917a7a595f6SVinicius Costa Gomes 
918a7a595f6SVinicius Costa Gomes 	if (rp->status)
919a7a595f6SVinicius Costa Gomes 		return;
920a7a595f6SVinicius Costa Gomes 
921a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
922a7a595f6SVinicius Costa Gomes }
923a7a595f6SVinicius Costa Gomes 
924a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
925a7a595f6SVinicius Costa Gomes {
926a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
927a7a595f6SVinicius Costa Gomes 
928a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
929a7a595f6SVinicius Costa Gomes 
930a7a595f6SVinicius Costa Gomes 	if (rp->status)
931a7a595f6SVinicius Costa Gomes 		return;
932a7a595f6SVinicius Costa Gomes 
933a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
934a7a595f6SVinicius Costa Gomes }
935a7a595f6SVinicius Costa Gomes 
936f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
937f9b49306SAndre Guedes 							struct sk_buff *skb)
938f9b49306SAndre Guedes {
939f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
940f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
941f9b49306SAndre Guedes 
942f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
943f9b49306SAndre Guedes 
944f9b49306SAndre Guedes 	if (status)
945f9b49306SAndre Guedes 		return;
946f9b49306SAndre Guedes 
947f9b49306SAndre Guedes 	cp.page = 0x01;
948f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
949f9b49306SAndre Guedes }
950f9b49306SAndre Guedes 
951a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
952a9de9248SMarcel Holtmann {
953a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
954a9de9248SMarcel Holtmann 
955a9de9248SMarcel Holtmann 	if (status) {
95623bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
957a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
958314b2381SJohan Hedberg 		return;
959314b2381SJohan Hedberg 	}
960314b2381SJohan Hedberg 
9612d20a26aSOliver Neukum 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags) &&
9622d20a26aSOliver Neukum 				test_bit(HCI_MGMT, &hdev->flags))
963314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 1);
964a9de9248SMarcel Holtmann }
965a9de9248SMarcel Holtmann 
9661da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
9671da177e4SLinus Torvalds {
968a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
9691da177e4SLinus Torvalds 	struct hci_conn *conn;
9701da177e4SLinus Torvalds 
971a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
972a9de9248SMarcel Holtmann 
973a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
9741da177e4SLinus Torvalds 	if (!cp)
9751da177e4SLinus Torvalds 		return;
9761da177e4SLinus Torvalds 
9771da177e4SLinus Torvalds 	hci_dev_lock(hdev);
9781da177e4SLinus Torvalds 
9791da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
9801da177e4SLinus Torvalds 
981a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
9821da177e4SLinus Torvalds 
9831da177e4SLinus Torvalds 	if (status) {
9841da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
9854c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
9861da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
9871da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
9881da177e4SLinus Torvalds 				hci_conn_del(conn);
9894c67bc74SMarcel Holtmann 			} else
9904c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
9911da177e4SLinus Torvalds 		}
9921da177e4SLinus Torvalds 	} else {
9931da177e4SLinus Torvalds 		if (!conn) {
9941da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
9951da177e4SLinus Torvalds 			if (conn) {
9961da177e4SLinus Torvalds 				conn->out = 1;
9971da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
9981da177e4SLinus Torvalds 			} else
999893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
10001da177e4SLinus Torvalds 		}
10011da177e4SLinus Torvalds 	}
10021da177e4SLinus Torvalds 
10031da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10041da177e4SLinus Torvalds }
10051da177e4SLinus Torvalds 
1006a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
10071da177e4SLinus Torvalds {
1008a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
10091da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
10101da177e4SLinus Torvalds 	__u16 handle;
10111da177e4SLinus Torvalds 
1012b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1013b6a0dc82SMarcel Holtmann 
1014a9de9248SMarcel Holtmann 	if (!status)
1015a9de9248SMarcel Holtmann 		return;
1016a9de9248SMarcel Holtmann 
1017a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
10181da177e4SLinus Torvalds 	if (!cp)
1019a9de9248SMarcel Holtmann 		return;
10201da177e4SLinus Torvalds 
10211da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
10221da177e4SLinus Torvalds 
1023a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
10241da177e4SLinus Torvalds 
10251da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10261da177e4SLinus Torvalds 
10271da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
10285a08ecceSAndrei Emeltchenko 	if (acl) {
10295a08ecceSAndrei Emeltchenko 		sco = acl->link;
10305a08ecceSAndrei Emeltchenko 		if (sco) {
10311da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
10321da177e4SLinus Torvalds 
10331da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
10341da177e4SLinus Torvalds 			hci_conn_del(sco);
10351da177e4SLinus Torvalds 		}
10365a08ecceSAndrei Emeltchenko 	}
10371da177e4SLinus Torvalds 
10381da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10391da177e4SLinus Torvalds }
10401da177e4SLinus Torvalds 
1041f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1042f8558555SMarcel Holtmann {
1043f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1044f8558555SMarcel Holtmann 	struct hci_conn *conn;
1045f8558555SMarcel Holtmann 
1046f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1047f8558555SMarcel Holtmann 
1048f8558555SMarcel Holtmann 	if (!status)
1049f8558555SMarcel Holtmann 		return;
1050f8558555SMarcel Holtmann 
1051f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1052f8558555SMarcel Holtmann 	if (!cp)
1053f8558555SMarcel Holtmann 		return;
1054f8558555SMarcel Holtmann 
1055f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1056f8558555SMarcel Holtmann 
1057f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1058f8558555SMarcel Holtmann 	if (conn) {
1059f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1060f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1061f8558555SMarcel Holtmann 			hci_conn_put(conn);
1062f8558555SMarcel Holtmann 		}
1063f8558555SMarcel Holtmann 	}
1064f8558555SMarcel Holtmann 
1065f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1066f8558555SMarcel Holtmann }
1067f8558555SMarcel Holtmann 
1068f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1069f8558555SMarcel Holtmann {
1070f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1071f8558555SMarcel Holtmann 	struct hci_conn *conn;
1072f8558555SMarcel Holtmann 
1073f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1074f8558555SMarcel Holtmann 
1075f8558555SMarcel Holtmann 	if (!status)
1076f8558555SMarcel Holtmann 		return;
1077f8558555SMarcel Holtmann 
1078f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1079f8558555SMarcel Holtmann 	if (!cp)
1080f8558555SMarcel Holtmann 		return;
1081f8558555SMarcel Holtmann 
1082f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1083f8558555SMarcel Holtmann 
1084f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1085f8558555SMarcel Holtmann 	if (conn) {
1086f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1087f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1088f8558555SMarcel Holtmann 			hci_conn_put(conn);
1089f8558555SMarcel Holtmann 		}
1090f8558555SMarcel Holtmann 	}
1091f8558555SMarcel Holtmann 
1092f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1093f8558555SMarcel Holtmann }
1094f8558555SMarcel Holtmann 
1095127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1096392599b9SJohan Hedberg 							struct hci_conn *conn)
1097392599b9SJohan Hedberg {
1098392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1099392599b9SJohan Hedberg 		return 0;
1100392599b9SJohan Hedberg 
1101765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1102392599b9SJohan Hedberg 		return 0;
1103392599b9SJohan Hedberg 
1104392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1105e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1106392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1107e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1108e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1109392599b9SJohan Hedberg 		return 0;
1110392599b9SJohan Hedberg 
1111392599b9SJohan Hedberg 	return 1;
1112392599b9SJohan Hedberg }
1113392599b9SJohan Hedberg 
1114a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
11151da177e4SLinus Torvalds {
1116127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1117127178d2SJohan Hedberg 	struct hci_conn *conn;
1118127178d2SJohan Hedberg 
1119a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1120127178d2SJohan Hedberg 
1121127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1122127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1123127178d2SJohan Hedberg 	if (!status)
1124127178d2SJohan Hedberg 		return;
1125127178d2SJohan Hedberg 
1126127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1127127178d2SJohan Hedberg 	if (!cp)
1128127178d2SJohan Hedberg 		return;
1129127178d2SJohan Hedberg 
1130127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1131127178d2SJohan Hedberg 
1132127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
113379c6c70cSJohan Hedberg 	if (!conn)
113479c6c70cSJohan Hedberg 		goto unlock;
113579c6c70cSJohan Hedberg 
113679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
113779c6c70cSJohan Hedberg 		goto unlock;
113879c6c70cSJohan Hedberg 
113979c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1140127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1141127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1142127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1143127178d2SJohan Hedberg 	}
1144127178d2SJohan Hedberg 
114579c6c70cSJohan Hedberg unlock:
1146127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1147a9de9248SMarcel Holtmann }
11481da177e4SLinus Torvalds 
1149769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1150769be974SMarcel Holtmann {
1151769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1152769be974SMarcel Holtmann 	struct hci_conn *conn;
1153769be974SMarcel Holtmann 
1154769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1155769be974SMarcel Holtmann 
1156769be974SMarcel Holtmann 	if (!status)
1157769be974SMarcel Holtmann 		return;
1158769be974SMarcel Holtmann 
1159769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1160769be974SMarcel Holtmann 	if (!cp)
1161769be974SMarcel Holtmann 		return;
1162769be974SMarcel Holtmann 
1163769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1164769be974SMarcel Holtmann 
1165769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1166769be974SMarcel Holtmann 	if (conn) {
1167769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1168769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1169769be974SMarcel Holtmann 			hci_conn_put(conn);
1170769be974SMarcel Holtmann 		}
1171769be974SMarcel Holtmann 	}
1172769be974SMarcel Holtmann 
1173769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1174769be974SMarcel Holtmann }
1175769be974SMarcel Holtmann 
1176769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1177769be974SMarcel Holtmann {
1178769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1179769be974SMarcel Holtmann 	struct hci_conn *conn;
1180769be974SMarcel Holtmann 
1181769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1182769be974SMarcel Holtmann 
1183769be974SMarcel Holtmann 	if (!status)
1184769be974SMarcel Holtmann 		return;
1185769be974SMarcel Holtmann 
1186769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1187769be974SMarcel Holtmann 	if (!cp)
1188769be974SMarcel Holtmann 		return;
1189769be974SMarcel Holtmann 
1190769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1191769be974SMarcel Holtmann 
1192769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1193769be974SMarcel Holtmann 	if (conn) {
1194769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1195769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1196769be974SMarcel Holtmann 			hci_conn_put(conn);
1197769be974SMarcel Holtmann 		}
1198769be974SMarcel Holtmann 	}
1199769be974SMarcel Holtmann 
1200769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1201769be974SMarcel Holtmann }
1202769be974SMarcel Holtmann 
1203a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1204a9de9248SMarcel Holtmann {
1205b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1206b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1207b6a0dc82SMarcel Holtmann 	__u16 handle;
1208b6a0dc82SMarcel Holtmann 
1209a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1210b6a0dc82SMarcel Holtmann 
1211b6a0dc82SMarcel Holtmann 	if (!status)
1212b6a0dc82SMarcel Holtmann 		return;
1213b6a0dc82SMarcel Holtmann 
1214b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1215b6a0dc82SMarcel Holtmann 	if (!cp)
1216b6a0dc82SMarcel Holtmann 		return;
1217b6a0dc82SMarcel Holtmann 
1218b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1219b6a0dc82SMarcel Holtmann 
1220b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1221b6a0dc82SMarcel Holtmann 
1222b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1223b6a0dc82SMarcel Holtmann 
1224b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12255a08ecceSAndrei Emeltchenko 	if (acl) {
12265a08ecceSAndrei Emeltchenko 		sco = acl->link;
12275a08ecceSAndrei Emeltchenko 		if (sco) {
1228b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1229b6a0dc82SMarcel Holtmann 
1230b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1231b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1232b6a0dc82SMarcel Holtmann 		}
12335a08ecceSAndrei Emeltchenko 	}
1234b6a0dc82SMarcel Holtmann 
1235b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1236a9de9248SMarcel Holtmann }
1237a9de9248SMarcel Holtmann 
1238a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1239a9de9248SMarcel Holtmann {
1240a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
124104837f64SMarcel Holtmann 	struct hci_conn *conn;
124204837f64SMarcel Holtmann 
1243a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1244a9de9248SMarcel Holtmann 
1245a9de9248SMarcel Holtmann 	if (!status)
1246a9de9248SMarcel Holtmann 		return;
1247a9de9248SMarcel Holtmann 
1248a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
124904837f64SMarcel Holtmann 	if (!cp)
1250a9de9248SMarcel Holtmann 		return;
125104837f64SMarcel Holtmann 
125204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
125304837f64SMarcel Holtmann 
125404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1255e73439d8SMarcel Holtmann 	if (conn) {
125604837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
125704837f64SMarcel Holtmann 
1258e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1259e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1260e73439d8SMarcel Holtmann 	}
1261e73439d8SMarcel Holtmann 
126204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
126304837f64SMarcel Holtmann }
126404837f64SMarcel Holtmann 
1265a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1266a9de9248SMarcel Holtmann {
1267a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
126804837f64SMarcel Holtmann 	struct hci_conn *conn;
126904837f64SMarcel Holtmann 
1270a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1271a9de9248SMarcel Holtmann 
1272a9de9248SMarcel Holtmann 	if (!status)
1273a9de9248SMarcel Holtmann 		return;
1274a9de9248SMarcel Holtmann 
1275a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
127604837f64SMarcel Holtmann 	if (!cp)
1277a9de9248SMarcel Holtmann 		return;
127804837f64SMarcel Holtmann 
127904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
128004837f64SMarcel Holtmann 
128104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1282e73439d8SMarcel Holtmann 	if (conn) {
128304837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
128404837f64SMarcel Holtmann 
1285e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1286e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1287e73439d8SMarcel Holtmann 	}
1288e73439d8SMarcel Holtmann 
128904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
129004837f64SMarcel Holtmann }
129104837f64SMarcel Holtmann 
1292fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1293fcd89c09SVille Tervo {
1294fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1295fcd89c09SVille Tervo 	struct hci_conn *conn;
1296fcd89c09SVille Tervo 
1297fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1298fcd89c09SVille Tervo 
1299fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1300fcd89c09SVille Tervo 	if (!cp)
1301fcd89c09SVille Tervo 		return;
1302fcd89c09SVille Tervo 
1303fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1304fcd89c09SVille Tervo 
1305fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1306fcd89c09SVille Tervo 
1307fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1308fcd89c09SVille Tervo 		conn);
1309fcd89c09SVille Tervo 
1310fcd89c09SVille Tervo 	if (status) {
1311fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1312fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1313fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1314fcd89c09SVille Tervo 			hci_conn_del(conn);
1315fcd89c09SVille Tervo 		}
1316fcd89c09SVille Tervo 	} else {
1317fcd89c09SVille Tervo 		if (!conn) {
1318fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
131929b7988aSAndre Guedes 			if (conn) {
132029b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1321fcd89c09SVille Tervo 				conn->out = 1;
132229b7988aSAndre Guedes 			} else {
1323fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1324fcd89c09SVille Tervo 			}
1325fcd89c09SVille Tervo 		}
132629b7988aSAndre Guedes 	}
1327fcd89c09SVille Tervo 
1328fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1329fcd89c09SVille Tervo }
1330fcd89c09SVille Tervo 
1331a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1332a7a595f6SVinicius Costa Gomes {
1333a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1334a7a595f6SVinicius Costa Gomes }
1335a7a595f6SVinicius Costa Gomes 
13361da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
13371da177e4SLinus Torvalds {
13381da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
13391da177e4SLinus Torvalds 
13401da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
13411da177e4SLinus Torvalds 
13422d20a26aSOliver Neukum 	if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) &&
13432d20a26aSOliver Neukum 				test_bit(HCI_MGMT, &hdev->flags))
1344314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 0);
1345a9de9248SMarcel Holtmann 
134623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
13476bd57416SMarcel Holtmann 
1348a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
13491da177e4SLinus Torvalds }
13501da177e4SLinus Torvalds 
13511da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
13521da177e4SLinus Torvalds {
135345bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1354a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
13551da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
13561da177e4SLinus Torvalds 
13571da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
13581da177e4SLinus Torvalds 
135945bb4bf0SMarcel Holtmann 	if (!num_rsp)
136045bb4bf0SMarcel Holtmann 		return;
136145bb4bf0SMarcel Holtmann 
13621da177e4SLinus Torvalds 	hci_dev_lock(hdev);
136345bb4bf0SMarcel Holtmann 
1364314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
1365314b2381SJohan Hedberg 
1366314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
1367314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
1368314b2381SJohan Hedberg 	}
1369314b2381SJohan Hedberg 
1370e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
13711da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
13721da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
13731da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
13741da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
13751da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
13761da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
13771da177e4SLinus Torvalds 		data.rssi		= 0x00;
137841a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
13791da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
1380e17acd40SJohan Hedberg 		mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0,
1381e17acd40SJohan Hedberg 									NULL);
13821da177e4SLinus Torvalds 	}
138345bb4bf0SMarcel Holtmann 
13841da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
13851da177e4SLinus Torvalds }
13861da177e4SLinus Torvalds 
1387a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
13881da177e4SLinus Torvalds {
1389a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1390a9de9248SMarcel Holtmann 	struct hci_conn *conn;
13911da177e4SLinus Torvalds 
1392a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
139345bb4bf0SMarcel Holtmann 
13941da177e4SLinus Torvalds 	hci_dev_lock(hdev);
139545bb4bf0SMarcel Holtmann 
1396a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
13979499237aSMarcel Holtmann 	if (!conn) {
13989499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
13999499237aSMarcel Holtmann 			goto unlock;
14009499237aSMarcel Holtmann 
14019499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1402a9de9248SMarcel Holtmann 		if (!conn)
1403a9de9248SMarcel Holtmann 			goto unlock;
140445bb4bf0SMarcel Holtmann 
14059499237aSMarcel Holtmann 		conn->type = SCO_LINK;
14069499237aSMarcel Holtmann 	}
14079499237aSMarcel Holtmann 
1408a9de9248SMarcel Holtmann 	if (!ev->status) {
1409a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1410769be974SMarcel Holtmann 
1411769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1412769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1413769be974SMarcel Holtmann 			hci_conn_hold(conn);
1414052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1415cfafccf7SVinicius Costa Gomes 			mgmt_connected(hdev->id, &ev->bdaddr, conn->type);
1416769be974SMarcel Holtmann 		} else
1417a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1418a9de9248SMarcel Holtmann 
14199eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
14207d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
14217d0db0a3SMarcel Holtmann 
1422a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1423a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1424a9de9248SMarcel Holtmann 
1425a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1426a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1427a9de9248SMarcel Holtmann 
1428a9de9248SMarcel Holtmann 		/* Get remote features */
1429a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1430a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1431a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1432769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1433769be974SMarcel Holtmann 							sizeof(cp), &cp);
143445bb4bf0SMarcel Holtmann 		}
1435a9de9248SMarcel Holtmann 
1436a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1437a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
1438a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1439a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1440a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1441a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1442a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1443a9de9248SMarcel Holtmann 		}
144417d5c04cSJohan Hedberg 	} else {
1445a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
144617d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
144717d5c04cSJohan Hedberg 			mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
144817d5c04cSJohan Hedberg 	}
144945bb4bf0SMarcel Holtmann 
1450e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1451e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
145245bb4bf0SMarcel Holtmann 
1453769be974SMarcel Holtmann 	if (ev->status) {
1454a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1455a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1456c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1457c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1458a9de9248SMarcel Holtmann 
1459a9de9248SMarcel Holtmann unlock:
14601da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1461a9de9248SMarcel Holtmann 
1462a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
14631da177e4SLinus Torvalds }
14641da177e4SLinus Torvalds 
14651da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
14661da177e4SLinus Torvalds {
1467a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
14681da177e4SLinus Torvalds 	int mask = hdev->link_mode;
14691da177e4SLinus Torvalds 
1470a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
14711da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
14721da177e4SLinus Torvalds 
14731da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
14741da177e4SLinus Torvalds 
1475138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1476138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
14771da177e4SLinus Torvalds 		/* Connection accepted */
1478c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
14791da177e4SLinus Torvalds 		struct hci_conn *conn;
14801da177e4SLinus Torvalds 
14811da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1482b6a0dc82SMarcel Holtmann 
1483cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1484cc11b9c1SAndrei Emeltchenko 		if (ie)
1485c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1486c7bdd502SMarcel Holtmann 
14871da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
14881da177e4SLinus Torvalds 		if (!conn) {
1489cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1490cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1491893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
14921da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
14931da177e4SLinus Torvalds 				return;
14941da177e4SLinus Torvalds 			}
14951da177e4SLinus Torvalds 		}
1496b6a0dc82SMarcel Holtmann 
14971da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
14981da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1499b6a0dc82SMarcel Holtmann 
15001da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
15011da177e4SLinus Torvalds 
1502b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1503b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1504b6a0dc82SMarcel Holtmann 
15051da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
15061da177e4SLinus Torvalds 
15071da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
15081da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
15091da177e4SLinus Torvalds 			else
15101da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
15111da177e4SLinus Torvalds 
1512b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1513b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1514b6a0dc82SMarcel Holtmann 		} else {
1515b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1516b6a0dc82SMarcel Holtmann 
1517b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1518a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1519b6a0dc82SMarcel Holtmann 
1520b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1521b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1522b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1523b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1524b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1525b6a0dc82SMarcel Holtmann 
1526b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1527b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1528b6a0dc82SMarcel Holtmann 		}
15291da177e4SLinus Torvalds 	} else {
15301da177e4SLinus Torvalds 		/* Connection rejected */
15311da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
15321da177e4SLinus Torvalds 
15331da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
15341da177e4SLinus Torvalds 		cp.reason = 0x0f;
1535a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
15361da177e4SLinus Torvalds 	}
15371da177e4SLinus Torvalds }
15381da177e4SLinus Torvalds 
15391da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15401da177e4SLinus Torvalds {
1541a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
154204837f64SMarcel Holtmann 	struct hci_conn *conn;
15431da177e4SLinus Torvalds 
15441da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
15451da177e4SLinus Torvalds 
15468962ee74SJohan Hedberg 	if (ev->status) {
15478962ee74SJohan Hedberg 		mgmt_disconnect_failed(hdev->id);
15481da177e4SLinus Torvalds 		return;
15498962ee74SJohan Hedberg 	}
15501da177e4SLinus Torvalds 
15511da177e4SLinus Torvalds 	hci_dev_lock(hdev);
15521da177e4SLinus Torvalds 
155304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1554f7520543SJohan Hedberg 	if (!conn)
1555f7520543SJohan Hedberg 		goto unlock;
1556f7520543SJohan Hedberg 
15571da177e4SLinus Torvalds 	conn->state = BT_CLOSED;
15587d0db0a3SMarcel Holtmann 
155983bc71b4SVinicius Costa Gomes 	if (conn->type == ACL_LINK || conn->type == LE_LINK)
1560f7520543SJohan Hedberg 		mgmt_disconnected(hdev->id, &conn->dst);
1561f7520543SJohan Hedberg 
15622950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
15631da177e4SLinus Torvalds 	hci_conn_del(conn);
15641da177e4SLinus Torvalds 
1565f7520543SJohan Hedberg unlock:
15661da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15671da177e4SLinus Torvalds }
15681da177e4SLinus Torvalds 
1569a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1570a9de9248SMarcel Holtmann {
1571a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1572a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1573a9de9248SMarcel Holtmann 
1574a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1575a9de9248SMarcel Holtmann 
1576a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1577a9de9248SMarcel Holtmann 
1578a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1579d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1580d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1581d7556e20SWaldemar Rymarkiewicz 
1582765c2a96SJohan Hedberg 	if (!ev->status) {
158319f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1584d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1585d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
158619f8def0SWaldemar Rymarkiewicz 		} else {
1587a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1588765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
158919f8def0SWaldemar Rymarkiewicz 		}
15902a611692SJohan Hedberg 	} else {
15912a611692SJohan Hedberg 		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
15922a611692SJohan Hedberg 	}
1593a9de9248SMarcel Holtmann 
1594a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
159519f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1596a9de9248SMarcel Holtmann 
1597f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1598d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1599f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1600f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1601f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1602d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1603d7556e20SWaldemar Rymarkiewicz 									&cp);
1604f8558555SMarcel Holtmann 		} else {
1605f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1606f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1607f8558555SMarcel Holtmann 			hci_conn_put(conn);
1608f8558555SMarcel Holtmann 		}
1609052b30b0SMarcel Holtmann 	} else {
1610a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1611a9de9248SMarcel Holtmann 
1612052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1613052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1614052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1615052b30b0SMarcel Holtmann 	}
1616052b30b0SMarcel Holtmann 
1617a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1618a9de9248SMarcel Holtmann 		if (!ev->status) {
1619a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1620f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1621f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1622d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1623d7556e20SWaldemar Rymarkiewicz 									&cp);
1624a9de9248SMarcel Holtmann 		} else {
1625a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1626a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1627a9de9248SMarcel Holtmann 		}
1628a9de9248SMarcel Holtmann 	}
1629a9de9248SMarcel Holtmann 
1630d7556e20SWaldemar Rymarkiewicz unlock:
1631a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1632a9de9248SMarcel Holtmann }
1633a9de9248SMarcel Holtmann 
1634a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1635a9de9248SMarcel Holtmann {
1636127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1637127178d2SJohan Hedberg 	struct hci_conn *conn;
1638127178d2SJohan Hedberg 
1639a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1640a9de9248SMarcel Holtmann 
1641a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1642127178d2SJohan Hedberg 
1643127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1644127178d2SJohan Hedberg 
1645a88a9652SJohan Hedberg 	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
1646a88a9652SJohan Hedberg 		mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name);
1647a88a9652SJohan Hedberg 
1648127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
164979c6c70cSJohan Hedberg 	if (!conn)
165079c6c70cSJohan Hedberg 		goto unlock;
165179c6c70cSJohan Hedberg 
165279c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
165379c6c70cSJohan Hedberg 		goto unlock;
165479c6c70cSJohan Hedberg 
165579c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1656127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1657127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1658127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1659127178d2SJohan Hedberg 	}
1660127178d2SJohan Hedberg 
166179c6c70cSJohan Hedberg unlock:
1662127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1663a9de9248SMarcel Holtmann }
1664a9de9248SMarcel Holtmann 
1665a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1666a9de9248SMarcel Holtmann {
1667a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1668a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1669a9de9248SMarcel Holtmann 
1670a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1671a9de9248SMarcel Holtmann 
1672a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1673a9de9248SMarcel Holtmann 
1674a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1675a9de9248SMarcel Holtmann 	if (conn) {
1676a9de9248SMarcel Holtmann 		if (!ev->status) {
1677ae293196SMarcel Holtmann 			if (ev->encrypt) {
1678ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1679ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1680a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1681da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1682ae293196SMarcel Holtmann 			} else
1683a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1684a9de9248SMarcel Holtmann 		}
1685a9de9248SMarcel Holtmann 
1686a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1687a9de9248SMarcel Holtmann 
1688f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1689f8558555SMarcel Holtmann 			if (!ev->status)
1690f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1691f8558555SMarcel Holtmann 
1692f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1693f8558555SMarcel Holtmann 			hci_conn_put(conn);
1694f8558555SMarcel Holtmann 		} else
1695a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1696a9de9248SMarcel Holtmann 	}
1697a9de9248SMarcel Holtmann 
1698a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1699a9de9248SMarcel Holtmann }
1700a9de9248SMarcel Holtmann 
1701a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1702a9de9248SMarcel Holtmann {
1703a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1704a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1705a9de9248SMarcel Holtmann 
1706a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1707a9de9248SMarcel Holtmann 
1708a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1709a9de9248SMarcel Holtmann 
1710a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1711a9de9248SMarcel Holtmann 	if (conn) {
1712a9de9248SMarcel Holtmann 		if (!ev->status)
1713a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1714a9de9248SMarcel Holtmann 
1715a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1716a9de9248SMarcel Holtmann 
1717a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1718a9de9248SMarcel Holtmann 	}
1719a9de9248SMarcel Holtmann 
1720a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1721a9de9248SMarcel Holtmann }
1722a9de9248SMarcel Holtmann 
1723a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1724a9de9248SMarcel Holtmann {
1725a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1726a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1727a9de9248SMarcel Holtmann 
1728a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1729a9de9248SMarcel Holtmann 
1730a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1731a9de9248SMarcel Holtmann 
1732a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1733ccd556feSJohan Hedberg 	if (!conn)
1734ccd556feSJohan Hedberg 		goto unlock;
1735ccd556feSJohan Hedberg 
1736769be974SMarcel Holtmann 	if (!ev->status)
1737a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1738a9de9248SMarcel Holtmann 
1739ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1740ccd556feSJohan Hedberg 		goto unlock;
1741ccd556feSJohan Hedberg 
1742ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1743769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1744769be974SMarcel Holtmann 		cp.handle = ev->handle;
1745769be974SMarcel Holtmann 		cp.page = 0x01;
1746ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1747769be974SMarcel Holtmann 							sizeof(cp), &cp);
1748392599b9SJohan Hedberg 		goto unlock;
1749392599b9SJohan Hedberg 	}
1750392599b9SJohan Hedberg 
1751127178d2SJohan Hedberg 	if (!ev->status) {
1752127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1753127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1754127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1755127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1756127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1757127178d2SJohan Hedberg 	}
1758392599b9SJohan Hedberg 
1759127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1760769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1761769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1762769be974SMarcel Holtmann 		hci_conn_put(conn);
1763769be974SMarcel Holtmann 	}
1764769be974SMarcel Holtmann 
1765ccd556feSJohan Hedberg unlock:
1766a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1767a9de9248SMarcel Holtmann }
1768a9de9248SMarcel Holtmann 
1769a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1770a9de9248SMarcel Holtmann {
1771a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1772a9de9248SMarcel Holtmann }
1773a9de9248SMarcel Holtmann 
1774a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1775a9de9248SMarcel Holtmann {
1776a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1777a9de9248SMarcel Holtmann }
1778a9de9248SMarcel Holtmann 
1779a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1780a9de9248SMarcel Holtmann {
1781a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1782a9de9248SMarcel Holtmann 	__u16 opcode;
1783a9de9248SMarcel Holtmann 
1784a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1785a9de9248SMarcel Holtmann 
1786a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1787a9de9248SMarcel Holtmann 
1788a9de9248SMarcel Holtmann 	switch (opcode) {
1789a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1790a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1791a9de9248SMarcel Holtmann 		break;
1792a9de9248SMarcel Holtmann 
1793a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1794a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1795a9de9248SMarcel Holtmann 		break;
1796a9de9248SMarcel Holtmann 
1797a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1798a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1799a9de9248SMarcel Holtmann 		break;
1800a9de9248SMarcel Holtmann 
1801a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1802a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1803a9de9248SMarcel Holtmann 		break;
1804a9de9248SMarcel Holtmann 
1805e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1806e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1807e4e8e37cSMarcel Holtmann 		break;
1808e4e8e37cSMarcel Holtmann 
1809a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1810a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1811a9de9248SMarcel Holtmann 		break;
1812a9de9248SMarcel Holtmann 
1813e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1814e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1815e4e8e37cSMarcel Holtmann 		break;
1816e4e8e37cSMarcel Holtmann 
1817e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1818e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1819e4e8e37cSMarcel Holtmann 		break;
1820e4e8e37cSMarcel Holtmann 
1821a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1822a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1823a9de9248SMarcel Holtmann 		break;
1824a9de9248SMarcel Holtmann 
1825a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1826a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1827a9de9248SMarcel Holtmann 		break;
1828a9de9248SMarcel Holtmann 
1829a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1830a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1831a9de9248SMarcel Holtmann 		break;
1832a9de9248SMarcel Holtmann 
1833a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1834a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1835a9de9248SMarcel Holtmann 		break;
1836a9de9248SMarcel Holtmann 
1837a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1838a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1839a9de9248SMarcel Holtmann 		break;
1840a9de9248SMarcel Holtmann 
1841a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1842a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1843a9de9248SMarcel Holtmann 		break;
1844a9de9248SMarcel Holtmann 
1845a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1846a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1847a9de9248SMarcel Holtmann 		break;
1848a9de9248SMarcel Holtmann 
1849a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1850a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1851a9de9248SMarcel Holtmann 		break;
1852a9de9248SMarcel Holtmann 
1853a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1854a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1855a9de9248SMarcel Holtmann 		break;
1856a9de9248SMarcel Holtmann 
1857a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1858a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1859a9de9248SMarcel Holtmann 		break;
1860a9de9248SMarcel Holtmann 
1861a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1862a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1863a9de9248SMarcel Holtmann 		break;
1864a9de9248SMarcel Holtmann 
1865333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1866333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1867333140b5SMarcel Holtmann 		break;
1868333140b5SMarcel Holtmann 
1869333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1870333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1871333140b5SMarcel Holtmann 		break;
1872333140b5SMarcel Holtmann 
1873a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1874a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1875a9de9248SMarcel Holtmann 		break;
1876a9de9248SMarcel Holtmann 
1877a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1878a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1879a9de9248SMarcel Holtmann 		break;
1880a9de9248SMarcel Holtmann 
1881a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1882a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1883a9de9248SMarcel Holtmann 		break;
1884a9de9248SMarcel Holtmann 
1885971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
1886971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
1887971e3a4bSAndre Guedes 		break;
1888971e3a4bSAndre Guedes 
1889a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
1890a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
1891a9de9248SMarcel Holtmann 		break;
1892a9de9248SMarcel Holtmann 
1893a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
1894a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
1895a9de9248SMarcel Holtmann 		break;
1896a9de9248SMarcel Holtmann 
189723bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
189823bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
189923bb5763SJohan Hedberg 		break;
190023bb5763SJohan Hedberg 
1901b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
1902b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
1903b0916ea0SJohan Hedberg 		break;
1904b0916ea0SJohan Hedberg 
1905d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
1906d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
1907d5859e22SJohan Hedberg 		break;
1908d5859e22SJohan Hedberg 
1909d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
1910d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
1911d5859e22SJohan Hedberg 		break;
1912d5859e22SJohan Hedberg 
1913d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
1914d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
1915d5859e22SJohan Hedberg 		break;
1916d5859e22SJohan Hedberg 
1917d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
1918d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
1919d5859e22SJohan Hedberg 		break;
1920d5859e22SJohan Hedberg 
1921980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
1922980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
1923980e1a53SJohan Hedberg 		break;
1924980e1a53SJohan Hedberg 
1925980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
1926980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
1927980e1a53SJohan Hedberg 		break;
1928980e1a53SJohan Hedberg 
1929c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
1930c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
1931c35938b2SSzymon Janc 		break;
1932c35938b2SSzymon Janc 
19336ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
19346ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
19356ed58ec5SVille Tervo 		break;
19366ed58ec5SVille Tervo 
1937a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
1938a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
1939a5c29683SJohan Hedberg 		break;
1940a5c29683SJohan Hedberg 
1941a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
1942a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
1943a5c29683SJohan Hedberg 		break;
1944a5c29683SJohan Hedberg 
1945eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
1946eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
1947eb9d91f5SAndre Guedes 		break;
1948eb9d91f5SAndre Guedes 
1949a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
1950a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
1951a7a595f6SVinicius Costa Gomes 		break;
1952a7a595f6SVinicius Costa Gomes 
1953a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
1954a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
1955a7a595f6SVinicius Costa Gomes 		break;
1956a7a595f6SVinicius Costa Gomes 
1957f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
1958f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
1959f9b49306SAndre Guedes 		break;
1960f9b49306SAndre Guedes 
1961a9de9248SMarcel Holtmann 	default:
1962a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1963a9de9248SMarcel Holtmann 		break;
1964a9de9248SMarcel Holtmann 	}
1965a9de9248SMarcel Holtmann 
19666bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
19676bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
19686bd32326SVille Tervo 
1969a9de9248SMarcel Holtmann 	if (ev->ncmd) {
1970a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
1971a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
1972c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
1973a9de9248SMarcel Holtmann 	}
1974a9de9248SMarcel Holtmann }
1975a9de9248SMarcel Holtmann 
1976a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1977a9de9248SMarcel Holtmann {
1978a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
1979a9de9248SMarcel Holtmann 	__u16 opcode;
1980a9de9248SMarcel Holtmann 
1981a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1982a9de9248SMarcel Holtmann 
1983a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1984a9de9248SMarcel Holtmann 
1985a9de9248SMarcel Holtmann 	switch (opcode) {
1986a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
1987a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
1988a9de9248SMarcel Holtmann 		break;
1989a9de9248SMarcel Holtmann 
1990a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
1991a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
1992a9de9248SMarcel Holtmann 		break;
1993a9de9248SMarcel Holtmann 
1994a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
1995a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
1996a9de9248SMarcel Holtmann 		break;
1997a9de9248SMarcel Holtmann 
1998f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
1999f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2000f8558555SMarcel Holtmann 		break;
2001f8558555SMarcel Holtmann 
2002f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2003f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2004f8558555SMarcel Holtmann 		break;
2005f8558555SMarcel Holtmann 
2006a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2007a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2008a9de9248SMarcel Holtmann 		break;
2009a9de9248SMarcel Holtmann 
2010769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2011769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2012769be974SMarcel Holtmann 		break;
2013769be974SMarcel Holtmann 
2014769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2015769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2016769be974SMarcel Holtmann 		break;
2017769be974SMarcel Holtmann 
2018a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2019a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2020a9de9248SMarcel Holtmann 		break;
2021a9de9248SMarcel Holtmann 
2022a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2023a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2024a9de9248SMarcel Holtmann 		break;
2025a9de9248SMarcel Holtmann 
2026a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2027a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2028a9de9248SMarcel Holtmann 		break;
2029a9de9248SMarcel Holtmann 
20308962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
20318962ee74SJohan Hedberg 		if (ev->status != 0)
20328962ee74SJohan Hedberg 			mgmt_disconnect_failed(hdev->id);
20338962ee74SJohan Hedberg 		break;
20348962ee74SJohan Hedberg 
2035fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2036fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2037fcd89c09SVille Tervo 		break;
2038fcd89c09SVille Tervo 
2039a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2040a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2041a7a595f6SVinicius Costa Gomes 		break;
2042a7a595f6SVinicius Costa Gomes 
2043a9de9248SMarcel Holtmann 	default:
2044a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2045a9de9248SMarcel Holtmann 		break;
2046a9de9248SMarcel Holtmann 	}
2047a9de9248SMarcel Holtmann 
20486bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
20496bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
20506bd32326SVille Tervo 
205110572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2052a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2053a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2054c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2055a9de9248SMarcel Holtmann 	}
2056a9de9248SMarcel Holtmann }
2057a9de9248SMarcel Holtmann 
2058a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2059a9de9248SMarcel Holtmann {
2060a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2061a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2062a9de9248SMarcel Holtmann 
2063a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2064a9de9248SMarcel Holtmann 
2065a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2066a9de9248SMarcel Holtmann 
2067a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2068a9de9248SMarcel Holtmann 	if (conn) {
2069a9de9248SMarcel Holtmann 		if (!ev->status) {
2070a9de9248SMarcel Holtmann 			if (ev->role)
2071a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2072a9de9248SMarcel Holtmann 			else
2073a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2074a9de9248SMarcel Holtmann 		}
2075a9de9248SMarcel Holtmann 
2076a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2077a9de9248SMarcel Holtmann 
2078a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2079a9de9248SMarcel Holtmann 	}
2080a9de9248SMarcel Holtmann 
2081a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2082a9de9248SMarcel Holtmann }
2083a9de9248SMarcel Holtmann 
20841da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
20851da177e4SLinus Torvalds {
2086a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
20871ebb9252SMarcel Holtmann 	__le16 *ptr;
20881da177e4SLinus Torvalds 	int i;
20891da177e4SLinus Torvalds 
20901da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
20911da177e4SLinus Torvalds 
20921da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
20931da177e4SLinus Torvalds 
20941da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
20951da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
20961da177e4SLinus Torvalds 		return;
20971da177e4SLinus Torvalds 	}
20981da177e4SLinus Torvalds 
20991da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
21001da177e4SLinus Torvalds 
21011ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
21021da177e4SLinus Torvalds 		struct hci_conn *conn;
21031da177e4SLinus Torvalds 		__u16  handle, count;
21041da177e4SLinus Torvalds 
210583985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
210683985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
21071da177e4SLinus Torvalds 
21081da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
21091da177e4SLinus Torvalds 		if (conn) {
21101da177e4SLinus Torvalds 			conn->sent -= count;
21111da177e4SLinus Torvalds 
21125b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
211370f23020SAndrei Emeltchenko 				hdev->acl_cnt += count;
211470f23020SAndrei Emeltchenko 				if (hdev->acl_cnt > hdev->acl_pkts)
21151da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
21166ed58ec5SVille Tervo 			} else if (conn->type == LE_LINK) {
21176ed58ec5SVille Tervo 				if (hdev->le_pkts) {
21186ed58ec5SVille Tervo 					hdev->le_cnt += count;
21196ed58ec5SVille Tervo 					if (hdev->le_cnt > hdev->le_pkts)
21206ed58ec5SVille Tervo 						hdev->le_cnt = hdev->le_pkts;
21216ed58ec5SVille Tervo 				} else {
21226ed58ec5SVille Tervo 					hdev->acl_cnt += count;
21236ed58ec5SVille Tervo 					if (hdev->acl_cnt > hdev->acl_pkts)
21246ed58ec5SVille Tervo 						hdev->acl_cnt = hdev->acl_pkts;
21256ed58ec5SVille Tervo 				}
21265b7f9909SMarcel Holtmann 			} else {
212770f23020SAndrei Emeltchenko 				hdev->sco_cnt += count;
212870f23020SAndrei Emeltchenko 				if (hdev->sco_cnt > hdev->sco_pkts)
21295b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
21301da177e4SLinus Torvalds 			}
21311da177e4SLinus Torvalds 		}
21321da177e4SLinus Torvalds 	}
2133a9de9248SMarcel Holtmann 
2134c78ae283SMarcel Holtmann 	tasklet_schedule(&hdev->tx_task);
21351da177e4SLinus Torvalds 
21361da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
21371da177e4SLinus Torvalds }
21381da177e4SLinus Torvalds 
213904837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
21401da177e4SLinus Torvalds {
2141a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
214204837f64SMarcel Holtmann 	struct hci_conn *conn;
21431da177e4SLinus Torvalds 
21441da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
21451da177e4SLinus Torvalds 
21461da177e4SLinus Torvalds 	hci_dev_lock(hdev);
21471da177e4SLinus Torvalds 
214804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
214904837f64SMarcel Holtmann 	if (conn) {
215004837f64SMarcel Holtmann 		conn->mode = ev->mode;
215104837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
215204837f64SMarcel Holtmann 
215304837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
215404837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
215504837f64SMarcel Holtmann 				conn->power_save = 1;
215604837f64SMarcel Holtmann 			else
215704837f64SMarcel Holtmann 				conn->power_save = 0;
215804837f64SMarcel Holtmann 		}
2159e73439d8SMarcel Holtmann 
2160e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2161e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
216204837f64SMarcel Holtmann 	}
216304837f64SMarcel Holtmann 
216404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
216504837f64SMarcel Holtmann }
216604837f64SMarcel Holtmann 
21671da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
21681da177e4SLinus Torvalds {
2169052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2170052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2171052b30b0SMarcel Holtmann 
2172a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2173052b30b0SMarcel Holtmann 
2174052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2175052b30b0SMarcel Holtmann 
2176052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
21773d7a9d1cSMarcel Holtmann 	if (conn && conn->state == BT_CONNECTED) {
2178052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2179052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2180052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2181052b30b0SMarcel Holtmann 	}
2182052b30b0SMarcel Holtmann 
218303b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
218403b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
218503b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2186582fbe9eSJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->flags)) {
2187a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2188a770bb5aSWaldemar Rymarkiewicz 
2189a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2190a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2191a770bb5aSWaldemar Rymarkiewicz 		else
2192a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2193a770bb5aSWaldemar Rymarkiewicz 
2194a770bb5aSWaldemar Rymarkiewicz 		mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure);
2195a770bb5aSWaldemar Rymarkiewicz 	}
2196980e1a53SJohan Hedberg 
2197052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
21981da177e4SLinus Torvalds }
21991da177e4SLinus Torvalds 
22001da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
22011da177e4SLinus Torvalds {
220255ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
220355ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
220455ed8ca1SJohan Hedberg 	struct hci_conn *conn;
220555ed8ca1SJohan Hedberg 	struct link_key *key;
220655ed8ca1SJohan Hedberg 
2207a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
220855ed8ca1SJohan Hedberg 
220955ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
221055ed8ca1SJohan Hedberg 		return;
221155ed8ca1SJohan Hedberg 
221255ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
221355ed8ca1SJohan Hedberg 
221455ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
221555ed8ca1SJohan Hedberg 	if (!key) {
221655ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
221755ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
221855ed8ca1SJohan Hedberg 		goto not_found;
221955ed8ca1SJohan Hedberg 	}
222055ed8ca1SJohan Hedberg 
222155ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
222255ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
222355ed8ca1SJohan Hedberg 
2224b6020ba0SWaldemar Rymarkiewicz 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2225b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
222655ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
222755ed8ca1SJohan Hedberg 		goto not_found;
222855ed8ca1SJohan Hedberg 	}
222955ed8ca1SJohan Hedberg 
223055ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
223160b83f57SWaldemar Rymarkiewicz 	if (conn) {
223260b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
223360b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
223460b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
223555ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
223655ed8ca1SJohan Hedberg 			goto not_found;
223755ed8ca1SJohan Hedberg 		}
223855ed8ca1SJohan Hedberg 
223960b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
224060b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
224160b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
224260b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
224360b83f57SWaldemar Rymarkiewicz 			goto not_found;
224460b83f57SWaldemar Rymarkiewicz 		}
224560b83f57SWaldemar Rymarkiewicz 
224660b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
224760b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
224860b83f57SWaldemar Rymarkiewicz 	}
224960b83f57SWaldemar Rymarkiewicz 
225055ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
225155ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
225255ed8ca1SJohan Hedberg 
225355ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
225455ed8ca1SJohan Hedberg 
225555ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
225655ed8ca1SJohan Hedberg 
225755ed8ca1SJohan Hedberg 	return;
225855ed8ca1SJohan Hedberg 
225955ed8ca1SJohan Hedberg not_found:
226055ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
226155ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
22621da177e4SLinus Torvalds }
22631da177e4SLinus Torvalds 
22641da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
22651da177e4SLinus Torvalds {
2266052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2267052b30b0SMarcel Holtmann 	struct hci_conn *conn;
226855ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2269052b30b0SMarcel Holtmann 
2270a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2271052b30b0SMarcel Holtmann 
2272052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2273052b30b0SMarcel Holtmann 
2274052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2275052b30b0SMarcel Holtmann 	if (conn) {
2276052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2277052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2278980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
227913d39315SWaldemar Rymarkiewicz 
228013d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
228113d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
228213d39315SWaldemar Rymarkiewicz 
2283052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2284052b30b0SMarcel Holtmann 	}
2285052b30b0SMarcel Holtmann 
228655ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2287d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
228855ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
228955ed8ca1SJohan Hedberg 
2290052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
22911da177e4SLinus Torvalds }
22921da177e4SLinus Torvalds 
229304837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
229404837f64SMarcel Holtmann {
2295a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
229604837f64SMarcel Holtmann 	struct hci_conn *conn;
229704837f64SMarcel Holtmann 
229804837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
229904837f64SMarcel Holtmann 
230004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
230104837f64SMarcel Holtmann 
230204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
23031da177e4SLinus Torvalds 	if (conn && !ev->status) {
23041da177e4SLinus Torvalds 		struct inquiry_entry *ie;
23051da177e4SLinus Torvalds 
2306cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2307cc11b9c1SAndrei Emeltchenko 		if (ie) {
23081da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
23091da177e4SLinus Torvalds 			ie->timestamp = jiffies;
23101da177e4SLinus Torvalds 		}
23111da177e4SLinus Torvalds 	}
23121da177e4SLinus Torvalds 
23131da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
23141da177e4SLinus Torvalds }
23151da177e4SLinus Torvalds 
2316a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2317a8746417SMarcel Holtmann {
2318a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2319a8746417SMarcel Holtmann 	struct hci_conn *conn;
2320a8746417SMarcel Holtmann 
2321a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2322a8746417SMarcel Holtmann 
2323a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2324a8746417SMarcel Holtmann 
2325a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2326a8746417SMarcel Holtmann 	if (conn && !ev->status)
2327a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2328a8746417SMarcel Holtmann 
2329a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2330a8746417SMarcel Holtmann }
2331a8746417SMarcel Holtmann 
233285a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
233385a1e930SMarcel Holtmann {
2334a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
233585a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
233685a1e930SMarcel Holtmann 
233785a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
233885a1e930SMarcel Holtmann 
233985a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
234085a1e930SMarcel Holtmann 
2341cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2342cc11b9c1SAndrei Emeltchenko 	if (ie) {
234385a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
234485a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
234585a1e930SMarcel Holtmann 	}
234685a1e930SMarcel Holtmann 
234785a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
234885a1e930SMarcel Holtmann }
234985a1e930SMarcel Holtmann 
2350a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2351a9de9248SMarcel Holtmann {
2352a9de9248SMarcel Holtmann 	struct inquiry_data data;
2353a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2354a9de9248SMarcel Holtmann 
2355a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2356a9de9248SMarcel Holtmann 
2357a9de9248SMarcel Holtmann 	if (!num_rsp)
2358a9de9248SMarcel Holtmann 		return;
2359a9de9248SMarcel Holtmann 
2360a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2361a9de9248SMarcel Holtmann 
2362314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
2363314b2381SJohan Hedberg 
2364314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
2365314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
2366314b2381SJohan Hedberg 	}
2367314b2381SJohan Hedberg 
2368a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2369138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2370138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2371a9de9248SMarcel Holtmann 
2372e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2373a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2374a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2375a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2376a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2377a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2378a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2379a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
238041a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2381a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
2382e17acd40SJohan Hedberg 			mgmt_device_found(hdev->id, &info->bdaddr,
2383e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2384e17acd40SJohan Hedberg 						NULL);
2385a9de9248SMarcel Holtmann 		}
2386a9de9248SMarcel Holtmann 	} else {
2387a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2388a9de9248SMarcel Holtmann 
2389e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2390a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2391a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2392a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2393a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2394a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2395a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2396a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
239741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2398a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
2399e17acd40SJohan Hedberg 			mgmt_device_found(hdev->id, &info->bdaddr,
2400e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2401e17acd40SJohan Hedberg 						NULL);
2402a9de9248SMarcel Holtmann 		}
2403a9de9248SMarcel Holtmann 	}
2404a9de9248SMarcel Holtmann 
2405a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2406a9de9248SMarcel Holtmann }
2407a9de9248SMarcel Holtmann 
2408a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2409a9de9248SMarcel Holtmann {
241041a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
241141a96212SMarcel Holtmann 	struct hci_conn *conn;
241241a96212SMarcel Holtmann 
2413a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
241441a96212SMarcel Holtmann 
241541a96212SMarcel Holtmann 	hci_dev_lock(hdev);
241641a96212SMarcel Holtmann 
241741a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2418ccd556feSJohan Hedberg 	if (!conn)
2419ccd556feSJohan Hedberg 		goto unlock;
2420ccd556feSJohan Hedberg 
2421769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
242241a96212SMarcel Holtmann 		struct inquiry_entry *ie;
242341a96212SMarcel Holtmann 
2424cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2425cc11b9c1SAndrei Emeltchenko 		if (ie)
242641a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
242741a96212SMarcel Holtmann 
242841a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
242941a96212SMarcel Holtmann 	}
243041a96212SMarcel Holtmann 
2431ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2432ccd556feSJohan Hedberg 		goto unlock;
2433ccd556feSJohan Hedberg 
2434127178d2SJohan Hedberg 	if (!ev->status) {
2435127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2436127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2437127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2438127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2439127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2440127178d2SJohan Hedberg 	}
2441392599b9SJohan Hedberg 
2442127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2443769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2444769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2445769be974SMarcel Holtmann 		hci_conn_put(conn);
2446769be974SMarcel Holtmann 	}
2447769be974SMarcel Holtmann 
2448ccd556feSJohan Hedberg unlock:
244941a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2450a9de9248SMarcel Holtmann }
2451a9de9248SMarcel Holtmann 
2452a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2453a9de9248SMarcel Holtmann {
2454b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2455b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2456b6a0dc82SMarcel Holtmann 
2457b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2458b6a0dc82SMarcel Holtmann 
2459b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2460b6a0dc82SMarcel Holtmann 
2461b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
24629dc0a3afSMarcel Holtmann 	if (!conn) {
24639dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
24649dc0a3afSMarcel Holtmann 			goto unlock;
24659dc0a3afSMarcel Holtmann 
24669dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2467b6a0dc82SMarcel Holtmann 		if (!conn)
2468b6a0dc82SMarcel Holtmann 			goto unlock;
2469b6a0dc82SMarcel Holtmann 
24709dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
24719dc0a3afSMarcel Holtmann 	}
24729dc0a3afSMarcel Holtmann 
2473732547f9SMarcel Holtmann 	switch (ev->status) {
2474732547f9SMarcel Holtmann 	case 0x00:
2475732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2476732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2477732547f9SMarcel Holtmann 
24789eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2479732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2480732547f9SMarcel Holtmann 		break;
2481732547f9SMarcel Holtmann 
2482705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2483732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
24841038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2485732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2486732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2487efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2488efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2489efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2490efc7688bSMarcel Holtmann 			goto unlock;
2491efc7688bSMarcel Holtmann 		}
2492732547f9SMarcel Holtmann 		/* fall through */
2493efc7688bSMarcel Holtmann 
2494732547f9SMarcel Holtmann 	default:
2495b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2496732547f9SMarcel Holtmann 		break;
2497732547f9SMarcel Holtmann 	}
2498b6a0dc82SMarcel Holtmann 
2499b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2500b6a0dc82SMarcel Holtmann 	if (ev->status)
2501b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2502b6a0dc82SMarcel Holtmann 
2503b6a0dc82SMarcel Holtmann unlock:
2504b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2505a9de9248SMarcel Holtmann }
2506a9de9248SMarcel Holtmann 
2507a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2508a9de9248SMarcel Holtmann {
2509a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2510a9de9248SMarcel Holtmann }
2511a9de9248SMarcel Holtmann 
251204837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
251304837f64SMarcel Holtmann {
2514a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
251504837f64SMarcel Holtmann 
251604837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
251704837f64SMarcel Holtmann }
251804837f64SMarcel Holtmann 
2519a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2520a9de9248SMarcel Holtmann {
2521a9de9248SMarcel Holtmann 	struct inquiry_data data;
2522a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2523a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2524a9de9248SMarcel Holtmann 
2525a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2526a9de9248SMarcel Holtmann 
2527a9de9248SMarcel Holtmann 	if (!num_rsp)
2528a9de9248SMarcel Holtmann 		return;
2529a9de9248SMarcel Holtmann 
2530314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
2531314b2381SJohan Hedberg 
2532314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
2533314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
2534314b2381SJohan Hedberg 	}
2535314b2381SJohan Hedberg 
2536a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2537a9de9248SMarcel Holtmann 
2538e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2539a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2540a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2541a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2542a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2543a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2544a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2545a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
254641a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2547a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
2548e17acd40SJohan Hedberg 		mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class,
2549e17acd40SJohan Hedberg 						info->rssi, info->data);
2550a9de9248SMarcel Holtmann 	}
2551a9de9248SMarcel Holtmann 
2552a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2553a9de9248SMarcel Holtmann }
2554a9de9248SMarcel Holtmann 
255517fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
255617fa4b9dSJohan Hedberg {
255717fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
255817fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
255917fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
256017fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
256117fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
256217fa4b9dSJohan Hedberg 			return 0x02;
256317fa4b9dSJohan Hedberg 		else
256417fa4b9dSJohan Hedberg 			return 0x03;
256517fa4b9dSJohan Hedberg 	}
256617fa4b9dSJohan Hedberg 
256717fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
256817fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
256958797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
257017fa4b9dSJohan Hedberg 
257117fa4b9dSJohan Hedberg 	return conn->auth_type;
257217fa4b9dSJohan Hedberg }
257317fa4b9dSJohan Hedberg 
25740493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25750493684eSMarcel Holtmann {
25760493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
25770493684eSMarcel Holtmann 	struct hci_conn *conn;
25780493684eSMarcel Holtmann 
25790493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
25800493684eSMarcel Holtmann 
25810493684eSMarcel Holtmann 	hci_dev_lock(hdev);
25820493684eSMarcel Holtmann 
25830493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
258403b555e1SJohan Hedberg 	if (!conn)
258503b555e1SJohan Hedberg 		goto unlock;
258603b555e1SJohan Hedberg 
25870493684eSMarcel Holtmann 	hci_conn_hold(conn);
25880493684eSMarcel Holtmann 
258903b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
259003b555e1SJohan Hedberg 		goto unlock;
259103b555e1SJohan Hedberg 
259203b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
259303b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
259417fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
259517fa4b9dSJohan Hedberg 
259617fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
259717fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
25987cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
25997cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
260017fa4b9dSJohan Hedberg 
2601ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2602ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2603ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2604ce85ee13SSzymon Janc 		else
2605ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2606ce85ee13SSzymon Janc 
260717fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
260817fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
260903b555e1SJohan Hedberg 	} else {
261003b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
261103b555e1SJohan Hedberg 
261203b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
2613be77159cSJohan Hedberg 		cp.reason = 0x18; /* Pairing not allowed */
261403b555e1SJohan Hedberg 
261503b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
261603b555e1SJohan Hedberg 							sizeof(cp), &cp);
261703b555e1SJohan Hedberg 	}
261803b555e1SJohan Hedberg 
261903b555e1SJohan Hedberg unlock:
262003b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
262103b555e1SJohan Hedberg }
262203b555e1SJohan Hedberg 
262303b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
262403b555e1SJohan Hedberg {
262503b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
262603b555e1SJohan Hedberg 	struct hci_conn *conn;
262703b555e1SJohan Hedberg 
262803b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
262903b555e1SJohan Hedberg 
263003b555e1SJohan Hedberg 	hci_dev_lock(hdev);
263103b555e1SJohan Hedberg 
263203b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
263303b555e1SJohan Hedberg 	if (!conn)
263403b555e1SJohan Hedberg 		goto unlock;
263503b555e1SJohan Hedberg 
263603b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
263703b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
263803b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
263903b555e1SJohan Hedberg 
264003b555e1SJohan Hedberg unlock:
26410493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
26420493684eSMarcel Holtmann }
26430493684eSMarcel Holtmann 
2644a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2645a5c29683SJohan Hedberg 							struct sk_buff *skb)
2646a5c29683SJohan Hedberg {
2647a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
264855bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
26497a828908SJohan Hedberg 	struct hci_conn *conn;
2650a5c29683SJohan Hedberg 
2651a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
2652a5c29683SJohan Hedberg 
2653a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
2654a5c29683SJohan Hedberg 
26557a828908SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
26567a828908SJohan Hedberg 		goto unlock;
26577a828908SJohan Hedberg 
26587a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
26597a828908SJohan Hedberg 	if (!conn)
26607a828908SJohan Hedberg 		goto unlock;
26617a828908SJohan Hedberg 
26627a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
26637a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
26647a828908SJohan Hedberg 
26657a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
26667a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
26677a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
26687a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
26697a828908SJohan Hedberg 	 * bit set. */
26707a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
26717a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
26727a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
26737a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
26747a828908SJohan Hedberg 		goto unlock;
26757a828908SJohan Hedberg 	}
26767a828908SJohan Hedberg 
26777a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
26787a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
26797a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
268055bc1a37SJohan Hedberg 
268155bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
268255bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
268355bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
268455bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
268555bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
268655bc1a37SJohan Hedberg 			confirm_hint = 1;
268755bc1a37SJohan Hedberg 			goto confirm;
268855bc1a37SJohan Hedberg 		}
268955bc1a37SJohan Hedberg 
26909f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
26919f61656aSJohan Hedberg 						hdev->auto_accept_delay);
26929f61656aSJohan Hedberg 
26939f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
26949f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
26959f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
26969f61656aSJohan Hedberg 			goto unlock;
26979f61656aSJohan Hedberg 		}
26989f61656aSJohan Hedberg 
26997a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
27007a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
27017a828908SJohan Hedberg 		goto unlock;
27027a828908SJohan Hedberg 	}
27037a828908SJohan Hedberg 
270455bc1a37SJohan Hedberg confirm:
270555bc1a37SJohan Hedberg 	mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey,
270655bc1a37SJohan Hedberg 								confirm_hint);
2707a5c29683SJohan Hedberg 
27087a828908SJohan Hedberg unlock:
2709a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
2710a5c29683SJohan Hedberg }
2711a5c29683SJohan Hedberg 
27120493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
27130493684eSMarcel Holtmann {
27140493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
27150493684eSMarcel Holtmann 	struct hci_conn *conn;
27160493684eSMarcel Holtmann 
27170493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
27180493684eSMarcel Holtmann 
27190493684eSMarcel Holtmann 	hci_dev_lock(hdev);
27200493684eSMarcel Holtmann 
27210493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
27222a611692SJohan Hedberg 	if (!conn)
27232a611692SJohan Hedberg 		goto unlock;
27242a611692SJohan Hedberg 
27252a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
27262a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
27272a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
27282a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
27292a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
27302a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
27312a611692SJohan Hedberg 		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
27322a611692SJohan Hedberg 
27330493684eSMarcel Holtmann 	hci_conn_put(conn);
27340493684eSMarcel Holtmann 
27352a611692SJohan Hedberg unlock:
27360493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
27370493684eSMarcel Holtmann }
27380493684eSMarcel Holtmann 
273941a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
274041a96212SMarcel Holtmann {
274141a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
274241a96212SMarcel Holtmann 	struct inquiry_entry *ie;
274341a96212SMarcel Holtmann 
274441a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
274541a96212SMarcel Holtmann 
274641a96212SMarcel Holtmann 	hci_dev_lock(hdev);
274741a96212SMarcel Holtmann 
2748cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2749cc11b9c1SAndrei Emeltchenko 	if (ie)
275041a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
275141a96212SMarcel Holtmann 
275241a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
275341a96212SMarcel Holtmann }
275441a96212SMarcel Holtmann 
27552763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
27562763eda6SSzymon Janc 							struct sk_buff *skb)
27572763eda6SSzymon Janc {
27582763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
27592763eda6SSzymon Janc 	struct oob_data *data;
27602763eda6SSzymon Janc 
27612763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
27622763eda6SSzymon Janc 
27632763eda6SSzymon Janc 	hci_dev_lock(hdev);
27642763eda6SSzymon Janc 
2765e1ba1f15SSzymon Janc 	if (!test_bit(HCI_MGMT, &hdev->flags))
2766e1ba1f15SSzymon Janc 		goto unlock;
2767e1ba1f15SSzymon Janc 
27682763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
27692763eda6SSzymon Janc 	if (data) {
27702763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
27712763eda6SSzymon Janc 
27722763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
27732763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
27742763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
27752763eda6SSzymon Janc 
27762763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
27772763eda6SSzymon Janc 									&cp);
27782763eda6SSzymon Janc 	} else {
27792763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
27802763eda6SSzymon Janc 
27812763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
27822763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
27832763eda6SSzymon Janc 									&cp);
27842763eda6SSzymon Janc 	}
27852763eda6SSzymon Janc 
2786e1ba1f15SSzymon Janc unlock:
27872763eda6SSzymon Janc 	hci_dev_unlock(hdev);
27882763eda6SSzymon Janc }
27892763eda6SSzymon Janc 
2790fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2791fcd89c09SVille Tervo {
2792fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2793fcd89c09SVille Tervo 	struct hci_conn *conn;
2794fcd89c09SVille Tervo 
2795fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
2796fcd89c09SVille Tervo 
2797fcd89c09SVille Tervo 	hci_dev_lock(hdev);
2798fcd89c09SVille Tervo 
2799fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2800b62f328bSVille Tervo 	if (!conn) {
2801b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2802b62f328bSVille Tervo 		if (!conn) {
2803b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
2804b62f328bSVille Tervo 			hci_dev_unlock(hdev);
2805b62f328bSVille Tervo 			return;
2806b62f328bSVille Tervo 		}
280729b7988aSAndre Guedes 
280829b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
2809b62f328bSVille Tervo 	}
2810fcd89c09SVille Tervo 
2811fcd89c09SVille Tervo 	if (ev->status) {
281283bc71b4SVinicius Costa Gomes 		mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
2813fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
2814fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
2815fcd89c09SVille Tervo 		hci_conn_del(conn);
2816fcd89c09SVille Tervo 		goto unlock;
2817fcd89c09SVille Tervo 	}
2818fcd89c09SVille Tervo 
2819cfafccf7SVinicius Costa Gomes 	mgmt_connected(hdev->id, &ev->bdaddr, conn->type);
282083bc71b4SVinicius Costa Gomes 
28217b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
2822fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
2823fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
2824fcd89c09SVille Tervo 
2825fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
2826fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
2827fcd89c09SVille Tervo 
2828fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
2829fcd89c09SVille Tervo 
2830fcd89c09SVille Tervo unlock:
2831fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
2832fcd89c09SVille Tervo }
2833fcd89c09SVille Tervo 
28349aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
28359aa04c91SAndre Guedes 						struct sk_buff *skb)
28369aa04c91SAndre Guedes {
28379aa04c91SAndre Guedes 	struct hci_ev_le_advertising_info *ev;
28389aa04c91SAndre Guedes 	u8 num_reports;
28399aa04c91SAndre Guedes 
28409aa04c91SAndre Guedes 	num_reports = skb->data[0];
28419aa04c91SAndre Guedes 	ev = (void *) &skb->data[1];
28429aa04c91SAndre Guedes 
28439aa04c91SAndre Guedes 	hci_dev_lock(hdev);
28449aa04c91SAndre Guedes 
28459aa04c91SAndre Guedes 	hci_add_adv_entry(hdev, ev);
28469aa04c91SAndre Guedes 
28479aa04c91SAndre Guedes 	while (--num_reports) {
28489aa04c91SAndre Guedes 		ev = (void *) (ev->data + ev->length + 1);
28499aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
28509aa04c91SAndre Guedes 	}
28519aa04c91SAndre Guedes 
28529aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
28539aa04c91SAndre Guedes }
28549aa04c91SAndre Guedes 
2855a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
2856a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
2857a7a595f6SVinicius Costa Gomes {
2858a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
2859a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
2860bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
2861a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
2862bea710feSVinicius Costa Gomes 	struct link_key *ltk;
2863a7a595f6SVinicius Costa Gomes 
2864a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
2865a7a595f6SVinicius Costa Gomes 
2866a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
2867a7a595f6SVinicius Costa Gomes 
2868a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2869bea710feSVinicius Costa Gomes 	if (conn == NULL)
2870bea710feSVinicius Costa Gomes 		goto not_found;
2871a7a595f6SVinicius Costa Gomes 
2872bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
2873bea710feSVinicius Costa Gomes 	if (ltk == NULL)
2874bea710feSVinicius Costa Gomes 		goto not_found;
2875bea710feSVinicius Costa Gomes 
2876bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
2877a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
2878726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
2879a7a595f6SVinicius Costa Gomes 
2880a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
2881a7a595f6SVinicius Costa Gomes 
2882a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
2883bea710feSVinicius Costa Gomes 
2884bea710feSVinicius Costa Gomes 	return;
2885bea710feSVinicius Costa Gomes 
2886bea710feSVinicius Costa Gomes not_found:
2887bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
2888bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
2889bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
2890a7a595f6SVinicius Costa Gomes }
2891a7a595f6SVinicius Costa Gomes 
2892fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2893fcd89c09SVille Tervo {
2894fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
2895fcd89c09SVille Tervo 
2896fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
2897fcd89c09SVille Tervo 
2898fcd89c09SVille Tervo 	switch (le_ev->subevent) {
2899fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
2900fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
2901fcd89c09SVille Tervo 		break;
2902fcd89c09SVille Tervo 
29039aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
29049aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
29059aa04c91SAndre Guedes 		break;
29069aa04c91SAndre Guedes 
2907a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
2908a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
2909a7a595f6SVinicius Costa Gomes 		break;
2910a7a595f6SVinicius Costa Gomes 
2911fcd89c09SVille Tervo 	default:
2912fcd89c09SVille Tervo 		break;
2913fcd89c09SVille Tervo 	}
2914fcd89c09SVille Tervo }
2915fcd89c09SVille Tervo 
29161da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
29171da177e4SLinus Torvalds {
2918a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
2919a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
29201da177e4SLinus Torvalds 
29211da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
29221da177e4SLinus Torvalds 
2923a9de9248SMarcel Holtmann 	switch (event) {
29241da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
29251da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
29261da177e4SLinus Torvalds 		break;
29271da177e4SLinus Torvalds 
29281da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
29291da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
29301da177e4SLinus Torvalds 		break;
29311da177e4SLinus Torvalds 
2932a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
2933a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
293421d9e30eSMarcel Holtmann 		break;
293521d9e30eSMarcel Holtmann 
29361da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
29371da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
29381da177e4SLinus Torvalds 		break;
29391da177e4SLinus Torvalds 
29401da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
29411da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
29421da177e4SLinus Torvalds 		break;
29431da177e4SLinus Torvalds 
29441da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
29451da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
29461da177e4SLinus Torvalds 		break;
29471da177e4SLinus Torvalds 
2948a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
2949a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
2950a9de9248SMarcel Holtmann 		break;
2951a9de9248SMarcel Holtmann 
29521da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
29531da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
29541da177e4SLinus Torvalds 		break;
29551da177e4SLinus Torvalds 
2956a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
2957a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
2958a9de9248SMarcel Holtmann 		break;
2959a9de9248SMarcel Holtmann 
2960a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
2961a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
2962a9de9248SMarcel Holtmann 		break;
2963a9de9248SMarcel Holtmann 
2964a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
2965a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
2966a9de9248SMarcel Holtmann 		break;
2967a9de9248SMarcel Holtmann 
2968a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
2969a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
2970a9de9248SMarcel Holtmann 		break;
2971a9de9248SMarcel Holtmann 
2972a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
2973a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
2974a9de9248SMarcel Holtmann 		break;
2975a9de9248SMarcel Holtmann 
2976a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
2977a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
2978a9de9248SMarcel Holtmann 		break;
2979a9de9248SMarcel Holtmann 
2980a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
2981a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
2982a9de9248SMarcel Holtmann 		break;
2983a9de9248SMarcel Holtmann 
2984a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
2985a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
2986a9de9248SMarcel Holtmann 		break;
2987a9de9248SMarcel Holtmann 
2988a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
2989a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
29901da177e4SLinus Torvalds 		break;
29911da177e4SLinus Torvalds 
29921da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
29931da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
29941da177e4SLinus Torvalds 		break;
29951da177e4SLinus Torvalds 
29961da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
29971da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
29981da177e4SLinus Torvalds 		break;
29991da177e4SLinus Torvalds 
30001da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
30011da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
30021da177e4SLinus Torvalds 		break;
30031da177e4SLinus Torvalds 
30041da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
30051da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
30061da177e4SLinus Torvalds 		break;
30071da177e4SLinus Torvalds 
3008a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3009a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3010a8746417SMarcel Holtmann 		break;
3011a8746417SMarcel Holtmann 
301285a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
301385a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
301485a1e930SMarcel Holtmann 		break;
301585a1e930SMarcel Holtmann 
3016a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3017a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3018a9de9248SMarcel Holtmann 		break;
3019a9de9248SMarcel Holtmann 
3020a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3021a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3022a9de9248SMarcel Holtmann 		break;
3023a9de9248SMarcel Holtmann 
3024a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3025a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3026a9de9248SMarcel Holtmann 		break;
3027a9de9248SMarcel Holtmann 
3028a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3029a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3030a9de9248SMarcel Holtmann 		break;
3031a9de9248SMarcel Holtmann 
303204837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
303304837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
303404837f64SMarcel Holtmann 		break;
303504837f64SMarcel Holtmann 
3036a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3037a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
30381da177e4SLinus Torvalds 		break;
30391da177e4SLinus Torvalds 
30400493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
30410493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
30420493684eSMarcel Holtmann 		break;
30430493684eSMarcel Holtmann 
304403b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
304503b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
304603b555e1SJohan Hedberg 		break;
304703b555e1SJohan Hedberg 
3048a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3049a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3050a5c29683SJohan Hedberg 		break;
3051a5c29683SJohan Hedberg 
30520493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
30530493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
30540493684eSMarcel Holtmann 		break;
30550493684eSMarcel Holtmann 
305641a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
305741a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
305841a96212SMarcel Holtmann 		break;
305941a96212SMarcel Holtmann 
3060fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3061fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3062fcd89c09SVille Tervo 		break;
3063fcd89c09SVille Tervo 
30642763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
30652763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
30662763eda6SSzymon Janc 		break;
30672763eda6SSzymon Janc 
30681da177e4SLinus Torvalds 	default:
3069a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
30701da177e4SLinus Torvalds 		break;
30711da177e4SLinus Torvalds 	}
30721da177e4SLinus Torvalds 
30731da177e4SLinus Torvalds 	kfree_skb(skb);
30741da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
30751da177e4SLinus Torvalds }
30761da177e4SLinus Torvalds 
30771da177e4SLinus Torvalds /* Generate internal stack event */
30781da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
30791da177e4SLinus Torvalds {
30801da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
30811da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
30821da177e4SLinus Torvalds 	struct sk_buff *skb;
30831da177e4SLinus Torvalds 
30841da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
30851da177e4SLinus Torvalds 	if (!skb)
30861da177e4SLinus Torvalds 		return;
30871da177e4SLinus Torvalds 
30881da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
30891da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
30901da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
30911da177e4SLinus Torvalds 
30921da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
30931da177e4SLinus Torvalds 	ev->type = type;
30941da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
30951da177e4SLinus Torvalds 
3096576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3097a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3098576c7d85SMarcel Holtmann 
30990d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
31001da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3101eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
31021da177e4SLinus Torvalds 	kfree_skb(skb);
31031da177e4SLinus Torvalds }
3104e6100a25SAndre Guedes 
3105e6100a25SAndre Guedes module_param(enable_le, bool, 0444);
3106e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3107