xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 164a6e78)
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 
751928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
752928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
753928abaa7SAndrei Emeltchenko {
754928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
755928abaa7SAndrei Emeltchenko 
756928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
757928abaa7SAndrei Emeltchenko 
758928abaa7SAndrei Emeltchenko 	if (rp->status)
759928abaa7SAndrei Emeltchenko 		return;
760928abaa7SAndrei Emeltchenko 
761928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
762928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
763928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
764928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
765928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
766928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
767928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
768928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
769928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
770928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
771928abaa7SAndrei Emeltchenko 
772928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
773928abaa7SAndrei Emeltchenko }
774928abaa7SAndrei Emeltchenko 
775b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
776b0916ea0SJohan Hedberg 							struct sk_buff *skb)
777b0916ea0SJohan Hedberg {
778b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
779b0916ea0SJohan Hedberg 
780b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
781b0916ea0SJohan Hedberg 
782b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
783b0916ea0SJohan Hedberg }
784b0916ea0SJohan Hedberg 
785d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
786d5859e22SJohan Hedberg {
787d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
788d5859e22SJohan Hedberg 
789d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
790d5859e22SJohan Hedberg 
791d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
792d5859e22SJohan Hedberg }
793d5859e22SJohan Hedberg 
794d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
795d5859e22SJohan Hedberg 							struct sk_buff *skb)
796d5859e22SJohan Hedberg {
797d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
798d5859e22SJohan Hedberg 
799d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
800d5859e22SJohan Hedberg 
801d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
802d5859e22SJohan Hedberg }
803d5859e22SJohan Hedberg 
804d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
805d5859e22SJohan Hedberg 							struct sk_buff *skb)
806d5859e22SJohan Hedberg {
807d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
808d5859e22SJohan Hedberg 
809d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
810d5859e22SJohan Hedberg 
811d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
812d5859e22SJohan Hedberg }
813d5859e22SJohan Hedberg 
814d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
815d5859e22SJohan Hedberg {
816d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
817d5859e22SJohan Hedberg 
818d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
819d5859e22SJohan Hedberg 
820d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
821d5859e22SJohan Hedberg }
822d5859e22SJohan Hedberg 
823980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
824980e1a53SJohan Hedberg {
825980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
826980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
827980e1a53SJohan Hedberg 	struct hci_conn *conn;
828980e1a53SJohan Hedberg 
829980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
830980e1a53SJohan Hedberg 
831980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
832980e1a53SJohan Hedberg 		mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);
833980e1a53SJohan Hedberg 
834980e1a53SJohan Hedberg 	if (rp->status != 0)
835980e1a53SJohan Hedberg 		return;
836980e1a53SJohan Hedberg 
837980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
838980e1a53SJohan Hedberg 	if (!cp)
839980e1a53SJohan Hedberg 		return;
840980e1a53SJohan Hedberg 
841980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
842980e1a53SJohan Hedberg 	if (conn)
843980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
844980e1a53SJohan Hedberg }
845980e1a53SJohan Hedberg 
846980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
847980e1a53SJohan Hedberg {
848980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
849980e1a53SJohan Hedberg 
850980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
851980e1a53SJohan Hedberg 
852980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
853980e1a53SJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
854980e1a53SJohan Hedberg 								rp->status);
855980e1a53SJohan Hedberg }
8566ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8576ed58ec5SVille Tervo 				       struct sk_buff *skb)
8586ed58ec5SVille Tervo {
8596ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
8606ed58ec5SVille Tervo 
8616ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
8626ed58ec5SVille Tervo 
8636ed58ec5SVille Tervo 	if (rp->status)
8646ed58ec5SVille Tervo 		return;
8656ed58ec5SVille Tervo 
8666ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
8676ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8686ed58ec5SVille Tervo 
8696ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8706ed58ec5SVille Tervo 
8716ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8726ed58ec5SVille Tervo 
8736ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
8746ed58ec5SVille Tervo }
875980e1a53SJohan Hedberg 
876a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
877a5c29683SJohan Hedberg {
878a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
879a5c29683SJohan Hedberg 
880a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
881a5c29683SJohan Hedberg 
882a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
883a5c29683SJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr,
884a5c29683SJohan Hedberg 								rp->status);
885a5c29683SJohan Hedberg }
886a5c29683SJohan Hedberg 
887a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
888a5c29683SJohan Hedberg 							struct sk_buff *skb)
889a5c29683SJohan Hedberg {
890a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
891a5c29683SJohan Hedberg 
892a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
893a5c29683SJohan Hedberg 
894a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
895a5c29683SJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr,
896a5c29683SJohan Hedberg 								rp->status);
897a5c29683SJohan Hedberg }
898a5c29683SJohan Hedberg 
899c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
900c35938b2SSzymon Janc 							struct sk_buff *skb)
901c35938b2SSzymon Janc {
902c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
903c35938b2SSzymon Janc 
904c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
905c35938b2SSzymon Janc 
906c35938b2SSzymon Janc 	mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash,
907c35938b2SSzymon Janc 						rp->randomizer, rp->status);
908c35938b2SSzymon Janc }
909c35938b2SSzymon Janc 
910eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
911eb9d91f5SAndre Guedes 					struct sk_buff *skb)
912eb9d91f5SAndre Guedes {
913eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
914eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
915eb9d91f5SAndre Guedes 
916eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
917eb9d91f5SAndre Guedes 
918eb9d91f5SAndre Guedes 	if (status)
919eb9d91f5SAndre Guedes 		return;
920eb9d91f5SAndre Guedes 
921eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
922eb9d91f5SAndre Guedes 	if (!cp)
923eb9d91f5SAndre Guedes 		return;
924eb9d91f5SAndre Guedes 
92535815085SAndre Guedes 	if (cp->enable == 0x01) {
92635815085SAndre Guedes 		del_timer(&hdev->adv_timer);
927a8f13c8cSAndre Guedes 
928a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
929eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
930a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
93135815085SAndre Guedes 	} else if (cp->enable == 0x00) {
93235815085SAndre Guedes 		mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
93335815085SAndre Guedes 	}
934eb9d91f5SAndre Guedes }
935eb9d91f5SAndre Guedes 
936a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
937a7a595f6SVinicius Costa Gomes {
938a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
939a7a595f6SVinicius Costa Gomes 
940a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
941a7a595f6SVinicius Costa Gomes 
942a7a595f6SVinicius Costa Gomes 	if (rp->status)
943a7a595f6SVinicius Costa Gomes 		return;
944a7a595f6SVinicius Costa Gomes 
945a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
946a7a595f6SVinicius Costa Gomes }
947a7a595f6SVinicius Costa Gomes 
948a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
949a7a595f6SVinicius Costa Gomes {
950a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
951a7a595f6SVinicius Costa Gomes 
952a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
953a7a595f6SVinicius Costa Gomes 
954a7a595f6SVinicius Costa Gomes 	if (rp->status)
955a7a595f6SVinicius Costa Gomes 		return;
956a7a595f6SVinicius Costa Gomes 
957a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
958a7a595f6SVinicius Costa Gomes }
959a7a595f6SVinicius Costa Gomes 
960f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
961f9b49306SAndre Guedes 							struct sk_buff *skb)
962f9b49306SAndre Guedes {
963f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
964f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
965f9b49306SAndre Guedes 
966f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
967f9b49306SAndre Guedes 
968f9b49306SAndre Guedes 	if (status)
969f9b49306SAndre Guedes 		return;
970f9b49306SAndre Guedes 
971f9b49306SAndre Guedes 	cp.page = 0x01;
972f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
973f9b49306SAndre Guedes }
974f9b49306SAndre Guedes 
975a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
976a9de9248SMarcel Holtmann {
977a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
978a9de9248SMarcel Holtmann 
979a9de9248SMarcel Holtmann 	if (status) {
98023bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
981a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
982164a6e78SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
983164a6e78SJohan Hedberg 			mgmt_inquiry_failed(hdev->id, status);
984314b2381SJohan Hedberg 		return;
985314b2381SJohan Hedberg 	}
986314b2381SJohan Hedberg 
9872d20a26aSOliver Neukum 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags) &&
9882d20a26aSOliver Neukum 				test_bit(HCI_MGMT, &hdev->flags))
989314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 1);
990a9de9248SMarcel Holtmann }
991a9de9248SMarcel Holtmann 
9921da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
9931da177e4SLinus Torvalds {
994a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
9951da177e4SLinus Torvalds 	struct hci_conn *conn;
9961da177e4SLinus Torvalds 
997a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
998a9de9248SMarcel Holtmann 
999a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
10001da177e4SLinus Torvalds 	if (!cp)
10011da177e4SLinus Torvalds 		return;
10021da177e4SLinus Torvalds 
10031da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10041da177e4SLinus Torvalds 
10051da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
10061da177e4SLinus Torvalds 
1007a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
10081da177e4SLinus Torvalds 
10091da177e4SLinus Torvalds 	if (status) {
10101da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
10114c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
10121da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
10131da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
10141da177e4SLinus Torvalds 				hci_conn_del(conn);
10154c67bc74SMarcel Holtmann 			} else
10164c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
10171da177e4SLinus Torvalds 		}
10181da177e4SLinus Torvalds 	} else {
10191da177e4SLinus Torvalds 		if (!conn) {
10201da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
10211da177e4SLinus Torvalds 			if (conn) {
10221da177e4SLinus Torvalds 				conn->out = 1;
10231da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
10241da177e4SLinus Torvalds 			} else
1025893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
10261da177e4SLinus Torvalds 		}
10271da177e4SLinus Torvalds 	}
10281da177e4SLinus Torvalds 
10291da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10301da177e4SLinus Torvalds }
10311da177e4SLinus Torvalds 
1032a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
10331da177e4SLinus Torvalds {
1034a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
10351da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
10361da177e4SLinus Torvalds 	__u16 handle;
10371da177e4SLinus Torvalds 
1038b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1039b6a0dc82SMarcel Holtmann 
1040a9de9248SMarcel Holtmann 	if (!status)
1041a9de9248SMarcel Holtmann 		return;
1042a9de9248SMarcel Holtmann 
1043a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
10441da177e4SLinus Torvalds 	if (!cp)
1045a9de9248SMarcel Holtmann 		return;
10461da177e4SLinus Torvalds 
10471da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
10481da177e4SLinus Torvalds 
1049a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
10501da177e4SLinus Torvalds 
10511da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10521da177e4SLinus Torvalds 
10531da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
10545a08ecceSAndrei Emeltchenko 	if (acl) {
10555a08ecceSAndrei Emeltchenko 		sco = acl->link;
10565a08ecceSAndrei Emeltchenko 		if (sco) {
10571da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
10581da177e4SLinus Torvalds 
10591da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
10601da177e4SLinus Torvalds 			hci_conn_del(sco);
10611da177e4SLinus Torvalds 		}
10625a08ecceSAndrei Emeltchenko 	}
10631da177e4SLinus Torvalds 
10641da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10651da177e4SLinus Torvalds }
10661da177e4SLinus Torvalds 
1067f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1068f8558555SMarcel Holtmann {
1069f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1070f8558555SMarcel Holtmann 	struct hci_conn *conn;
1071f8558555SMarcel Holtmann 
1072f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1073f8558555SMarcel Holtmann 
1074f8558555SMarcel Holtmann 	if (!status)
1075f8558555SMarcel Holtmann 		return;
1076f8558555SMarcel Holtmann 
1077f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1078f8558555SMarcel Holtmann 	if (!cp)
1079f8558555SMarcel Holtmann 		return;
1080f8558555SMarcel Holtmann 
1081f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1082f8558555SMarcel Holtmann 
1083f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1084f8558555SMarcel Holtmann 	if (conn) {
1085f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1086f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1087f8558555SMarcel Holtmann 			hci_conn_put(conn);
1088f8558555SMarcel Holtmann 		}
1089f8558555SMarcel Holtmann 	}
1090f8558555SMarcel Holtmann 
1091f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1092f8558555SMarcel Holtmann }
1093f8558555SMarcel Holtmann 
1094f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1095f8558555SMarcel Holtmann {
1096f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1097f8558555SMarcel Holtmann 	struct hci_conn *conn;
1098f8558555SMarcel Holtmann 
1099f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1100f8558555SMarcel Holtmann 
1101f8558555SMarcel Holtmann 	if (!status)
1102f8558555SMarcel Holtmann 		return;
1103f8558555SMarcel Holtmann 
1104f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1105f8558555SMarcel Holtmann 	if (!cp)
1106f8558555SMarcel Holtmann 		return;
1107f8558555SMarcel Holtmann 
1108f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1109f8558555SMarcel Holtmann 
1110f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1111f8558555SMarcel Holtmann 	if (conn) {
1112f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1113f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1114f8558555SMarcel Holtmann 			hci_conn_put(conn);
1115f8558555SMarcel Holtmann 		}
1116f8558555SMarcel Holtmann 	}
1117f8558555SMarcel Holtmann 
1118f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1119f8558555SMarcel Holtmann }
1120f8558555SMarcel Holtmann 
1121127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1122392599b9SJohan Hedberg 							struct hci_conn *conn)
1123392599b9SJohan Hedberg {
1124392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1125392599b9SJohan Hedberg 		return 0;
1126392599b9SJohan Hedberg 
1127765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1128392599b9SJohan Hedberg 		return 0;
1129392599b9SJohan Hedberg 
1130392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1131e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1132392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1133e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1134e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1135392599b9SJohan Hedberg 		return 0;
1136392599b9SJohan Hedberg 
1137392599b9SJohan Hedberg 	return 1;
1138392599b9SJohan Hedberg }
1139392599b9SJohan Hedberg 
1140a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
11411da177e4SLinus Torvalds {
1142127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1143127178d2SJohan Hedberg 	struct hci_conn *conn;
1144127178d2SJohan Hedberg 
1145a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1146127178d2SJohan Hedberg 
1147127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1148127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1149127178d2SJohan Hedberg 	if (!status)
1150127178d2SJohan Hedberg 		return;
1151127178d2SJohan Hedberg 
1152127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1153127178d2SJohan Hedberg 	if (!cp)
1154127178d2SJohan Hedberg 		return;
1155127178d2SJohan Hedberg 
1156127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1157127178d2SJohan Hedberg 
1158127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
115979c6c70cSJohan Hedberg 	if (!conn)
116079c6c70cSJohan Hedberg 		goto unlock;
116179c6c70cSJohan Hedberg 
116279c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
116379c6c70cSJohan Hedberg 		goto unlock;
116479c6c70cSJohan Hedberg 
116579c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1166127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1167127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1168127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1169127178d2SJohan Hedberg 	}
1170127178d2SJohan Hedberg 
117179c6c70cSJohan Hedberg unlock:
1172127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1173a9de9248SMarcel Holtmann }
11741da177e4SLinus Torvalds 
1175769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1176769be974SMarcel Holtmann {
1177769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1178769be974SMarcel Holtmann 	struct hci_conn *conn;
1179769be974SMarcel Holtmann 
1180769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1181769be974SMarcel Holtmann 
1182769be974SMarcel Holtmann 	if (!status)
1183769be974SMarcel Holtmann 		return;
1184769be974SMarcel Holtmann 
1185769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1186769be974SMarcel Holtmann 	if (!cp)
1187769be974SMarcel Holtmann 		return;
1188769be974SMarcel Holtmann 
1189769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1190769be974SMarcel Holtmann 
1191769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1192769be974SMarcel Holtmann 	if (conn) {
1193769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1194769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1195769be974SMarcel Holtmann 			hci_conn_put(conn);
1196769be974SMarcel Holtmann 		}
1197769be974SMarcel Holtmann 	}
1198769be974SMarcel Holtmann 
1199769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1200769be974SMarcel Holtmann }
1201769be974SMarcel Holtmann 
1202769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1203769be974SMarcel Holtmann {
1204769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1205769be974SMarcel Holtmann 	struct hci_conn *conn;
1206769be974SMarcel Holtmann 
1207769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1208769be974SMarcel Holtmann 
1209769be974SMarcel Holtmann 	if (!status)
1210769be974SMarcel Holtmann 		return;
1211769be974SMarcel Holtmann 
1212769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1213769be974SMarcel Holtmann 	if (!cp)
1214769be974SMarcel Holtmann 		return;
1215769be974SMarcel Holtmann 
1216769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1217769be974SMarcel Holtmann 
1218769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1219769be974SMarcel Holtmann 	if (conn) {
1220769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1221769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1222769be974SMarcel Holtmann 			hci_conn_put(conn);
1223769be974SMarcel Holtmann 		}
1224769be974SMarcel Holtmann 	}
1225769be974SMarcel Holtmann 
1226769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1227769be974SMarcel Holtmann }
1228769be974SMarcel Holtmann 
1229a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1230a9de9248SMarcel Holtmann {
1231b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1232b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1233b6a0dc82SMarcel Holtmann 	__u16 handle;
1234b6a0dc82SMarcel Holtmann 
1235a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1236b6a0dc82SMarcel Holtmann 
1237b6a0dc82SMarcel Holtmann 	if (!status)
1238b6a0dc82SMarcel Holtmann 		return;
1239b6a0dc82SMarcel Holtmann 
1240b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1241b6a0dc82SMarcel Holtmann 	if (!cp)
1242b6a0dc82SMarcel Holtmann 		return;
1243b6a0dc82SMarcel Holtmann 
1244b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1245b6a0dc82SMarcel Holtmann 
1246b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1247b6a0dc82SMarcel Holtmann 
1248b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1249b6a0dc82SMarcel Holtmann 
1250b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12515a08ecceSAndrei Emeltchenko 	if (acl) {
12525a08ecceSAndrei Emeltchenko 		sco = acl->link;
12535a08ecceSAndrei Emeltchenko 		if (sco) {
1254b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1255b6a0dc82SMarcel Holtmann 
1256b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1257b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1258b6a0dc82SMarcel Holtmann 		}
12595a08ecceSAndrei Emeltchenko 	}
1260b6a0dc82SMarcel Holtmann 
1261b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1262a9de9248SMarcel Holtmann }
1263a9de9248SMarcel Holtmann 
1264a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1265a9de9248SMarcel Holtmann {
1266a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
126704837f64SMarcel Holtmann 	struct hci_conn *conn;
126804837f64SMarcel Holtmann 
1269a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1270a9de9248SMarcel Holtmann 
1271a9de9248SMarcel Holtmann 	if (!status)
1272a9de9248SMarcel Holtmann 		return;
1273a9de9248SMarcel Holtmann 
1274a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
127504837f64SMarcel Holtmann 	if (!cp)
1276a9de9248SMarcel Holtmann 		return;
127704837f64SMarcel Holtmann 
127804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
127904837f64SMarcel Holtmann 
128004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1281e73439d8SMarcel Holtmann 	if (conn) {
128204837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
128304837f64SMarcel Holtmann 
1284e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1285e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1286e73439d8SMarcel Holtmann 	}
1287e73439d8SMarcel Holtmann 
128804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
128904837f64SMarcel Holtmann }
129004837f64SMarcel Holtmann 
1291a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1292a9de9248SMarcel Holtmann {
1293a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
129404837f64SMarcel Holtmann 	struct hci_conn *conn;
129504837f64SMarcel Holtmann 
1296a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1297a9de9248SMarcel Holtmann 
1298a9de9248SMarcel Holtmann 	if (!status)
1299a9de9248SMarcel Holtmann 		return;
1300a9de9248SMarcel Holtmann 
1301a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
130204837f64SMarcel Holtmann 	if (!cp)
1303a9de9248SMarcel Holtmann 		return;
130404837f64SMarcel Holtmann 
130504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
130604837f64SMarcel Holtmann 
130704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1308e73439d8SMarcel Holtmann 	if (conn) {
130904837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
131004837f64SMarcel Holtmann 
1311e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1312e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1313e73439d8SMarcel Holtmann 	}
1314e73439d8SMarcel Holtmann 
131504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
131604837f64SMarcel Holtmann }
131704837f64SMarcel Holtmann 
1318fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1319fcd89c09SVille Tervo {
1320fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1321fcd89c09SVille Tervo 	struct hci_conn *conn;
1322fcd89c09SVille Tervo 
1323fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1324fcd89c09SVille Tervo 
1325fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1326fcd89c09SVille Tervo 	if (!cp)
1327fcd89c09SVille Tervo 		return;
1328fcd89c09SVille Tervo 
1329fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1330fcd89c09SVille Tervo 
1331fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1332fcd89c09SVille Tervo 
1333fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1334fcd89c09SVille Tervo 		conn);
1335fcd89c09SVille Tervo 
1336fcd89c09SVille Tervo 	if (status) {
1337fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1338fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1339fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1340fcd89c09SVille Tervo 			hci_conn_del(conn);
1341fcd89c09SVille Tervo 		}
1342fcd89c09SVille Tervo 	} else {
1343fcd89c09SVille Tervo 		if (!conn) {
1344fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
134529b7988aSAndre Guedes 			if (conn) {
134629b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1347fcd89c09SVille Tervo 				conn->out = 1;
134829b7988aSAndre Guedes 			} else {
1349fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1350fcd89c09SVille Tervo 			}
1351fcd89c09SVille Tervo 		}
135229b7988aSAndre Guedes 	}
1353fcd89c09SVille Tervo 
1354fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1355fcd89c09SVille Tervo }
1356fcd89c09SVille Tervo 
1357a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1358a7a595f6SVinicius Costa Gomes {
1359a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1360a7a595f6SVinicius Costa Gomes }
1361a7a595f6SVinicius Costa Gomes 
13621da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
13631da177e4SLinus Torvalds {
13641da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
13651da177e4SLinus Torvalds 
13661da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
13671da177e4SLinus Torvalds 
13682d20a26aSOliver Neukum 	if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) &&
13692d20a26aSOliver Neukum 				test_bit(HCI_MGMT, &hdev->flags))
1370314b2381SJohan Hedberg 		mgmt_discovering(hdev->id, 0);
1371a9de9248SMarcel Holtmann 
137223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
13736bd57416SMarcel Holtmann 
1374a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
13751da177e4SLinus Torvalds }
13761da177e4SLinus Torvalds 
13771da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
13781da177e4SLinus Torvalds {
137945bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1380a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
13811da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
13821da177e4SLinus Torvalds 
13831da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
13841da177e4SLinus Torvalds 
138545bb4bf0SMarcel Holtmann 	if (!num_rsp)
138645bb4bf0SMarcel Holtmann 		return;
138745bb4bf0SMarcel Holtmann 
13881da177e4SLinus Torvalds 	hci_dev_lock(hdev);
138945bb4bf0SMarcel Holtmann 
1390314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
1391314b2381SJohan Hedberg 
1392314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
1393314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
1394314b2381SJohan Hedberg 	}
1395314b2381SJohan Hedberg 
1396e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
13971da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
13981da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
13991da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
14001da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
14011da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
14021da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
14031da177e4SLinus Torvalds 		data.rssi		= 0x00;
140441a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
14051da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
1406e17acd40SJohan Hedberg 		mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0,
1407e17acd40SJohan Hedberg 									NULL);
14081da177e4SLinus Torvalds 	}
140945bb4bf0SMarcel Holtmann 
14101da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14111da177e4SLinus Torvalds }
14121da177e4SLinus Torvalds 
1413a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14141da177e4SLinus Torvalds {
1415a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1416a9de9248SMarcel Holtmann 	struct hci_conn *conn;
14171da177e4SLinus Torvalds 
1418a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
141945bb4bf0SMarcel Holtmann 
14201da177e4SLinus Torvalds 	hci_dev_lock(hdev);
142145bb4bf0SMarcel Holtmann 
1422a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
14239499237aSMarcel Holtmann 	if (!conn) {
14249499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
14259499237aSMarcel Holtmann 			goto unlock;
14269499237aSMarcel Holtmann 
14279499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1428a9de9248SMarcel Holtmann 		if (!conn)
1429a9de9248SMarcel Holtmann 			goto unlock;
143045bb4bf0SMarcel Holtmann 
14319499237aSMarcel Holtmann 		conn->type = SCO_LINK;
14329499237aSMarcel Holtmann 	}
14339499237aSMarcel Holtmann 
1434a9de9248SMarcel Holtmann 	if (!ev->status) {
1435a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1436769be974SMarcel Holtmann 
1437769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1438769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1439769be974SMarcel Holtmann 			hci_conn_hold(conn);
1440052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1441cfafccf7SVinicius Costa Gomes 			mgmt_connected(hdev->id, &ev->bdaddr, conn->type);
1442769be974SMarcel Holtmann 		} else
1443a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1444a9de9248SMarcel Holtmann 
14459eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
14467d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
14477d0db0a3SMarcel Holtmann 
1448a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1449a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1450a9de9248SMarcel Holtmann 
1451a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1452a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1453a9de9248SMarcel Holtmann 
1454a9de9248SMarcel Holtmann 		/* Get remote features */
1455a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1456a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1457a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1458769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1459769be974SMarcel Holtmann 							sizeof(cp), &cp);
146045bb4bf0SMarcel Holtmann 		}
1461a9de9248SMarcel Holtmann 
1462a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1463a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
1464a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1465a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1466a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1467a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1468a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1469a9de9248SMarcel Holtmann 		}
147017d5c04cSJohan Hedberg 	} else {
1471a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
147217d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
147317d5c04cSJohan Hedberg 			mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
147417d5c04cSJohan Hedberg 	}
147545bb4bf0SMarcel Holtmann 
1476e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1477e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
147845bb4bf0SMarcel Holtmann 
1479769be974SMarcel Holtmann 	if (ev->status) {
1480a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1481a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1482c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1483c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1484a9de9248SMarcel Holtmann 
1485a9de9248SMarcel Holtmann unlock:
14861da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1487a9de9248SMarcel Holtmann 
1488a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
14891da177e4SLinus Torvalds }
14901da177e4SLinus Torvalds 
14911da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
14921da177e4SLinus Torvalds {
1493a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
14941da177e4SLinus Torvalds 	int mask = hdev->link_mode;
14951da177e4SLinus Torvalds 
1496a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
14971da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
14981da177e4SLinus Torvalds 
14991da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
15001da177e4SLinus Torvalds 
1501138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1502138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
15031da177e4SLinus Torvalds 		/* Connection accepted */
1504c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
15051da177e4SLinus Torvalds 		struct hci_conn *conn;
15061da177e4SLinus Torvalds 
15071da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1508b6a0dc82SMarcel Holtmann 
1509cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1510cc11b9c1SAndrei Emeltchenko 		if (ie)
1511c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1512c7bdd502SMarcel Holtmann 
15131da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
15141da177e4SLinus Torvalds 		if (!conn) {
1515cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1516cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1517893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
15181da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
15191da177e4SLinus Torvalds 				return;
15201da177e4SLinus Torvalds 			}
15211da177e4SLinus Torvalds 		}
1522b6a0dc82SMarcel Holtmann 
15231da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
15241da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1525b6a0dc82SMarcel Holtmann 
15261da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
15271da177e4SLinus Torvalds 
1528b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1529b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1530b6a0dc82SMarcel Holtmann 
15311da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
15321da177e4SLinus Torvalds 
15331da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
15341da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
15351da177e4SLinus Torvalds 			else
15361da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
15371da177e4SLinus Torvalds 
1538b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1539b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1540b6a0dc82SMarcel Holtmann 		} else {
1541b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1542b6a0dc82SMarcel Holtmann 
1543b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1544a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1545b6a0dc82SMarcel Holtmann 
1546b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1547b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1548b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1549b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1550b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1551b6a0dc82SMarcel Holtmann 
1552b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1553b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1554b6a0dc82SMarcel Holtmann 		}
15551da177e4SLinus Torvalds 	} else {
15561da177e4SLinus Torvalds 		/* Connection rejected */
15571da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
15581da177e4SLinus Torvalds 
15591da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
15601da177e4SLinus Torvalds 		cp.reason = 0x0f;
1561a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
15621da177e4SLinus Torvalds 	}
15631da177e4SLinus Torvalds }
15641da177e4SLinus Torvalds 
15651da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15661da177e4SLinus Torvalds {
1567a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
156804837f64SMarcel Holtmann 	struct hci_conn *conn;
15691da177e4SLinus Torvalds 
15701da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
15711da177e4SLinus Torvalds 
15728962ee74SJohan Hedberg 	if (ev->status) {
15738962ee74SJohan Hedberg 		mgmt_disconnect_failed(hdev->id);
15741da177e4SLinus Torvalds 		return;
15758962ee74SJohan Hedberg 	}
15761da177e4SLinus Torvalds 
15771da177e4SLinus Torvalds 	hci_dev_lock(hdev);
15781da177e4SLinus Torvalds 
157904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1580f7520543SJohan Hedberg 	if (!conn)
1581f7520543SJohan Hedberg 		goto unlock;
1582f7520543SJohan Hedberg 
15831da177e4SLinus Torvalds 	conn->state = BT_CLOSED;
15847d0db0a3SMarcel Holtmann 
158583bc71b4SVinicius Costa Gomes 	if (conn->type == ACL_LINK || conn->type == LE_LINK)
1586f7520543SJohan Hedberg 		mgmt_disconnected(hdev->id, &conn->dst);
1587f7520543SJohan Hedberg 
15882950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
15891da177e4SLinus Torvalds 	hci_conn_del(conn);
15901da177e4SLinus Torvalds 
1591f7520543SJohan Hedberg unlock:
15921da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15931da177e4SLinus Torvalds }
15941da177e4SLinus Torvalds 
1595a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1596a9de9248SMarcel Holtmann {
1597a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1598a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1599a9de9248SMarcel Holtmann 
1600a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1601a9de9248SMarcel Holtmann 
1602a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1603a9de9248SMarcel Holtmann 
1604a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1605d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1606d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1607d7556e20SWaldemar Rymarkiewicz 
1608765c2a96SJohan Hedberg 	if (!ev->status) {
160919f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1610d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1611d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
161219f8def0SWaldemar Rymarkiewicz 		} else {
1613a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1614765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
161519f8def0SWaldemar Rymarkiewicz 		}
16162a611692SJohan Hedberg 	} else {
16172a611692SJohan Hedberg 		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
16182a611692SJohan Hedberg 	}
1619a9de9248SMarcel Holtmann 
1620a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
162119f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1622a9de9248SMarcel Holtmann 
1623f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1624d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1625f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1626f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1627f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1628d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1629d7556e20SWaldemar Rymarkiewicz 									&cp);
1630f8558555SMarcel Holtmann 		} else {
1631f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1632f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1633f8558555SMarcel Holtmann 			hci_conn_put(conn);
1634f8558555SMarcel Holtmann 		}
1635052b30b0SMarcel Holtmann 	} else {
1636a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1637a9de9248SMarcel Holtmann 
1638052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1639052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1640052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1641052b30b0SMarcel Holtmann 	}
1642052b30b0SMarcel Holtmann 
1643a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1644a9de9248SMarcel Holtmann 		if (!ev->status) {
1645a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1646f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1647f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1648d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1649d7556e20SWaldemar Rymarkiewicz 									&cp);
1650a9de9248SMarcel Holtmann 		} else {
1651a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1652a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1653a9de9248SMarcel Holtmann 		}
1654a9de9248SMarcel Holtmann 	}
1655a9de9248SMarcel Holtmann 
1656d7556e20SWaldemar Rymarkiewicz unlock:
1657a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1658a9de9248SMarcel Holtmann }
1659a9de9248SMarcel Holtmann 
1660a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1661a9de9248SMarcel Holtmann {
1662127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1663127178d2SJohan Hedberg 	struct hci_conn *conn;
1664127178d2SJohan Hedberg 
1665a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1666a9de9248SMarcel Holtmann 
1667a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1668127178d2SJohan Hedberg 
1669127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1670127178d2SJohan Hedberg 
1671a88a9652SJohan Hedberg 	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
1672a88a9652SJohan Hedberg 		mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name);
1673a88a9652SJohan Hedberg 
1674127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
167579c6c70cSJohan Hedberg 	if (!conn)
167679c6c70cSJohan Hedberg 		goto unlock;
167779c6c70cSJohan Hedberg 
167879c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
167979c6c70cSJohan Hedberg 		goto unlock;
168079c6c70cSJohan Hedberg 
168179c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1682127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1683127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1684127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1685127178d2SJohan Hedberg 	}
1686127178d2SJohan Hedberg 
168779c6c70cSJohan Hedberg unlock:
1688127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1689a9de9248SMarcel Holtmann }
1690a9de9248SMarcel Holtmann 
1691a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1692a9de9248SMarcel Holtmann {
1693a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1694a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1695a9de9248SMarcel Holtmann 
1696a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1697a9de9248SMarcel Holtmann 
1698a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1699a9de9248SMarcel Holtmann 
1700a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1701a9de9248SMarcel Holtmann 	if (conn) {
1702a9de9248SMarcel Holtmann 		if (!ev->status) {
1703ae293196SMarcel Holtmann 			if (ev->encrypt) {
1704ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1705ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1706a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1707da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1708ae293196SMarcel Holtmann 			} else
1709a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1710a9de9248SMarcel Holtmann 		}
1711a9de9248SMarcel Holtmann 
1712a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1713a9de9248SMarcel Holtmann 
1714f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1715f8558555SMarcel Holtmann 			if (!ev->status)
1716f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1717f8558555SMarcel Holtmann 
1718f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1719f8558555SMarcel Holtmann 			hci_conn_put(conn);
1720f8558555SMarcel Holtmann 		} else
1721a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1722a9de9248SMarcel Holtmann 	}
1723a9de9248SMarcel Holtmann 
1724a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1725a9de9248SMarcel Holtmann }
1726a9de9248SMarcel Holtmann 
1727a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1728a9de9248SMarcel Holtmann {
1729a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1730a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1731a9de9248SMarcel Holtmann 
1732a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1733a9de9248SMarcel Holtmann 
1734a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1735a9de9248SMarcel Holtmann 
1736a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1737a9de9248SMarcel Holtmann 	if (conn) {
1738a9de9248SMarcel Holtmann 		if (!ev->status)
1739a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1740a9de9248SMarcel Holtmann 
1741a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1742a9de9248SMarcel Holtmann 
1743a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1744a9de9248SMarcel Holtmann 	}
1745a9de9248SMarcel Holtmann 
1746a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1747a9de9248SMarcel Holtmann }
1748a9de9248SMarcel Holtmann 
1749a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1750a9de9248SMarcel Holtmann {
1751a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1752a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1753a9de9248SMarcel Holtmann 
1754a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1755a9de9248SMarcel Holtmann 
1756a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1757a9de9248SMarcel Holtmann 
1758a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1759ccd556feSJohan Hedberg 	if (!conn)
1760ccd556feSJohan Hedberg 		goto unlock;
1761ccd556feSJohan Hedberg 
1762769be974SMarcel Holtmann 	if (!ev->status)
1763a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1764a9de9248SMarcel Holtmann 
1765ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1766ccd556feSJohan Hedberg 		goto unlock;
1767ccd556feSJohan Hedberg 
1768ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1769769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1770769be974SMarcel Holtmann 		cp.handle = ev->handle;
1771769be974SMarcel Holtmann 		cp.page = 0x01;
1772ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1773769be974SMarcel Holtmann 							sizeof(cp), &cp);
1774392599b9SJohan Hedberg 		goto unlock;
1775392599b9SJohan Hedberg 	}
1776392599b9SJohan Hedberg 
1777127178d2SJohan Hedberg 	if (!ev->status) {
1778127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1779127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1780127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1781127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1782127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1783127178d2SJohan Hedberg 	}
1784392599b9SJohan Hedberg 
1785127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1786769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1787769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1788769be974SMarcel Holtmann 		hci_conn_put(conn);
1789769be974SMarcel Holtmann 	}
1790769be974SMarcel Holtmann 
1791ccd556feSJohan Hedberg unlock:
1792a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1793a9de9248SMarcel Holtmann }
1794a9de9248SMarcel Holtmann 
1795a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1796a9de9248SMarcel Holtmann {
1797a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1798a9de9248SMarcel Holtmann }
1799a9de9248SMarcel Holtmann 
1800a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1801a9de9248SMarcel Holtmann {
1802a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1803a9de9248SMarcel Holtmann }
1804a9de9248SMarcel Holtmann 
1805a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1806a9de9248SMarcel Holtmann {
1807a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1808a9de9248SMarcel Holtmann 	__u16 opcode;
1809a9de9248SMarcel Holtmann 
1810a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1811a9de9248SMarcel Holtmann 
1812a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1813a9de9248SMarcel Holtmann 
1814a9de9248SMarcel Holtmann 	switch (opcode) {
1815a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1816a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1817a9de9248SMarcel Holtmann 		break;
1818a9de9248SMarcel Holtmann 
1819a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1820a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1821a9de9248SMarcel Holtmann 		break;
1822a9de9248SMarcel Holtmann 
1823a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1824a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1825a9de9248SMarcel Holtmann 		break;
1826a9de9248SMarcel Holtmann 
1827a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1828a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1829a9de9248SMarcel Holtmann 		break;
1830a9de9248SMarcel Holtmann 
1831e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1832e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1833e4e8e37cSMarcel Holtmann 		break;
1834e4e8e37cSMarcel Holtmann 
1835a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1836a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1837a9de9248SMarcel Holtmann 		break;
1838a9de9248SMarcel Holtmann 
1839e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1840e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1841e4e8e37cSMarcel Holtmann 		break;
1842e4e8e37cSMarcel Holtmann 
1843e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1844e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1845e4e8e37cSMarcel Holtmann 		break;
1846e4e8e37cSMarcel Holtmann 
1847a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1848a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1849a9de9248SMarcel Holtmann 		break;
1850a9de9248SMarcel Holtmann 
1851a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1852a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1853a9de9248SMarcel Holtmann 		break;
1854a9de9248SMarcel Holtmann 
1855a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1856a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1857a9de9248SMarcel Holtmann 		break;
1858a9de9248SMarcel Holtmann 
1859a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1860a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1861a9de9248SMarcel Holtmann 		break;
1862a9de9248SMarcel Holtmann 
1863a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1864a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1865a9de9248SMarcel Holtmann 		break;
1866a9de9248SMarcel Holtmann 
1867a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1868a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1869a9de9248SMarcel Holtmann 		break;
1870a9de9248SMarcel Holtmann 
1871a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1872a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1873a9de9248SMarcel Holtmann 		break;
1874a9de9248SMarcel Holtmann 
1875a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1876a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1877a9de9248SMarcel Holtmann 		break;
1878a9de9248SMarcel Holtmann 
1879a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1880a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1881a9de9248SMarcel Holtmann 		break;
1882a9de9248SMarcel Holtmann 
1883a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1884a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1885a9de9248SMarcel Holtmann 		break;
1886a9de9248SMarcel Holtmann 
1887a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1888a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1889a9de9248SMarcel Holtmann 		break;
1890a9de9248SMarcel Holtmann 
1891333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1892333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1893333140b5SMarcel Holtmann 		break;
1894333140b5SMarcel Holtmann 
1895333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1896333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1897333140b5SMarcel Holtmann 		break;
1898333140b5SMarcel Holtmann 
1899a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1900a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1901a9de9248SMarcel Holtmann 		break;
1902a9de9248SMarcel Holtmann 
1903a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1904a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1905a9de9248SMarcel Holtmann 		break;
1906a9de9248SMarcel Holtmann 
1907a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1908a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1909a9de9248SMarcel Holtmann 		break;
1910a9de9248SMarcel Holtmann 
1911971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
1912971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
1913971e3a4bSAndre Guedes 		break;
1914971e3a4bSAndre Guedes 
1915a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
1916a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
1917a9de9248SMarcel Holtmann 		break;
1918a9de9248SMarcel Holtmann 
1919a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
1920a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
1921a9de9248SMarcel Holtmann 		break;
1922a9de9248SMarcel Holtmann 
192323bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
192423bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
192523bb5763SJohan Hedberg 		break;
192623bb5763SJohan Hedberg 
1927928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
1928928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
1929928abaa7SAndrei Emeltchenko 		break;
1930928abaa7SAndrei Emeltchenko 
1931b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
1932b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
1933b0916ea0SJohan Hedberg 		break;
1934b0916ea0SJohan Hedberg 
1935d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
1936d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
1937d5859e22SJohan Hedberg 		break;
1938d5859e22SJohan Hedberg 
1939d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
1940d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
1941d5859e22SJohan Hedberg 		break;
1942d5859e22SJohan Hedberg 
1943d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
1944d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
1945d5859e22SJohan Hedberg 		break;
1946d5859e22SJohan Hedberg 
1947d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
1948d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
1949d5859e22SJohan Hedberg 		break;
1950d5859e22SJohan Hedberg 
1951980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
1952980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
1953980e1a53SJohan Hedberg 		break;
1954980e1a53SJohan Hedberg 
1955980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
1956980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
1957980e1a53SJohan Hedberg 		break;
1958980e1a53SJohan Hedberg 
1959c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
1960c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
1961c35938b2SSzymon Janc 		break;
1962c35938b2SSzymon Janc 
19636ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
19646ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
19656ed58ec5SVille Tervo 		break;
19666ed58ec5SVille Tervo 
1967a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
1968a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
1969a5c29683SJohan Hedberg 		break;
1970a5c29683SJohan Hedberg 
1971a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
1972a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
1973a5c29683SJohan Hedberg 		break;
1974a5c29683SJohan Hedberg 
1975eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
1976eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
1977eb9d91f5SAndre Guedes 		break;
1978eb9d91f5SAndre Guedes 
1979a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
1980a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
1981a7a595f6SVinicius Costa Gomes 		break;
1982a7a595f6SVinicius Costa Gomes 
1983a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
1984a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
1985a7a595f6SVinicius Costa Gomes 		break;
1986a7a595f6SVinicius Costa Gomes 
1987f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
1988f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
1989f9b49306SAndre Guedes 		break;
1990f9b49306SAndre Guedes 
1991a9de9248SMarcel Holtmann 	default:
1992a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1993a9de9248SMarcel Holtmann 		break;
1994a9de9248SMarcel Holtmann 	}
1995a9de9248SMarcel Holtmann 
19966bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
19976bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
19986bd32326SVille Tervo 
1999a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2000a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2001a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2002c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2003a9de9248SMarcel Holtmann 	}
2004a9de9248SMarcel Holtmann }
2005a9de9248SMarcel Holtmann 
2006a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2007a9de9248SMarcel Holtmann {
2008a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2009a9de9248SMarcel Holtmann 	__u16 opcode;
2010a9de9248SMarcel Holtmann 
2011a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2012a9de9248SMarcel Holtmann 
2013a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2014a9de9248SMarcel Holtmann 
2015a9de9248SMarcel Holtmann 	switch (opcode) {
2016a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2017a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2018a9de9248SMarcel Holtmann 		break;
2019a9de9248SMarcel Holtmann 
2020a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2021a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2022a9de9248SMarcel Holtmann 		break;
2023a9de9248SMarcel Holtmann 
2024a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2025a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2026a9de9248SMarcel Holtmann 		break;
2027a9de9248SMarcel Holtmann 
2028f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2029f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2030f8558555SMarcel Holtmann 		break;
2031f8558555SMarcel Holtmann 
2032f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2033f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2034f8558555SMarcel Holtmann 		break;
2035f8558555SMarcel Holtmann 
2036a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2037a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2038a9de9248SMarcel Holtmann 		break;
2039a9de9248SMarcel Holtmann 
2040769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2041769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2042769be974SMarcel Holtmann 		break;
2043769be974SMarcel Holtmann 
2044769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2045769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2046769be974SMarcel Holtmann 		break;
2047769be974SMarcel Holtmann 
2048a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2049a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2050a9de9248SMarcel Holtmann 		break;
2051a9de9248SMarcel Holtmann 
2052a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2053a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2054a9de9248SMarcel Holtmann 		break;
2055a9de9248SMarcel Holtmann 
2056a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2057a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2058a9de9248SMarcel Holtmann 		break;
2059a9de9248SMarcel Holtmann 
20608962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
20618962ee74SJohan Hedberg 		if (ev->status != 0)
20628962ee74SJohan Hedberg 			mgmt_disconnect_failed(hdev->id);
20638962ee74SJohan Hedberg 		break;
20648962ee74SJohan Hedberg 
2065fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2066fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2067fcd89c09SVille Tervo 		break;
2068fcd89c09SVille Tervo 
2069a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2070a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2071a7a595f6SVinicius Costa Gomes 		break;
2072a7a595f6SVinicius Costa Gomes 
2073a9de9248SMarcel Holtmann 	default:
2074a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2075a9de9248SMarcel Holtmann 		break;
2076a9de9248SMarcel Holtmann 	}
2077a9de9248SMarcel Holtmann 
20786bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
20796bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
20806bd32326SVille Tervo 
208110572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2082a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2083a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2084c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2085a9de9248SMarcel Holtmann 	}
2086a9de9248SMarcel Holtmann }
2087a9de9248SMarcel Holtmann 
2088a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2089a9de9248SMarcel Holtmann {
2090a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2091a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2092a9de9248SMarcel Holtmann 
2093a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2094a9de9248SMarcel Holtmann 
2095a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2096a9de9248SMarcel Holtmann 
2097a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2098a9de9248SMarcel Holtmann 	if (conn) {
2099a9de9248SMarcel Holtmann 		if (!ev->status) {
2100a9de9248SMarcel Holtmann 			if (ev->role)
2101a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2102a9de9248SMarcel Holtmann 			else
2103a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2104a9de9248SMarcel Holtmann 		}
2105a9de9248SMarcel Holtmann 
2106a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2107a9de9248SMarcel Holtmann 
2108a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2109a9de9248SMarcel Holtmann 	}
2110a9de9248SMarcel Holtmann 
2111a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2112a9de9248SMarcel Holtmann }
2113a9de9248SMarcel Holtmann 
21141da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
21151da177e4SLinus Torvalds {
2116a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
21171ebb9252SMarcel Holtmann 	__le16 *ptr;
21181da177e4SLinus Torvalds 	int i;
21191da177e4SLinus Torvalds 
21201da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
21211da177e4SLinus Torvalds 
21221da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
21231da177e4SLinus Torvalds 
21241da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
21251da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
21261da177e4SLinus Torvalds 		return;
21271da177e4SLinus Torvalds 	}
21281da177e4SLinus Torvalds 
21291da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
21301da177e4SLinus Torvalds 
21311ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
21321da177e4SLinus Torvalds 		struct hci_conn *conn;
21331da177e4SLinus Torvalds 		__u16  handle, count;
21341da177e4SLinus Torvalds 
213583985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
213683985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
21371da177e4SLinus Torvalds 
21381da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
21391da177e4SLinus Torvalds 		if (conn) {
21401da177e4SLinus Torvalds 			conn->sent -= count;
21411da177e4SLinus Torvalds 
21425b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
214370f23020SAndrei Emeltchenko 				hdev->acl_cnt += count;
214470f23020SAndrei Emeltchenko 				if (hdev->acl_cnt > hdev->acl_pkts)
21451da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
21466ed58ec5SVille Tervo 			} else if (conn->type == LE_LINK) {
21476ed58ec5SVille Tervo 				if (hdev->le_pkts) {
21486ed58ec5SVille Tervo 					hdev->le_cnt += count;
21496ed58ec5SVille Tervo 					if (hdev->le_cnt > hdev->le_pkts)
21506ed58ec5SVille Tervo 						hdev->le_cnt = hdev->le_pkts;
21516ed58ec5SVille Tervo 				} else {
21526ed58ec5SVille Tervo 					hdev->acl_cnt += count;
21536ed58ec5SVille Tervo 					if (hdev->acl_cnt > hdev->acl_pkts)
21546ed58ec5SVille Tervo 						hdev->acl_cnt = hdev->acl_pkts;
21556ed58ec5SVille Tervo 				}
21565b7f9909SMarcel Holtmann 			} else {
215770f23020SAndrei Emeltchenko 				hdev->sco_cnt += count;
215870f23020SAndrei Emeltchenko 				if (hdev->sco_cnt > hdev->sco_pkts)
21595b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
21601da177e4SLinus Torvalds 			}
21611da177e4SLinus Torvalds 		}
21621da177e4SLinus Torvalds 	}
2163a9de9248SMarcel Holtmann 
2164c78ae283SMarcel Holtmann 	tasklet_schedule(&hdev->tx_task);
21651da177e4SLinus Torvalds 
21661da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
21671da177e4SLinus Torvalds }
21681da177e4SLinus Torvalds 
216904837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
21701da177e4SLinus Torvalds {
2171a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
217204837f64SMarcel Holtmann 	struct hci_conn *conn;
21731da177e4SLinus Torvalds 
21741da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
21751da177e4SLinus Torvalds 
21761da177e4SLinus Torvalds 	hci_dev_lock(hdev);
21771da177e4SLinus Torvalds 
217804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
217904837f64SMarcel Holtmann 	if (conn) {
218004837f64SMarcel Holtmann 		conn->mode = ev->mode;
218104837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
218204837f64SMarcel Holtmann 
218304837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
218404837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
218504837f64SMarcel Holtmann 				conn->power_save = 1;
218604837f64SMarcel Holtmann 			else
218704837f64SMarcel Holtmann 				conn->power_save = 0;
218804837f64SMarcel Holtmann 		}
2189e73439d8SMarcel Holtmann 
2190e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2191e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
219204837f64SMarcel Holtmann 	}
219304837f64SMarcel Holtmann 
219404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
219504837f64SMarcel Holtmann }
219604837f64SMarcel Holtmann 
21971da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
21981da177e4SLinus Torvalds {
2199052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2200052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2201052b30b0SMarcel Holtmann 
2202a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2203052b30b0SMarcel Holtmann 
2204052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2205052b30b0SMarcel Holtmann 
2206052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2207b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2208b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2209b6f98044SWaldemar Rymarkiewicz 
2210b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2211052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2212052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2213052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2214052b30b0SMarcel Holtmann 	}
2215052b30b0SMarcel Holtmann 
221603b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
221703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
221803b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2219582fbe9eSJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->flags)) {
2220a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2221a770bb5aSWaldemar Rymarkiewicz 
2222a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2223a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2224a770bb5aSWaldemar Rymarkiewicz 		else
2225a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2226a770bb5aSWaldemar Rymarkiewicz 
2227a770bb5aSWaldemar Rymarkiewicz 		mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure);
2228a770bb5aSWaldemar Rymarkiewicz 	}
2229980e1a53SJohan Hedberg 
2230b6f98044SWaldemar Rymarkiewicz unlock:
2231052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
22321da177e4SLinus Torvalds }
22331da177e4SLinus Torvalds 
22341da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
22351da177e4SLinus Torvalds {
223655ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
223755ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
223855ed8ca1SJohan Hedberg 	struct hci_conn *conn;
223955ed8ca1SJohan Hedberg 	struct link_key *key;
224055ed8ca1SJohan Hedberg 
2241a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
224255ed8ca1SJohan Hedberg 
224355ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
224455ed8ca1SJohan Hedberg 		return;
224555ed8ca1SJohan Hedberg 
224655ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
224755ed8ca1SJohan Hedberg 
224855ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
224955ed8ca1SJohan Hedberg 	if (!key) {
225055ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
225155ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
225255ed8ca1SJohan Hedberg 		goto not_found;
225355ed8ca1SJohan Hedberg 	}
225455ed8ca1SJohan Hedberg 
225555ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
225655ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
225755ed8ca1SJohan Hedberg 
2258b6020ba0SWaldemar Rymarkiewicz 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2259b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
226055ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
226155ed8ca1SJohan Hedberg 		goto not_found;
226255ed8ca1SJohan Hedberg 	}
226355ed8ca1SJohan Hedberg 
226455ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
226560b83f57SWaldemar Rymarkiewicz 	if (conn) {
226660b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
226760b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
226860b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
226955ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
227055ed8ca1SJohan Hedberg 			goto not_found;
227155ed8ca1SJohan Hedberg 		}
227255ed8ca1SJohan Hedberg 
227360b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
227460b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
227560b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
227660b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
227760b83f57SWaldemar Rymarkiewicz 			goto not_found;
227860b83f57SWaldemar Rymarkiewicz 		}
227960b83f57SWaldemar Rymarkiewicz 
228060b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
228160b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
228260b83f57SWaldemar Rymarkiewicz 	}
228360b83f57SWaldemar Rymarkiewicz 
228455ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
228555ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
228655ed8ca1SJohan Hedberg 
228755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
228855ed8ca1SJohan Hedberg 
228955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
229055ed8ca1SJohan Hedberg 
229155ed8ca1SJohan Hedberg 	return;
229255ed8ca1SJohan Hedberg 
229355ed8ca1SJohan Hedberg not_found:
229455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
229555ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
22961da177e4SLinus Torvalds }
22971da177e4SLinus Torvalds 
22981da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
22991da177e4SLinus Torvalds {
2300052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2301052b30b0SMarcel Holtmann 	struct hci_conn *conn;
230255ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2303052b30b0SMarcel Holtmann 
2304a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2305052b30b0SMarcel Holtmann 
2306052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2307052b30b0SMarcel Holtmann 
2308052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2309052b30b0SMarcel Holtmann 	if (conn) {
2310052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2311052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2312980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
231313d39315SWaldemar Rymarkiewicz 
231413d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
231513d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
231613d39315SWaldemar Rymarkiewicz 
2317052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2318052b30b0SMarcel Holtmann 	}
2319052b30b0SMarcel Holtmann 
232055ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2321d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
232255ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
232355ed8ca1SJohan Hedberg 
2324052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
23251da177e4SLinus Torvalds }
23261da177e4SLinus Torvalds 
232704837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
232804837f64SMarcel Holtmann {
2329a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
233004837f64SMarcel Holtmann 	struct hci_conn *conn;
233104837f64SMarcel Holtmann 
233204837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
233304837f64SMarcel Holtmann 
233404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
233504837f64SMarcel Holtmann 
233604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
23371da177e4SLinus Torvalds 	if (conn && !ev->status) {
23381da177e4SLinus Torvalds 		struct inquiry_entry *ie;
23391da177e4SLinus Torvalds 
2340cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2341cc11b9c1SAndrei Emeltchenko 		if (ie) {
23421da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
23431da177e4SLinus Torvalds 			ie->timestamp = jiffies;
23441da177e4SLinus Torvalds 		}
23451da177e4SLinus Torvalds 	}
23461da177e4SLinus Torvalds 
23471da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
23481da177e4SLinus Torvalds }
23491da177e4SLinus Torvalds 
2350a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2351a8746417SMarcel Holtmann {
2352a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2353a8746417SMarcel Holtmann 	struct hci_conn *conn;
2354a8746417SMarcel Holtmann 
2355a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2356a8746417SMarcel Holtmann 
2357a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2358a8746417SMarcel Holtmann 
2359a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2360a8746417SMarcel Holtmann 	if (conn && !ev->status)
2361a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2362a8746417SMarcel Holtmann 
2363a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2364a8746417SMarcel Holtmann }
2365a8746417SMarcel Holtmann 
236685a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
236785a1e930SMarcel Holtmann {
2368a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
236985a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
237085a1e930SMarcel Holtmann 
237185a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
237285a1e930SMarcel Holtmann 
237385a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
237485a1e930SMarcel Holtmann 
2375cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2376cc11b9c1SAndrei Emeltchenko 	if (ie) {
237785a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
237885a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
237985a1e930SMarcel Holtmann 	}
238085a1e930SMarcel Holtmann 
238185a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
238285a1e930SMarcel Holtmann }
238385a1e930SMarcel Holtmann 
2384a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2385a9de9248SMarcel Holtmann {
2386a9de9248SMarcel Holtmann 	struct inquiry_data data;
2387a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2388a9de9248SMarcel Holtmann 
2389a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2390a9de9248SMarcel Holtmann 
2391a9de9248SMarcel Holtmann 	if (!num_rsp)
2392a9de9248SMarcel Holtmann 		return;
2393a9de9248SMarcel Holtmann 
2394a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2395a9de9248SMarcel Holtmann 
2396314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
2397314b2381SJohan Hedberg 
2398314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
2399314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
2400314b2381SJohan Hedberg 	}
2401314b2381SJohan Hedberg 
2402a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2403138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2404138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2405a9de9248SMarcel Holtmann 
2406e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2407a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2408a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2409a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2410a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2411a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2412a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2413a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
241441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2415a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
2416e17acd40SJohan Hedberg 			mgmt_device_found(hdev->id, &info->bdaddr,
2417e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2418e17acd40SJohan Hedberg 						NULL);
2419a9de9248SMarcel Holtmann 		}
2420a9de9248SMarcel Holtmann 	} else {
2421a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2422a9de9248SMarcel Holtmann 
2423e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2424a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2425a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2426a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2427a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2428a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2429a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2430a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
243141a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2432a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
2433e17acd40SJohan Hedberg 			mgmt_device_found(hdev->id, &info->bdaddr,
2434e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2435e17acd40SJohan Hedberg 						NULL);
2436a9de9248SMarcel Holtmann 		}
2437a9de9248SMarcel Holtmann 	}
2438a9de9248SMarcel Holtmann 
2439a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2440a9de9248SMarcel Holtmann }
2441a9de9248SMarcel Holtmann 
2442a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2443a9de9248SMarcel Holtmann {
244441a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
244541a96212SMarcel Holtmann 	struct hci_conn *conn;
244641a96212SMarcel Holtmann 
2447a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
244841a96212SMarcel Holtmann 
244941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
245041a96212SMarcel Holtmann 
245141a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2452ccd556feSJohan Hedberg 	if (!conn)
2453ccd556feSJohan Hedberg 		goto unlock;
2454ccd556feSJohan Hedberg 
2455769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
245641a96212SMarcel Holtmann 		struct inquiry_entry *ie;
245741a96212SMarcel Holtmann 
2458cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2459cc11b9c1SAndrei Emeltchenko 		if (ie)
246041a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
246141a96212SMarcel Holtmann 
246241a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
246341a96212SMarcel Holtmann 	}
246441a96212SMarcel Holtmann 
2465ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2466ccd556feSJohan Hedberg 		goto unlock;
2467ccd556feSJohan Hedberg 
2468127178d2SJohan Hedberg 	if (!ev->status) {
2469127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2470127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2471127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2472127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2473127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2474127178d2SJohan Hedberg 	}
2475392599b9SJohan Hedberg 
2476127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2477769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2478769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2479769be974SMarcel Holtmann 		hci_conn_put(conn);
2480769be974SMarcel Holtmann 	}
2481769be974SMarcel Holtmann 
2482ccd556feSJohan Hedberg unlock:
248341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2484a9de9248SMarcel Holtmann }
2485a9de9248SMarcel Holtmann 
2486a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2487a9de9248SMarcel Holtmann {
2488b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2489b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2490b6a0dc82SMarcel Holtmann 
2491b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2492b6a0dc82SMarcel Holtmann 
2493b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2494b6a0dc82SMarcel Holtmann 
2495b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
24969dc0a3afSMarcel Holtmann 	if (!conn) {
24979dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
24989dc0a3afSMarcel Holtmann 			goto unlock;
24999dc0a3afSMarcel Holtmann 
25009dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2501b6a0dc82SMarcel Holtmann 		if (!conn)
2502b6a0dc82SMarcel Holtmann 			goto unlock;
2503b6a0dc82SMarcel Holtmann 
25049dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
25059dc0a3afSMarcel Holtmann 	}
25069dc0a3afSMarcel Holtmann 
2507732547f9SMarcel Holtmann 	switch (ev->status) {
2508732547f9SMarcel Holtmann 	case 0x00:
2509732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2510732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2511732547f9SMarcel Holtmann 
25129eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2513732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2514732547f9SMarcel Holtmann 		break;
2515732547f9SMarcel Holtmann 
2516705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2517732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
25181038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2519732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2520732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2521efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2522efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2523efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2524efc7688bSMarcel Holtmann 			goto unlock;
2525efc7688bSMarcel Holtmann 		}
2526732547f9SMarcel Holtmann 		/* fall through */
2527efc7688bSMarcel Holtmann 
2528732547f9SMarcel Holtmann 	default:
2529b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2530732547f9SMarcel Holtmann 		break;
2531732547f9SMarcel Holtmann 	}
2532b6a0dc82SMarcel Holtmann 
2533b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2534b6a0dc82SMarcel Holtmann 	if (ev->status)
2535b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2536b6a0dc82SMarcel Holtmann 
2537b6a0dc82SMarcel Holtmann unlock:
2538b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2539a9de9248SMarcel Holtmann }
2540a9de9248SMarcel Holtmann 
2541a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2542a9de9248SMarcel Holtmann {
2543a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2544a9de9248SMarcel Holtmann }
2545a9de9248SMarcel Holtmann 
254604837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
254704837f64SMarcel Holtmann {
2548a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
254904837f64SMarcel Holtmann 
255004837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
255104837f64SMarcel Holtmann }
255204837f64SMarcel Holtmann 
2553a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2554a9de9248SMarcel Holtmann {
2555a9de9248SMarcel Holtmann 	struct inquiry_data data;
2556a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2557a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2558a9de9248SMarcel Holtmann 
2559a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2560a9de9248SMarcel Holtmann 
2561a9de9248SMarcel Holtmann 	if (!num_rsp)
2562a9de9248SMarcel Holtmann 		return;
2563a9de9248SMarcel Holtmann 
2564314b2381SJohan Hedberg 	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
2565314b2381SJohan Hedberg 
2566314b2381SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
2567314b2381SJohan Hedberg 			mgmt_discovering(hdev->id, 1);
2568314b2381SJohan Hedberg 	}
2569314b2381SJohan Hedberg 
2570a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2571a9de9248SMarcel Holtmann 
2572e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2573a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2574a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2575a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2576a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2577a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2578a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2579a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
258041a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2581a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
2582e17acd40SJohan Hedberg 		mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class,
2583e17acd40SJohan Hedberg 						info->rssi, info->data);
2584a9de9248SMarcel Holtmann 	}
2585a9de9248SMarcel Holtmann 
2586a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2587a9de9248SMarcel Holtmann }
2588a9de9248SMarcel Holtmann 
258917fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
259017fa4b9dSJohan Hedberg {
259117fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
259217fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
259317fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
259417fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
259517fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
259617fa4b9dSJohan Hedberg 			return 0x02;
259717fa4b9dSJohan Hedberg 		else
259817fa4b9dSJohan Hedberg 			return 0x03;
259917fa4b9dSJohan Hedberg 	}
260017fa4b9dSJohan Hedberg 
260117fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
260217fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
260358797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
260417fa4b9dSJohan Hedberg 
260517fa4b9dSJohan Hedberg 	return conn->auth_type;
260617fa4b9dSJohan Hedberg }
260717fa4b9dSJohan Hedberg 
26080493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26090493684eSMarcel Holtmann {
26100493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
26110493684eSMarcel Holtmann 	struct hci_conn *conn;
26120493684eSMarcel Holtmann 
26130493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
26140493684eSMarcel Holtmann 
26150493684eSMarcel Holtmann 	hci_dev_lock(hdev);
26160493684eSMarcel Holtmann 
26170493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
261803b555e1SJohan Hedberg 	if (!conn)
261903b555e1SJohan Hedberg 		goto unlock;
262003b555e1SJohan Hedberg 
26210493684eSMarcel Holtmann 	hci_conn_hold(conn);
26220493684eSMarcel Holtmann 
262303b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
262403b555e1SJohan Hedberg 		goto unlock;
262503b555e1SJohan Hedberg 
262603b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
262703b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
262817fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
262917fa4b9dSJohan Hedberg 
263017fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
263117fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
26327cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
26337cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
263417fa4b9dSJohan Hedberg 
2635ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2636ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2637ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2638ce85ee13SSzymon Janc 		else
2639ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2640ce85ee13SSzymon Janc 
264117fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
264217fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
264303b555e1SJohan Hedberg 	} else {
264403b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
264503b555e1SJohan Hedberg 
264603b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
2647be77159cSJohan Hedberg 		cp.reason = 0x18; /* Pairing not allowed */
264803b555e1SJohan Hedberg 
264903b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
265003b555e1SJohan Hedberg 							sizeof(cp), &cp);
265103b555e1SJohan Hedberg 	}
265203b555e1SJohan Hedberg 
265303b555e1SJohan Hedberg unlock:
265403b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
265503b555e1SJohan Hedberg }
265603b555e1SJohan Hedberg 
265703b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
265803b555e1SJohan Hedberg {
265903b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
266003b555e1SJohan Hedberg 	struct hci_conn *conn;
266103b555e1SJohan Hedberg 
266203b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
266303b555e1SJohan Hedberg 
266403b555e1SJohan Hedberg 	hci_dev_lock(hdev);
266503b555e1SJohan Hedberg 
266603b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
266703b555e1SJohan Hedberg 	if (!conn)
266803b555e1SJohan Hedberg 		goto unlock;
266903b555e1SJohan Hedberg 
267003b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
267103b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
267203b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
267303b555e1SJohan Hedberg 
267403b555e1SJohan Hedberg unlock:
26750493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
26760493684eSMarcel Holtmann }
26770493684eSMarcel Holtmann 
2678a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2679a5c29683SJohan Hedberg 							struct sk_buff *skb)
2680a5c29683SJohan Hedberg {
2681a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
268255bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
26837a828908SJohan Hedberg 	struct hci_conn *conn;
2684a5c29683SJohan Hedberg 
2685a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
2686a5c29683SJohan Hedberg 
2687a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
2688a5c29683SJohan Hedberg 
26897a828908SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
26907a828908SJohan Hedberg 		goto unlock;
26917a828908SJohan Hedberg 
26927a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
26937a828908SJohan Hedberg 	if (!conn)
26947a828908SJohan Hedberg 		goto unlock;
26957a828908SJohan Hedberg 
26967a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
26977a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
26987a828908SJohan Hedberg 
26997a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
27007a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
27017a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
27027a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
27037a828908SJohan Hedberg 	 * bit set. */
27047a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
27057a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
27067a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
27077a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
27087a828908SJohan Hedberg 		goto unlock;
27097a828908SJohan Hedberg 	}
27107a828908SJohan Hedberg 
27117a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
27127a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
27137a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
271455bc1a37SJohan Hedberg 
271555bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
271655bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
271755bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
271855bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
271955bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
272055bc1a37SJohan Hedberg 			confirm_hint = 1;
272155bc1a37SJohan Hedberg 			goto confirm;
272255bc1a37SJohan Hedberg 		}
272355bc1a37SJohan Hedberg 
27249f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
27259f61656aSJohan Hedberg 						hdev->auto_accept_delay);
27269f61656aSJohan Hedberg 
27279f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
27289f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
27299f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
27309f61656aSJohan Hedberg 			goto unlock;
27319f61656aSJohan Hedberg 		}
27329f61656aSJohan Hedberg 
27337a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
27347a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
27357a828908SJohan Hedberg 		goto unlock;
27367a828908SJohan Hedberg 	}
27377a828908SJohan Hedberg 
273855bc1a37SJohan Hedberg confirm:
273955bc1a37SJohan Hedberg 	mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey,
274055bc1a37SJohan Hedberg 								confirm_hint);
2741a5c29683SJohan Hedberg 
27427a828908SJohan Hedberg unlock:
2743a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
2744a5c29683SJohan Hedberg }
2745a5c29683SJohan Hedberg 
27460493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
27470493684eSMarcel Holtmann {
27480493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
27490493684eSMarcel Holtmann 	struct hci_conn *conn;
27500493684eSMarcel Holtmann 
27510493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
27520493684eSMarcel Holtmann 
27530493684eSMarcel Holtmann 	hci_dev_lock(hdev);
27540493684eSMarcel Holtmann 
27550493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
27562a611692SJohan Hedberg 	if (!conn)
27572a611692SJohan Hedberg 		goto unlock;
27582a611692SJohan Hedberg 
27592a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
27602a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
27612a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
27622a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
27632a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
27642a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
27652a611692SJohan Hedberg 		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
27662a611692SJohan Hedberg 
27670493684eSMarcel Holtmann 	hci_conn_put(conn);
27680493684eSMarcel Holtmann 
27692a611692SJohan Hedberg unlock:
27700493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
27710493684eSMarcel Holtmann }
27720493684eSMarcel Holtmann 
277341a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
277441a96212SMarcel Holtmann {
277541a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
277641a96212SMarcel Holtmann 	struct inquiry_entry *ie;
277741a96212SMarcel Holtmann 
277841a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
277941a96212SMarcel Holtmann 
278041a96212SMarcel Holtmann 	hci_dev_lock(hdev);
278141a96212SMarcel Holtmann 
2782cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2783cc11b9c1SAndrei Emeltchenko 	if (ie)
278441a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
278541a96212SMarcel Holtmann 
278641a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
278741a96212SMarcel Holtmann }
278841a96212SMarcel Holtmann 
27892763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
27902763eda6SSzymon Janc 							struct sk_buff *skb)
27912763eda6SSzymon Janc {
27922763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
27932763eda6SSzymon Janc 	struct oob_data *data;
27942763eda6SSzymon Janc 
27952763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
27962763eda6SSzymon Janc 
27972763eda6SSzymon Janc 	hci_dev_lock(hdev);
27982763eda6SSzymon Janc 
2799e1ba1f15SSzymon Janc 	if (!test_bit(HCI_MGMT, &hdev->flags))
2800e1ba1f15SSzymon Janc 		goto unlock;
2801e1ba1f15SSzymon Janc 
28022763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
28032763eda6SSzymon Janc 	if (data) {
28042763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
28052763eda6SSzymon Janc 
28062763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
28072763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
28082763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
28092763eda6SSzymon Janc 
28102763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
28112763eda6SSzymon Janc 									&cp);
28122763eda6SSzymon Janc 	} else {
28132763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
28142763eda6SSzymon Janc 
28152763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
28162763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
28172763eda6SSzymon Janc 									&cp);
28182763eda6SSzymon Janc 	}
28192763eda6SSzymon Janc 
2820e1ba1f15SSzymon Janc unlock:
28212763eda6SSzymon Janc 	hci_dev_unlock(hdev);
28222763eda6SSzymon Janc }
28232763eda6SSzymon Janc 
2824fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2825fcd89c09SVille Tervo {
2826fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2827fcd89c09SVille Tervo 	struct hci_conn *conn;
2828fcd89c09SVille Tervo 
2829fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
2830fcd89c09SVille Tervo 
2831fcd89c09SVille Tervo 	hci_dev_lock(hdev);
2832fcd89c09SVille Tervo 
2833fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2834b62f328bSVille Tervo 	if (!conn) {
2835b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2836b62f328bSVille Tervo 		if (!conn) {
2837b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
2838b62f328bSVille Tervo 			hci_dev_unlock(hdev);
2839b62f328bSVille Tervo 			return;
2840b62f328bSVille Tervo 		}
284129b7988aSAndre Guedes 
284229b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
2843b62f328bSVille Tervo 	}
2844fcd89c09SVille Tervo 
2845fcd89c09SVille Tervo 	if (ev->status) {
284683bc71b4SVinicius Costa Gomes 		mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
2847fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
2848fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
2849fcd89c09SVille Tervo 		hci_conn_del(conn);
2850fcd89c09SVille Tervo 		goto unlock;
2851fcd89c09SVille Tervo 	}
2852fcd89c09SVille Tervo 
2853cfafccf7SVinicius Costa Gomes 	mgmt_connected(hdev->id, &ev->bdaddr, conn->type);
285483bc71b4SVinicius Costa Gomes 
28557b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
2856fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
2857fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
2858fcd89c09SVille Tervo 
2859fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
2860fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
2861fcd89c09SVille Tervo 
2862fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
2863fcd89c09SVille Tervo 
2864fcd89c09SVille Tervo unlock:
2865fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
2866fcd89c09SVille Tervo }
2867fcd89c09SVille Tervo 
28689aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
28699aa04c91SAndre Guedes 						struct sk_buff *skb)
28709aa04c91SAndre Guedes {
2871e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
2872e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
28739aa04c91SAndre Guedes 
28749aa04c91SAndre Guedes 	hci_dev_lock(hdev);
28759aa04c91SAndre Guedes 
2876e95beb41SAndre Guedes 	while (num_reports--) {
2877e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
2878e95beb41SAndre Guedes 
28799aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
28809aa04c91SAndre Guedes 
2881e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
28829aa04c91SAndre Guedes 	}
28839aa04c91SAndre Guedes 
28849aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
28859aa04c91SAndre Guedes }
28869aa04c91SAndre Guedes 
2887a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
2888a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
2889a7a595f6SVinicius Costa Gomes {
2890a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
2891a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
2892bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
2893a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
2894bea710feSVinicius Costa Gomes 	struct link_key *ltk;
2895a7a595f6SVinicius Costa Gomes 
2896a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
2897a7a595f6SVinicius Costa Gomes 
2898a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
2899a7a595f6SVinicius Costa Gomes 
2900a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2901bea710feSVinicius Costa Gomes 	if (conn == NULL)
2902bea710feSVinicius Costa Gomes 		goto not_found;
2903a7a595f6SVinicius Costa Gomes 
2904bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
2905bea710feSVinicius Costa Gomes 	if (ltk == NULL)
2906bea710feSVinicius Costa Gomes 		goto not_found;
2907bea710feSVinicius Costa Gomes 
2908bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
2909a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
2910726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
2911a7a595f6SVinicius Costa Gomes 
2912a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
2913a7a595f6SVinicius Costa Gomes 
2914a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
2915bea710feSVinicius Costa Gomes 
2916bea710feSVinicius Costa Gomes 	return;
2917bea710feSVinicius Costa Gomes 
2918bea710feSVinicius Costa Gomes not_found:
2919bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
2920bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
2921bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
2922a7a595f6SVinicius Costa Gomes }
2923a7a595f6SVinicius Costa Gomes 
2924fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2925fcd89c09SVille Tervo {
2926fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
2927fcd89c09SVille Tervo 
2928fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
2929fcd89c09SVille Tervo 
2930fcd89c09SVille Tervo 	switch (le_ev->subevent) {
2931fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
2932fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
2933fcd89c09SVille Tervo 		break;
2934fcd89c09SVille Tervo 
29359aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
29369aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
29379aa04c91SAndre Guedes 		break;
29389aa04c91SAndre Guedes 
2939a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
2940a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
2941a7a595f6SVinicius Costa Gomes 		break;
2942a7a595f6SVinicius Costa Gomes 
2943fcd89c09SVille Tervo 	default:
2944fcd89c09SVille Tervo 		break;
2945fcd89c09SVille Tervo 	}
2946fcd89c09SVille Tervo }
2947fcd89c09SVille Tervo 
29481da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
29491da177e4SLinus Torvalds {
2950a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
2951a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
29521da177e4SLinus Torvalds 
29531da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
29541da177e4SLinus Torvalds 
2955a9de9248SMarcel Holtmann 	switch (event) {
29561da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
29571da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
29581da177e4SLinus Torvalds 		break;
29591da177e4SLinus Torvalds 
29601da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
29611da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
29621da177e4SLinus Torvalds 		break;
29631da177e4SLinus Torvalds 
2964a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
2965a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
296621d9e30eSMarcel Holtmann 		break;
296721d9e30eSMarcel Holtmann 
29681da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
29691da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
29701da177e4SLinus Torvalds 		break;
29711da177e4SLinus Torvalds 
29721da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
29731da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
29741da177e4SLinus Torvalds 		break;
29751da177e4SLinus Torvalds 
29761da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
29771da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
29781da177e4SLinus Torvalds 		break;
29791da177e4SLinus Torvalds 
2980a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
2981a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
2982a9de9248SMarcel Holtmann 		break;
2983a9de9248SMarcel Holtmann 
29841da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
29851da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
29861da177e4SLinus Torvalds 		break;
29871da177e4SLinus Torvalds 
2988a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
2989a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
2990a9de9248SMarcel Holtmann 		break;
2991a9de9248SMarcel Holtmann 
2992a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
2993a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
2994a9de9248SMarcel Holtmann 		break;
2995a9de9248SMarcel Holtmann 
2996a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
2997a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
2998a9de9248SMarcel Holtmann 		break;
2999a9de9248SMarcel Holtmann 
3000a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3001a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3002a9de9248SMarcel Holtmann 		break;
3003a9de9248SMarcel Holtmann 
3004a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3005a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3006a9de9248SMarcel Holtmann 		break;
3007a9de9248SMarcel Holtmann 
3008a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3009a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3010a9de9248SMarcel Holtmann 		break;
3011a9de9248SMarcel Holtmann 
3012a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3013a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3014a9de9248SMarcel Holtmann 		break;
3015a9de9248SMarcel Holtmann 
3016a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3017a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3018a9de9248SMarcel Holtmann 		break;
3019a9de9248SMarcel Holtmann 
3020a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3021a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
30221da177e4SLinus Torvalds 		break;
30231da177e4SLinus Torvalds 
30241da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
30251da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
30261da177e4SLinus Torvalds 		break;
30271da177e4SLinus Torvalds 
30281da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
30291da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
30301da177e4SLinus Torvalds 		break;
30311da177e4SLinus Torvalds 
30321da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
30331da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
30341da177e4SLinus Torvalds 		break;
30351da177e4SLinus Torvalds 
30361da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
30371da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
30381da177e4SLinus Torvalds 		break;
30391da177e4SLinus Torvalds 
3040a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3041a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3042a8746417SMarcel Holtmann 		break;
3043a8746417SMarcel Holtmann 
304485a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
304585a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
304685a1e930SMarcel Holtmann 		break;
304785a1e930SMarcel Holtmann 
3048a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3049a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3050a9de9248SMarcel Holtmann 		break;
3051a9de9248SMarcel Holtmann 
3052a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3053a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3054a9de9248SMarcel Holtmann 		break;
3055a9de9248SMarcel Holtmann 
3056a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3057a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3058a9de9248SMarcel Holtmann 		break;
3059a9de9248SMarcel Holtmann 
3060a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3061a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3062a9de9248SMarcel Holtmann 		break;
3063a9de9248SMarcel Holtmann 
306404837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
306504837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
306604837f64SMarcel Holtmann 		break;
306704837f64SMarcel Holtmann 
3068a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3069a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
30701da177e4SLinus Torvalds 		break;
30711da177e4SLinus Torvalds 
30720493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
30730493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
30740493684eSMarcel Holtmann 		break;
30750493684eSMarcel Holtmann 
307603b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
307703b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
307803b555e1SJohan Hedberg 		break;
307903b555e1SJohan Hedberg 
3080a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3081a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3082a5c29683SJohan Hedberg 		break;
3083a5c29683SJohan Hedberg 
30840493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
30850493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
30860493684eSMarcel Holtmann 		break;
30870493684eSMarcel Holtmann 
308841a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
308941a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
309041a96212SMarcel Holtmann 		break;
309141a96212SMarcel Holtmann 
3092fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3093fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3094fcd89c09SVille Tervo 		break;
3095fcd89c09SVille Tervo 
30962763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
30972763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
30982763eda6SSzymon Janc 		break;
30992763eda6SSzymon Janc 
31001da177e4SLinus Torvalds 	default:
3101a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
31021da177e4SLinus Torvalds 		break;
31031da177e4SLinus Torvalds 	}
31041da177e4SLinus Torvalds 
31051da177e4SLinus Torvalds 	kfree_skb(skb);
31061da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
31071da177e4SLinus Torvalds }
31081da177e4SLinus Torvalds 
31091da177e4SLinus Torvalds /* Generate internal stack event */
31101da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
31111da177e4SLinus Torvalds {
31121da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
31131da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
31141da177e4SLinus Torvalds 	struct sk_buff *skb;
31151da177e4SLinus Torvalds 
31161da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
31171da177e4SLinus Torvalds 	if (!skb)
31181da177e4SLinus Torvalds 		return;
31191da177e4SLinus Torvalds 
31201da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
31211da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
31221da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
31231da177e4SLinus Torvalds 
31241da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
31251da177e4SLinus Torvalds 	ev->type = type;
31261da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
31271da177e4SLinus Torvalds 
3128576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3129a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3130576c7d85SMarcel Holtmann 
31310d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
31321da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3133eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
31341da177e4SLinus Torvalds 	kfree_skb(skb);
31351da177e4SLinus Torvalds }
3136e6100a25SAndre Guedes 
3137669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3138e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3139