xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 37d9ef76)
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 
6189352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
6289352e7dSAndre Guedes 
6356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
64744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 0);
6556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
66a9de9248SMarcel Holtmann 
6723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
68a9de9248SMarcel Holtmann 
69a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
701da177e4SLinus Torvalds }
716bd57416SMarcel Holtmann 
72a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
731da177e4SLinus Torvalds {
74a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
75a9de9248SMarcel Holtmann 
76a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
77a9de9248SMarcel Holtmann 
78a9de9248SMarcel Holtmann 	if (status)
79a9de9248SMarcel Holtmann 		return;
80a9de9248SMarcel Holtmann 
81a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
82a9de9248SMarcel Holtmann }
83a9de9248SMarcel Holtmann 
84a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
85a9de9248SMarcel Holtmann {
86a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
87a9de9248SMarcel Holtmann }
88a9de9248SMarcel Holtmann 
89a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
90a9de9248SMarcel Holtmann {
91a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
921da177e4SLinus Torvalds 	struct hci_conn *conn;
931da177e4SLinus Torvalds 
94a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
951da177e4SLinus Torvalds 
96a9de9248SMarcel Holtmann 	if (rp->status)
97a9de9248SMarcel Holtmann 		return;
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1001da177e4SLinus Torvalds 
101a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1021da177e4SLinus Torvalds 	if (conn) {
103a9de9248SMarcel Holtmann 		if (rp->role)
1041da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1051da177e4SLinus Torvalds 		else
1061da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1071da177e4SLinus Torvalds 	}
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
110a9de9248SMarcel Holtmann }
1111da177e4SLinus Torvalds 
112e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
113e4e8e37cSMarcel Holtmann {
114e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
115e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
116e4e8e37cSMarcel Holtmann 
117e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
118e4e8e37cSMarcel Holtmann 
119e4e8e37cSMarcel Holtmann 	if (rp->status)
120e4e8e37cSMarcel Holtmann 		return;
121e4e8e37cSMarcel Holtmann 
122e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
123e4e8e37cSMarcel Holtmann 
124e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
125e4e8e37cSMarcel Holtmann 	if (conn)
126e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
127e4e8e37cSMarcel Holtmann 
128e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
129e4e8e37cSMarcel Holtmann }
130e4e8e37cSMarcel Holtmann 
131a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
132a9de9248SMarcel Holtmann {
133a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
134a9de9248SMarcel Holtmann 	struct hci_conn *conn;
135a9de9248SMarcel Holtmann 	void *sent;
136a9de9248SMarcel Holtmann 
137a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
138a9de9248SMarcel Holtmann 
139a9de9248SMarcel Holtmann 	if (rp->status)
140a9de9248SMarcel Holtmann 		return;
141a9de9248SMarcel Holtmann 
142a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14304837f64SMarcel Holtmann 	if (!sent)
144a9de9248SMarcel Holtmann 		return;
14504837f64SMarcel Holtmann 
14604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14704837f64SMarcel Holtmann 
148a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
149e4e8e37cSMarcel Holtmann 	if (conn)
15083985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15104837f64SMarcel Holtmann 
15204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1531da177e4SLinus Torvalds }
1541da177e4SLinus Torvalds 
155e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
156e4e8e37cSMarcel Holtmann {
157e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
158e4e8e37cSMarcel Holtmann 
159e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
160e4e8e37cSMarcel Holtmann 
161e4e8e37cSMarcel Holtmann 	if (rp->status)
162e4e8e37cSMarcel Holtmann 		return;
163e4e8e37cSMarcel Holtmann 
164e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
165e4e8e37cSMarcel Holtmann }
166e4e8e37cSMarcel Holtmann 
167e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
168e4e8e37cSMarcel Holtmann {
169e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
170e4e8e37cSMarcel Holtmann 	void *sent;
171e4e8e37cSMarcel Holtmann 
172e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
173e4e8e37cSMarcel Holtmann 
174e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
175e4e8e37cSMarcel Holtmann 	if (!sent)
176e4e8e37cSMarcel Holtmann 		return;
177e4e8e37cSMarcel Holtmann 
178e4e8e37cSMarcel Holtmann 	if (!status)
179e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
180e4e8e37cSMarcel Holtmann 
18123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
182e4e8e37cSMarcel Holtmann }
183e4e8e37cSMarcel Holtmann 
184a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1851da177e4SLinus Torvalds {
186a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
187a9de9248SMarcel Holtmann 
188a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
189a9de9248SMarcel Holtmann 
19010572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19110572132SGustavo F. Padovan 
19223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
193a9de9248SMarcel Holtmann }
194a9de9248SMarcel Holtmann 
195a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
196a9de9248SMarcel Holtmann {
197a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1981da177e4SLinus Torvalds 	void *sent;
1991da177e4SLinus Torvalds 
200a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2011da177e4SLinus Torvalds 
202a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2031da177e4SLinus Torvalds 	if (!sent)
204a9de9248SMarcel Holtmann 		return;
2051da177e4SLinus Torvalds 
20656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
20756e5cb86SJohan Hedberg 
208b312b161SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
209744cf19eSJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
210b312b161SJohan Hedberg 
21156e5cb86SJohan Hedberg 	if (status == 0)
2121f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
21356e5cb86SJohan Hedberg 
21456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
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 {
27736f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
27836f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
279a9de9248SMarcel Holtmann 	void *sent;
2801da177e4SLinus Torvalds 
281a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
282a9de9248SMarcel Holtmann 
283a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2841da177e4SLinus Torvalds 	if (!sent)
285a9de9248SMarcel Holtmann 		return;
2861da177e4SLinus Torvalds 
28736f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
288a9de9248SMarcel Holtmann 
28956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29056e5cb86SJohan Hedberg 
2912d7cee58SJohan Hedberg 	if (status != 0) {
292744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
2932d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
2942d7cee58SJohan Hedberg 		goto done;
2952d7cee58SJohan Hedberg 	}
2962d7cee58SJohan Hedberg 
2979fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
2989fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
299a9de9248SMarcel Holtmann 
30073f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3011da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3029fbcbb45SJohan Hedberg 		if (!old_iscan)
303744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
30416ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
30516ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
30616ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
30716ab91abSJohan Hedberg 									to);
30816ab91abSJohan Hedberg 		}
3099fbcbb45SJohan Hedberg 	} else if (old_iscan)
310744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3111da177e4SLinus Torvalds 
3129fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3131da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3149fbcbb45SJohan Hedberg 		if (!old_pscan)
315744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3169fbcbb45SJohan Hedberg 	} else if (old_pscan)
317744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
318a9de9248SMarcel Holtmann 
31936f7fc7eSJohan Hedberg done:
32056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
32123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3221da177e4SLinus Torvalds }
3231da177e4SLinus Torvalds 
324a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
325a9de9248SMarcel Holtmann {
326a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
327a9de9248SMarcel Holtmann 
328a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
329a9de9248SMarcel Holtmann 
330a9de9248SMarcel Holtmann 	if (rp->status)
331a9de9248SMarcel Holtmann 		return;
332a9de9248SMarcel Holtmann 
333a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
334a9de9248SMarcel Holtmann 
335a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
336a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
337a9de9248SMarcel Holtmann }
338a9de9248SMarcel Holtmann 
339a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
340a9de9248SMarcel Holtmann {
341a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
342a9de9248SMarcel Holtmann 	void *sent;
343a9de9248SMarcel Holtmann 
344a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
345a9de9248SMarcel Holtmann 
346f383f275SMarcel Holtmann 	if (status)
347f383f275SMarcel Holtmann 		return;
348f383f275SMarcel Holtmann 
349a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
350a9de9248SMarcel Holtmann 	if (!sent)
351a9de9248SMarcel Holtmann 		return;
352a9de9248SMarcel Holtmann 
353a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
354a9de9248SMarcel Holtmann }
355a9de9248SMarcel Holtmann 
356a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
357a9de9248SMarcel Holtmann {
358a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
359a9de9248SMarcel Holtmann 	__u16 setting;
360a9de9248SMarcel Holtmann 
361a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
362a9de9248SMarcel Holtmann 
363a9de9248SMarcel Holtmann 	if (rp->status)
364a9de9248SMarcel Holtmann 		return;
365a9de9248SMarcel Holtmann 
366a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
367a9de9248SMarcel Holtmann 
368a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
369a9de9248SMarcel Holtmann 		return;
370a9de9248SMarcel Holtmann 
371a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
372a9de9248SMarcel Holtmann 
373a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
374a9de9248SMarcel Holtmann 
375a9de9248SMarcel Holtmann 	if (hdev->notify) {
376a9de9248SMarcel Holtmann 		tasklet_disable(&hdev->tx_task);
377a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
378a9de9248SMarcel Holtmann 		tasklet_enable(&hdev->tx_task);
379a9de9248SMarcel Holtmann 	}
380a9de9248SMarcel Holtmann }
381a9de9248SMarcel Holtmann 
382a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
383a9de9248SMarcel Holtmann {
384a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
385f383f275SMarcel Holtmann 	__u16 setting;
386a9de9248SMarcel Holtmann 	void *sent;
387a9de9248SMarcel Holtmann 
388a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
389a9de9248SMarcel Holtmann 
390f383f275SMarcel Holtmann 	if (status)
391f383f275SMarcel Holtmann 		return;
392f383f275SMarcel Holtmann 
393a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
394a9de9248SMarcel Holtmann 	if (!sent)
395a9de9248SMarcel Holtmann 		return;
396a9de9248SMarcel Holtmann 
397f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
3981da177e4SLinus Torvalds 
399f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
400f383f275SMarcel Holtmann 		return;
401f383f275SMarcel Holtmann 
4021da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4031da177e4SLinus Torvalds 
404a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4051da177e4SLinus Torvalds 
4061da177e4SLinus Torvalds 	if (hdev->notify) {
4071da177e4SLinus Torvalds 		tasklet_disable(&hdev->tx_task);
4081da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4091da177e4SLinus Torvalds 		tasklet_enable(&hdev->tx_task);
4101da177e4SLinus Torvalds 	}
4111da177e4SLinus Torvalds }
4121da177e4SLinus Torvalds 
413a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4141da177e4SLinus Torvalds {
415a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4161da177e4SLinus Torvalds 
417a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4181da177e4SLinus Torvalds 
41923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4201143e5a6SMarcel Holtmann }
4211143e5a6SMarcel Holtmann 
422333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
423333140b5SMarcel Holtmann {
424333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
425333140b5SMarcel Holtmann 
426333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
427333140b5SMarcel Holtmann 
428333140b5SMarcel Holtmann 	if (rp->status)
429333140b5SMarcel Holtmann 		return;
430333140b5SMarcel Holtmann 
431333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
432333140b5SMarcel Holtmann }
433333140b5SMarcel Holtmann 
434333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
435333140b5SMarcel Holtmann {
436333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
437333140b5SMarcel Holtmann 	void *sent;
438333140b5SMarcel Holtmann 
439333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
440333140b5SMarcel Holtmann 
441333140b5SMarcel Holtmann 	if (status)
442333140b5SMarcel Holtmann 		return;
443333140b5SMarcel Holtmann 
444333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
445333140b5SMarcel Holtmann 	if (!sent)
446333140b5SMarcel Holtmann 		return;
447333140b5SMarcel Holtmann 
448333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
449333140b5SMarcel Holtmann }
450333140b5SMarcel Holtmann 
451d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
452d5859e22SJohan Hedberg {
453d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
454d5859e22SJohan Hedberg 		return 2;
455d5859e22SJohan Hedberg 
456d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
457d5859e22SJohan Hedberg 		return 1;
458d5859e22SJohan Hedberg 
459d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
460d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
461d5859e22SJohan Hedberg 		return 1;
462d5859e22SJohan Hedberg 
463d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
464d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
465d5859e22SJohan Hedberg 			return 1;
466d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
467d5859e22SJohan Hedberg 			return 1;
468d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
469d5859e22SJohan Hedberg 			return 1;
470d5859e22SJohan Hedberg 	}
471d5859e22SJohan Hedberg 
472d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
473d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
474d5859e22SJohan Hedberg 		return 1;
475d5859e22SJohan Hedberg 
476d5859e22SJohan Hedberg 	return 0;
477d5859e22SJohan Hedberg }
478d5859e22SJohan Hedberg 
479d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
480d5859e22SJohan Hedberg {
481d5859e22SJohan Hedberg 	u8 mode;
482d5859e22SJohan Hedberg 
483d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
484d5859e22SJohan Hedberg 
485d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
486d5859e22SJohan Hedberg }
487d5859e22SJohan Hedberg 
488d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
489d5859e22SJohan Hedberg {
490d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
491d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
492d5859e22SJohan Hedberg 	 * command otherwise */
493d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
494d5859e22SJohan Hedberg 
4956de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
4966de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
4976de6c18dSVille Tervo 	if (hdev->lmp_ver <= 1)
4986de6c18dSVille Tervo 		return;
4996de6c18dSVille Tervo 
500d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
501d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
502d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
503d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
504d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
505d5859e22SJohan Hedberg 
506d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
507d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
508d5859e22SJohan Hedberg 
509d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
510d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
511d5859e22SJohan Hedberg 
512d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
513d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
514d5859e22SJohan Hedberg 
515d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
516d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
517d5859e22SJohan Hedberg 
518d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
519d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
520d5859e22SJohan Hedberg 
521d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
522d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
523d5859e22SJohan Hedberg 
524d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
525d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
526d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
527d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
528d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
529d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
530d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
531d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
532d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
533d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
534d5859e22SJohan Hedberg 					 * Features Notification */
535d5859e22SJohan Hedberg 	}
536d5859e22SJohan Hedberg 
537d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
538d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
539d5859e22SJohan Hedberg 
540d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
541d5859e22SJohan Hedberg }
542d5859e22SJohan Hedberg 
543e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
544e6100a25SAndre Guedes {
545e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
546e6100a25SAndre Guedes 
547e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
548e6100a25SAndre Guedes 
549e6100a25SAndre Guedes 	if (enable_le) {
550e6100a25SAndre Guedes 		cp.le = 1;
551e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
552e6100a25SAndre Guedes 	}
553e6100a25SAndre Guedes 
554e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
555e6100a25SAndre Guedes }
556e6100a25SAndre Guedes 
557d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
558d5859e22SJohan Hedberg {
559d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
560d5859e22SJohan Hedberg 
561d5859e22SJohan Hedberg 	if (hdev->lmp_ver > 1)
562d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
563d5859e22SJohan Hedberg 
564d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
565d5859e22SJohan Hedberg 		u8 mode = 0x01;
566d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
567d5859e22SJohan Hedberg 	}
568d5859e22SJohan Hedberg 
569d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
570d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
571d5859e22SJohan Hedberg 
572d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
573d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
574971e3a4bSAndre Guedes 
575971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
576971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
577971e3a4bSAndre Guedes 
578971e3a4bSAndre Guedes 		cp.page = 0x01;
579971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
580971e3a4bSAndre Guedes 							sizeof(cp), &cp);
581971e3a4bSAndre Guedes 	}
582e6100a25SAndre Guedes 
583e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
584e6100a25SAndre Guedes 		hci_set_le_support(hdev);
585d5859e22SJohan Hedberg }
586d5859e22SJohan Hedberg 
587a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
588a9de9248SMarcel Holtmann {
589a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5901143e5a6SMarcel Holtmann 
591a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5921143e5a6SMarcel Holtmann 
593a9de9248SMarcel Holtmann 	if (rp->status)
594a9de9248SMarcel Holtmann 		return;
5951143e5a6SMarcel Holtmann 
596a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
597e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
598d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
599e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
600d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6011da177e4SLinus Torvalds 
602a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
603a9de9248SMarcel Holtmann 					hdev->manufacturer,
604a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
605d5859e22SJohan Hedberg 
606d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
607d5859e22SJohan Hedberg 		hci_setup(hdev);
608d5859e22SJohan Hedberg }
609d5859e22SJohan Hedberg 
610d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
611d5859e22SJohan Hedberg {
612d5859e22SJohan Hedberg 	u16 link_policy = 0;
613d5859e22SJohan Hedberg 
614d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
615d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
616d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
617d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
618d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
619d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
620d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
621d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
622d5859e22SJohan Hedberg 
623d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
624d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
625d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6261da177e4SLinus Torvalds }
6271da177e4SLinus Torvalds 
628a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
629a9de9248SMarcel Holtmann {
630a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
631a9de9248SMarcel Holtmann 
632a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
633a9de9248SMarcel Holtmann 
634a9de9248SMarcel Holtmann 	if (rp->status)
635d5859e22SJohan Hedberg 		goto done;
636a9de9248SMarcel Holtmann 
637a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
638d5859e22SJohan Hedberg 
639d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
640d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
641d5859e22SJohan Hedberg 
642d5859e22SJohan Hedberg done:
643d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
644a9de9248SMarcel Holtmann }
645a9de9248SMarcel Holtmann 
646a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
647a9de9248SMarcel Holtmann {
648a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
649a9de9248SMarcel Holtmann 
650a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
651a9de9248SMarcel Holtmann 
652a9de9248SMarcel Holtmann 	if (rp->status)
653a9de9248SMarcel Holtmann 		return;
654a9de9248SMarcel Holtmann 
655a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6561da177e4SLinus Torvalds 
6571da177e4SLinus Torvalds 	/* Adjust default settings according to features
6581da177e4SLinus Torvalds 	 * supported by device. */
659a9de9248SMarcel Holtmann 
6601da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6611da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6641da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6651da177e4SLinus Torvalds 
6665b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6671da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6685b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6695b7f9909SMarcel Holtmann 	}
6701da177e4SLinus Torvalds 
6715b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6721da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6735b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6745b7f9909SMarcel Holtmann 	}
6755b7f9909SMarcel Holtmann 
6765b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6775b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6785b7f9909SMarcel Holtmann 
6795b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6805b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6815b7f9909SMarcel Holtmann 
6825b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6835b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6841da177e4SLinus Torvalds 
685efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
686efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
687efc7688bSMarcel Holtmann 
688efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
689efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
690efc7688bSMarcel Holtmann 
691efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
692efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
693efc7688bSMarcel Holtmann 
694a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
695a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
696a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
697a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
698a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
6991da177e4SLinus Torvalds }
7001da177e4SLinus Torvalds 
701971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
702971e3a4bSAndre Guedes 							struct sk_buff *skb)
703971e3a4bSAndre Guedes {
704971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
705971e3a4bSAndre Guedes 
706971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
707971e3a4bSAndre Guedes 
708971e3a4bSAndre Guedes 	if (rp->status)
709971e3a4bSAndre Guedes 		return;
710971e3a4bSAndre Guedes 
711971e3a4bSAndre Guedes 	memcpy(hdev->extfeatures, rp->features, 8);
712971e3a4bSAndre Guedes 
713971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
714971e3a4bSAndre Guedes }
715971e3a4bSAndre Guedes 
716a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
717a9de9248SMarcel Holtmann {
718a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
719a9de9248SMarcel Holtmann 
720a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
721a9de9248SMarcel Holtmann 
722a9de9248SMarcel Holtmann 	if (rp->status)
723a9de9248SMarcel Holtmann 		return;
724a9de9248SMarcel Holtmann 
725a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
726a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
727a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
728a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
729da1f5198SMarcel Holtmann 
730da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
731da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
732da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
733da1f5198SMarcel Holtmann 	}
734da1f5198SMarcel Holtmann 
735da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
736da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7371da177e4SLinus Torvalds 
738a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
739a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
740a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7411da177e4SLinus Torvalds }
7421da177e4SLinus Torvalds 
743a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
744a9de9248SMarcel Holtmann {
745a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7461da177e4SLinus Torvalds 
747a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
748a9de9248SMarcel Holtmann 
749a9de9248SMarcel Holtmann 	if (!rp->status)
750a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
751a9de9248SMarcel Holtmann 
75223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
75323bb5763SJohan Hedberg }
75423bb5763SJohan Hedberg 
75523bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
75623bb5763SJohan Hedberg {
75723bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
75823bb5763SJohan Hedberg 
75923bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
76023bb5763SJohan Hedberg 
76123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
7621da177e4SLinus Torvalds }
7631da177e4SLinus Torvalds 
764928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
765928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
766928abaa7SAndrei Emeltchenko {
767928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
768928abaa7SAndrei Emeltchenko 
769928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
770928abaa7SAndrei Emeltchenko 
771928abaa7SAndrei Emeltchenko 	if (rp->status)
772928abaa7SAndrei Emeltchenko 		return;
773928abaa7SAndrei Emeltchenko 
774928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
775928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
776928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
777928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
778928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
779928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
780928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
781928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
782928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
783928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
784928abaa7SAndrei Emeltchenko 
785928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
786928abaa7SAndrei Emeltchenko }
787928abaa7SAndrei Emeltchenko 
788b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
789b0916ea0SJohan Hedberg 							struct sk_buff *skb)
790b0916ea0SJohan Hedberg {
791b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
792b0916ea0SJohan Hedberg 
793b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
794b0916ea0SJohan Hedberg 
795b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
796b0916ea0SJohan Hedberg }
797b0916ea0SJohan Hedberg 
798d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
799d5859e22SJohan Hedberg {
800d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
801d5859e22SJohan Hedberg 
802d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
803d5859e22SJohan Hedberg 
804d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
805d5859e22SJohan Hedberg }
806d5859e22SJohan Hedberg 
807d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
808d5859e22SJohan Hedberg 							struct sk_buff *skb)
809d5859e22SJohan Hedberg {
810d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
811d5859e22SJohan Hedberg 
812d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
813d5859e22SJohan Hedberg 
814d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
815d5859e22SJohan Hedberg }
816d5859e22SJohan Hedberg 
817d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
818d5859e22SJohan Hedberg 							struct sk_buff *skb)
819d5859e22SJohan Hedberg {
820d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
821d5859e22SJohan Hedberg 
822d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
823d5859e22SJohan Hedberg 
824d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
825d5859e22SJohan Hedberg }
826d5859e22SJohan Hedberg 
827d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
828d5859e22SJohan Hedberg {
829d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
830d5859e22SJohan Hedberg 
831d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
832d5859e22SJohan Hedberg 
833d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
834d5859e22SJohan Hedberg }
835d5859e22SJohan Hedberg 
836980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
837980e1a53SJohan Hedberg {
838980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
839980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
840980e1a53SJohan Hedberg 	struct hci_conn *conn;
841980e1a53SJohan Hedberg 
842980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
843980e1a53SJohan Hedberg 
84456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
84556e5cb86SJohan Hedberg 
846980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
847744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
848980e1a53SJohan Hedberg 
849980e1a53SJohan Hedberg 	if (rp->status != 0)
85056e5cb86SJohan Hedberg 		goto unlock;
851980e1a53SJohan Hedberg 
852980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
853980e1a53SJohan Hedberg 	if (!cp)
85456e5cb86SJohan Hedberg 		goto unlock;
855980e1a53SJohan Hedberg 
856980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
857980e1a53SJohan Hedberg 	if (conn)
858980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
85956e5cb86SJohan Hedberg 
86056e5cb86SJohan Hedberg unlock:
86156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
862980e1a53SJohan Hedberg }
863980e1a53SJohan Hedberg 
864980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
865980e1a53SJohan Hedberg {
866980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
867980e1a53SJohan Hedberg 
868980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
869980e1a53SJohan Hedberg 
87056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
87156e5cb86SJohan Hedberg 
872980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
873744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
874980e1a53SJohan Hedberg 								rp->status);
87556e5cb86SJohan Hedberg 
87656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
877980e1a53SJohan Hedberg }
87856e5cb86SJohan Hedberg 
8796ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8806ed58ec5SVille Tervo 				       struct sk_buff *skb)
8816ed58ec5SVille Tervo {
8826ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
8836ed58ec5SVille Tervo 
8846ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
8856ed58ec5SVille Tervo 
8866ed58ec5SVille Tervo 	if (rp->status)
8876ed58ec5SVille Tervo 		return;
8886ed58ec5SVille Tervo 
8896ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
8906ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8916ed58ec5SVille Tervo 
8926ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8936ed58ec5SVille Tervo 
8946ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8956ed58ec5SVille Tervo 
8966ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
8976ed58ec5SVille Tervo }
898980e1a53SJohan Hedberg 
899a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
900a5c29683SJohan Hedberg {
901a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
902a5c29683SJohan Hedberg 
903a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
904a5c29683SJohan Hedberg 
90556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
90656e5cb86SJohan Hedberg 
907a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
908744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
909a5c29683SJohan Hedberg 								rp->status);
91056e5cb86SJohan Hedberg 
91156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
912a5c29683SJohan Hedberg }
913a5c29683SJohan Hedberg 
914a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
915a5c29683SJohan Hedberg 							struct sk_buff *skb)
916a5c29683SJohan Hedberg {
917a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
918a5c29683SJohan Hedberg 
919a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
920a5c29683SJohan Hedberg 
92156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92256e5cb86SJohan Hedberg 
923a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
924744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
925a5c29683SJohan Hedberg 								rp->status);
92656e5cb86SJohan Hedberg 
92756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
928a5c29683SJohan Hedberg }
929a5c29683SJohan Hedberg 
930c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
931c35938b2SSzymon Janc 							struct sk_buff *skb)
932c35938b2SSzymon Janc {
933c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
934c35938b2SSzymon Janc 
935c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
936c35938b2SSzymon Janc 
93756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
938744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
939c35938b2SSzymon Janc 						rp->randomizer, rp->status);
94056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
941c35938b2SSzymon Janc }
942c35938b2SSzymon Janc 
943eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
944eb9d91f5SAndre Guedes 					struct sk_buff *skb)
945eb9d91f5SAndre Guedes {
946eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
947eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
948eb9d91f5SAndre Guedes 
949eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
950eb9d91f5SAndre Guedes 
951eb9d91f5SAndre Guedes 	if (status)
952eb9d91f5SAndre Guedes 		return;
953eb9d91f5SAndre Guedes 
954eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
955eb9d91f5SAndre Guedes 	if (!cp)
956eb9d91f5SAndre Guedes 		return;
957eb9d91f5SAndre Guedes 
95835815085SAndre Guedes 	if (cp->enable == 0x01) {
95935815085SAndre Guedes 		del_timer(&hdev->adv_timer);
960a8f13c8cSAndre Guedes 
961a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
962eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
963a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
96435815085SAndre Guedes 	} else if (cp->enable == 0x00) {
96535815085SAndre Guedes 		mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
96635815085SAndre Guedes 	}
967eb9d91f5SAndre Guedes }
968eb9d91f5SAndre Guedes 
969a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
970a7a595f6SVinicius Costa Gomes {
971a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
972a7a595f6SVinicius Costa Gomes 
973a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
974a7a595f6SVinicius Costa Gomes 
975a7a595f6SVinicius Costa Gomes 	if (rp->status)
976a7a595f6SVinicius Costa Gomes 		return;
977a7a595f6SVinicius Costa Gomes 
978a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
979a7a595f6SVinicius Costa Gomes }
980a7a595f6SVinicius Costa Gomes 
981a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
982a7a595f6SVinicius Costa Gomes {
983a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
984a7a595f6SVinicius Costa Gomes 
985a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
986a7a595f6SVinicius Costa Gomes 
987a7a595f6SVinicius Costa Gomes 	if (rp->status)
988a7a595f6SVinicius Costa Gomes 		return;
989a7a595f6SVinicius Costa Gomes 
990a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
991a7a595f6SVinicius Costa Gomes }
992a7a595f6SVinicius Costa Gomes 
993f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
994f9b49306SAndre Guedes 							struct sk_buff *skb)
995f9b49306SAndre Guedes {
996f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
997f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
998f9b49306SAndre Guedes 
999f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1000f9b49306SAndre Guedes 
1001f9b49306SAndre Guedes 	if (status)
1002f9b49306SAndre Guedes 		return;
1003f9b49306SAndre Guedes 
1004f9b49306SAndre Guedes 	cp.page = 0x01;
1005f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1006f9b49306SAndre Guedes }
1007f9b49306SAndre Guedes 
1008a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1009a9de9248SMarcel Holtmann {
1010a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1011a9de9248SMarcel Holtmann 
1012a9de9248SMarcel Holtmann 	if (status) {
101323bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1014a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
101556e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1016164a6e78SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
1017744cf19eSJohan Hedberg 			mgmt_inquiry_failed(hdev, status);
101856e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1019314b2381SJohan Hedberg 		return;
1020314b2381SJohan Hedberg 	}
1021314b2381SJohan Hedberg 
102289352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
102389352e7dSAndre Guedes 
102456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1025744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 1);
102656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1027a9de9248SMarcel Holtmann }
1028a9de9248SMarcel Holtmann 
10291da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
10301da177e4SLinus Torvalds {
1031a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
10321da177e4SLinus Torvalds 	struct hci_conn *conn;
10331da177e4SLinus Torvalds 
1034a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1035a9de9248SMarcel Holtmann 
1036a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
10371da177e4SLinus Torvalds 	if (!cp)
10381da177e4SLinus Torvalds 		return;
10391da177e4SLinus Torvalds 
10401da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10411da177e4SLinus Torvalds 
10421da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
10431da177e4SLinus Torvalds 
1044a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
10451da177e4SLinus Torvalds 
10461da177e4SLinus Torvalds 	if (status) {
10471da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
10484c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
10491da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
10501da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
10511da177e4SLinus Torvalds 				hci_conn_del(conn);
10524c67bc74SMarcel Holtmann 			} else
10534c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
10541da177e4SLinus Torvalds 		}
10551da177e4SLinus Torvalds 	} else {
10561da177e4SLinus Torvalds 		if (!conn) {
10571da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
10581da177e4SLinus Torvalds 			if (conn) {
10591da177e4SLinus Torvalds 				conn->out = 1;
10601da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
10611da177e4SLinus Torvalds 			} else
1062893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
10631da177e4SLinus Torvalds 		}
10641da177e4SLinus Torvalds 	}
10651da177e4SLinus Torvalds 
10661da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10671da177e4SLinus Torvalds }
10681da177e4SLinus Torvalds 
1069a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
10701da177e4SLinus Torvalds {
1071a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
10721da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
10731da177e4SLinus Torvalds 	__u16 handle;
10741da177e4SLinus Torvalds 
1075b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1076b6a0dc82SMarcel Holtmann 
1077a9de9248SMarcel Holtmann 	if (!status)
1078a9de9248SMarcel Holtmann 		return;
1079a9de9248SMarcel Holtmann 
1080a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
10811da177e4SLinus Torvalds 	if (!cp)
1082a9de9248SMarcel Holtmann 		return;
10831da177e4SLinus Torvalds 
10841da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
10851da177e4SLinus Torvalds 
1086a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
10871da177e4SLinus Torvalds 
10881da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10891da177e4SLinus Torvalds 
10901da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
10915a08ecceSAndrei Emeltchenko 	if (acl) {
10925a08ecceSAndrei Emeltchenko 		sco = acl->link;
10935a08ecceSAndrei Emeltchenko 		if (sco) {
10941da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
10951da177e4SLinus Torvalds 
10961da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
10971da177e4SLinus Torvalds 			hci_conn_del(sco);
10981da177e4SLinus Torvalds 		}
10995a08ecceSAndrei Emeltchenko 	}
11001da177e4SLinus Torvalds 
11011da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11021da177e4SLinus Torvalds }
11031da177e4SLinus Torvalds 
1104f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1105f8558555SMarcel Holtmann {
1106f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1107f8558555SMarcel Holtmann 	struct hci_conn *conn;
1108f8558555SMarcel Holtmann 
1109f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1110f8558555SMarcel Holtmann 
1111f8558555SMarcel Holtmann 	if (!status)
1112f8558555SMarcel Holtmann 		return;
1113f8558555SMarcel Holtmann 
1114f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1115f8558555SMarcel Holtmann 	if (!cp)
1116f8558555SMarcel Holtmann 		return;
1117f8558555SMarcel Holtmann 
1118f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1119f8558555SMarcel Holtmann 
1120f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1121f8558555SMarcel Holtmann 	if (conn) {
1122f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1123f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1124f8558555SMarcel Holtmann 			hci_conn_put(conn);
1125f8558555SMarcel Holtmann 		}
1126f8558555SMarcel Holtmann 	}
1127f8558555SMarcel Holtmann 
1128f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1129f8558555SMarcel Holtmann }
1130f8558555SMarcel Holtmann 
1131f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1132f8558555SMarcel Holtmann {
1133f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1134f8558555SMarcel Holtmann 	struct hci_conn *conn;
1135f8558555SMarcel Holtmann 
1136f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1137f8558555SMarcel Holtmann 
1138f8558555SMarcel Holtmann 	if (!status)
1139f8558555SMarcel Holtmann 		return;
1140f8558555SMarcel Holtmann 
1141f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1142f8558555SMarcel Holtmann 	if (!cp)
1143f8558555SMarcel Holtmann 		return;
1144f8558555SMarcel Holtmann 
1145f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1146f8558555SMarcel Holtmann 
1147f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1148f8558555SMarcel Holtmann 	if (conn) {
1149f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1150f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1151f8558555SMarcel Holtmann 			hci_conn_put(conn);
1152f8558555SMarcel Holtmann 		}
1153f8558555SMarcel Holtmann 	}
1154f8558555SMarcel Holtmann 
1155f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1156f8558555SMarcel Holtmann }
1157f8558555SMarcel Holtmann 
1158127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1159392599b9SJohan Hedberg 							struct hci_conn *conn)
1160392599b9SJohan Hedberg {
1161392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1162392599b9SJohan Hedberg 		return 0;
1163392599b9SJohan Hedberg 
1164765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1165392599b9SJohan Hedberg 		return 0;
1166392599b9SJohan Hedberg 
1167392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1168e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1169392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1170e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1171e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1172392599b9SJohan Hedberg 		return 0;
1173392599b9SJohan Hedberg 
1174392599b9SJohan Hedberg 	return 1;
1175392599b9SJohan Hedberg }
1176392599b9SJohan Hedberg 
1177a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
11781da177e4SLinus Torvalds {
1179127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1180127178d2SJohan Hedberg 	struct hci_conn *conn;
1181127178d2SJohan Hedberg 
1182a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1183127178d2SJohan Hedberg 
1184127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1185127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1186127178d2SJohan Hedberg 	if (!status)
1187127178d2SJohan Hedberg 		return;
1188127178d2SJohan Hedberg 
1189127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1190127178d2SJohan Hedberg 	if (!cp)
1191127178d2SJohan Hedberg 		return;
1192127178d2SJohan Hedberg 
1193127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1194127178d2SJohan Hedberg 
1195127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
119679c6c70cSJohan Hedberg 	if (!conn)
119779c6c70cSJohan Hedberg 		goto unlock;
119879c6c70cSJohan Hedberg 
119979c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
120079c6c70cSJohan Hedberg 		goto unlock;
120179c6c70cSJohan Hedberg 
120279c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1203127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1204127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1205127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1206127178d2SJohan Hedberg 	}
1207127178d2SJohan Hedberg 
120879c6c70cSJohan Hedberg unlock:
1209127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1210a9de9248SMarcel Holtmann }
12111da177e4SLinus Torvalds 
1212769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1213769be974SMarcel Holtmann {
1214769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1215769be974SMarcel Holtmann 	struct hci_conn *conn;
1216769be974SMarcel Holtmann 
1217769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1218769be974SMarcel Holtmann 
1219769be974SMarcel Holtmann 	if (!status)
1220769be974SMarcel Holtmann 		return;
1221769be974SMarcel Holtmann 
1222769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1223769be974SMarcel Holtmann 	if (!cp)
1224769be974SMarcel Holtmann 		return;
1225769be974SMarcel Holtmann 
1226769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1227769be974SMarcel Holtmann 
1228769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1229769be974SMarcel Holtmann 	if (conn) {
1230769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1231769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1232769be974SMarcel Holtmann 			hci_conn_put(conn);
1233769be974SMarcel Holtmann 		}
1234769be974SMarcel Holtmann 	}
1235769be974SMarcel Holtmann 
1236769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1237769be974SMarcel Holtmann }
1238769be974SMarcel Holtmann 
1239769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1240769be974SMarcel Holtmann {
1241769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1242769be974SMarcel Holtmann 	struct hci_conn *conn;
1243769be974SMarcel Holtmann 
1244769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1245769be974SMarcel Holtmann 
1246769be974SMarcel Holtmann 	if (!status)
1247769be974SMarcel Holtmann 		return;
1248769be974SMarcel Holtmann 
1249769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1250769be974SMarcel Holtmann 	if (!cp)
1251769be974SMarcel Holtmann 		return;
1252769be974SMarcel Holtmann 
1253769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1254769be974SMarcel Holtmann 
1255769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1256769be974SMarcel Holtmann 	if (conn) {
1257769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1258769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1259769be974SMarcel Holtmann 			hci_conn_put(conn);
1260769be974SMarcel Holtmann 		}
1261769be974SMarcel Holtmann 	}
1262769be974SMarcel Holtmann 
1263769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1264769be974SMarcel Holtmann }
1265769be974SMarcel Holtmann 
1266a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1267a9de9248SMarcel Holtmann {
1268b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1269b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1270b6a0dc82SMarcel Holtmann 	__u16 handle;
1271b6a0dc82SMarcel Holtmann 
1272a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1273b6a0dc82SMarcel Holtmann 
1274b6a0dc82SMarcel Holtmann 	if (!status)
1275b6a0dc82SMarcel Holtmann 		return;
1276b6a0dc82SMarcel Holtmann 
1277b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1278b6a0dc82SMarcel Holtmann 	if (!cp)
1279b6a0dc82SMarcel Holtmann 		return;
1280b6a0dc82SMarcel Holtmann 
1281b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1282b6a0dc82SMarcel Holtmann 
1283b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1284b6a0dc82SMarcel Holtmann 
1285b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1286b6a0dc82SMarcel Holtmann 
1287b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12885a08ecceSAndrei Emeltchenko 	if (acl) {
12895a08ecceSAndrei Emeltchenko 		sco = acl->link;
12905a08ecceSAndrei Emeltchenko 		if (sco) {
1291b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1292b6a0dc82SMarcel Holtmann 
1293b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1294b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1295b6a0dc82SMarcel Holtmann 		}
12965a08ecceSAndrei Emeltchenko 	}
1297b6a0dc82SMarcel Holtmann 
1298b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1299a9de9248SMarcel Holtmann }
1300a9de9248SMarcel Holtmann 
1301a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1302a9de9248SMarcel Holtmann {
1303a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
130404837f64SMarcel Holtmann 	struct hci_conn *conn;
130504837f64SMarcel Holtmann 
1306a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1307a9de9248SMarcel Holtmann 
1308a9de9248SMarcel Holtmann 	if (!status)
1309a9de9248SMarcel Holtmann 		return;
1310a9de9248SMarcel Holtmann 
1311a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
131204837f64SMarcel Holtmann 	if (!cp)
1313a9de9248SMarcel Holtmann 		return;
131404837f64SMarcel Holtmann 
131504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
131604837f64SMarcel Holtmann 
131704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1318e73439d8SMarcel Holtmann 	if (conn) {
131904837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
132004837f64SMarcel Holtmann 
1321e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1322e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1323e73439d8SMarcel Holtmann 	}
1324e73439d8SMarcel Holtmann 
132504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
132604837f64SMarcel Holtmann }
132704837f64SMarcel Holtmann 
1328a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1329a9de9248SMarcel Holtmann {
1330a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
133104837f64SMarcel Holtmann 	struct hci_conn *conn;
133204837f64SMarcel Holtmann 
1333a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1334a9de9248SMarcel Holtmann 
1335a9de9248SMarcel Holtmann 	if (!status)
1336a9de9248SMarcel Holtmann 		return;
1337a9de9248SMarcel Holtmann 
1338a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
133904837f64SMarcel Holtmann 	if (!cp)
1340a9de9248SMarcel Holtmann 		return;
134104837f64SMarcel Holtmann 
134204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
134304837f64SMarcel Holtmann 
134404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1345e73439d8SMarcel Holtmann 	if (conn) {
134604837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
134704837f64SMarcel Holtmann 
1348e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1349e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1350e73439d8SMarcel Holtmann 	}
1351e73439d8SMarcel Holtmann 
135204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
135304837f64SMarcel Holtmann }
135404837f64SMarcel Holtmann 
1355fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1356fcd89c09SVille Tervo {
1357fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1358fcd89c09SVille Tervo 	struct hci_conn *conn;
1359fcd89c09SVille Tervo 
1360fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1361fcd89c09SVille Tervo 
1362fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1363fcd89c09SVille Tervo 	if (!cp)
1364fcd89c09SVille Tervo 		return;
1365fcd89c09SVille Tervo 
1366fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1367fcd89c09SVille Tervo 
1368fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1369fcd89c09SVille Tervo 
1370fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1371fcd89c09SVille Tervo 		conn);
1372fcd89c09SVille Tervo 
1373fcd89c09SVille Tervo 	if (status) {
1374fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1375fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1376fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1377fcd89c09SVille Tervo 			hci_conn_del(conn);
1378fcd89c09SVille Tervo 		}
1379fcd89c09SVille Tervo 	} else {
1380fcd89c09SVille Tervo 		if (!conn) {
1381fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
138229b7988aSAndre Guedes 			if (conn) {
138329b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1384fcd89c09SVille Tervo 				conn->out = 1;
138529b7988aSAndre Guedes 			} else {
1386fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1387fcd89c09SVille Tervo 			}
1388fcd89c09SVille Tervo 		}
138929b7988aSAndre Guedes 	}
1390fcd89c09SVille Tervo 
1391fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1392fcd89c09SVille Tervo }
1393fcd89c09SVille Tervo 
1394a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1395a7a595f6SVinicius Costa Gomes {
1396a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1397a7a595f6SVinicius Costa Gomes }
1398a7a595f6SVinicius Costa Gomes 
13991da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14001da177e4SLinus Torvalds {
14011da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
14021da177e4SLinus Torvalds 
14031da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
14041da177e4SLinus Torvalds 
140523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
14066bd57416SMarcel Holtmann 
1407a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
140889352e7dSAndre Guedes 
140989352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
141089352e7dSAndre Guedes 		return;
141189352e7dSAndre Guedes 
141256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1413744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 0);
141456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
14151da177e4SLinus Torvalds }
14161da177e4SLinus Torvalds 
14171da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
14181da177e4SLinus Torvalds {
141945bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1420a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
14211da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
14221da177e4SLinus Torvalds 
14231da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
14241da177e4SLinus Torvalds 
142545bb4bf0SMarcel Holtmann 	if (!num_rsp)
142645bb4bf0SMarcel Holtmann 		return;
142745bb4bf0SMarcel Holtmann 
14281da177e4SLinus Torvalds 	hci_dev_lock(hdev);
142945bb4bf0SMarcel Holtmann 
1430e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
14311da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
14321da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
14331da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
14341da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
14351da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
14361da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
14371da177e4SLinus Torvalds 		data.rssi		= 0x00;
143841a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
14391da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
144048264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
14414c659c39SJohan Hedberg 						info->dev_class, 0, NULL);
14421da177e4SLinus Torvalds 	}
144345bb4bf0SMarcel Holtmann 
14441da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14451da177e4SLinus Torvalds }
14461da177e4SLinus Torvalds 
1447a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14481da177e4SLinus Torvalds {
1449a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1450a9de9248SMarcel Holtmann 	struct hci_conn *conn;
14511da177e4SLinus Torvalds 
1452a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
145345bb4bf0SMarcel Holtmann 
14541da177e4SLinus Torvalds 	hci_dev_lock(hdev);
145545bb4bf0SMarcel Holtmann 
1456a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
14579499237aSMarcel Holtmann 	if (!conn) {
14589499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
14599499237aSMarcel Holtmann 			goto unlock;
14609499237aSMarcel Holtmann 
14619499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1462a9de9248SMarcel Holtmann 		if (!conn)
1463a9de9248SMarcel Holtmann 			goto unlock;
146445bb4bf0SMarcel Holtmann 
14659499237aSMarcel Holtmann 		conn->type = SCO_LINK;
14669499237aSMarcel Holtmann 	}
14679499237aSMarcel Holtmann 
1468a9de9248SMarcel Holtmann 	if (!ev->status) {
1469a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1470769be974SMarcel Holtmann 
1471769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1472769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1473769be974SMarcel Holtmann 			hci_conn_hold(conn);
1474052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
147548264f06SJohan Hedberg 			mgmt_connected(hdev, &ev->bdaddr, conn->type,
147648264f06SJohan Hedberg 							conn->dst_type);
1477769be974SMarcel Holtmann 		} else
1478a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1479a9de9248SMarcel Holtmann 
14809eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
14817d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
14827d0db0a3SMarcel Holtmann 
1483a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1484a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1485a9de9248SMarcel Holtmann 
1486a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1487a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1488a9de9248SMarcel Holtmann 
1489a9de9248SMarcel Holtmann 		/* Get remote features */
1490a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1491a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1492a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1493769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1494769be974SMarcel Holtmann 							sizeof(cp), &cp);
149545bb4bf0SMarcel Holtmann 		}
1496a9de9248SMarcel Holtmann 
1497a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1498a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
1499a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1500a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1501a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1502a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1503a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1504a9de9248SMarcel Holtmann 		}
150517d5c04cSJohan Hedberg 	} else {
1506a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
150717d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1508744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
150948264f06SJohan Hedberg 						conn->dst_type, ev->status);
151017d5c04cSJohan Hedberg 	}
151145bb4bf0SMarcel Holtmann 
1512e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1513e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
151445bb4bf0SMarcel Holtmann 
1515769be974SMarcel Holtmann 	if (ev->status) {
1516a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1517a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1518c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1519c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1520a9de9248SMarcel Holtmann 
1521a9de9248SMarcel Holtmann unlock:
15221da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1523a9de9248SMarcel Holtmann 
1524a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
15251da177e4SLinus Torvalds }
15261da177e4SLinus Torvalds 
15271da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
15281da177e4SLinus Torvalds {
1529a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
15301da177e4SLinus Torvalds 	int mask = hdev->link_mode;
15311da177e4SLinus Torvalds 
1532a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
15331da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
15341da177e4SLinus Torvalds 
15351da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
15361da177e4SLinus Torvalds 
1537138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1538138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
15391da177e4SLinus Torvalds 		/* Connection accepted */
1540c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
15411da177e4SLinus Torvalds 		struct hci_conn *conn;
15421da177e4SLinus Torvalds 
15431da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1544b6a0dc82SMarcel Holtmann 
1545cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1546cc11b9c1SAndrei Emeltchenko 		if (ie)
1547c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1548c7bdd502SMarcel Holtmann 
15491da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
15501da177e4SLinus Torvalds 		if (!conn) {
1551cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1552cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1553893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
15541da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
15551da177e4SLinus Torvalds 				return;
15561da177e4SLinus Torvalds 			}
15571da177e4SLinus Torvalds 		}
1558b6a0dc82SMarcel Holtmann 
15591da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
15601da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1561b6a0dc82SMarcel Holtmann 
15621da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
15631da177e4SLinus Torvalds 
1564b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1565b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1566b6a0dc82SMarcel Holtmann 
15671da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
15681da177e4SLinus Torvalds 
15691da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
15701da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
15711da177e4SLinus Torvalds 			else
15721da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
15731da177e4SLinus Torvalds 
1574b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1575b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1576b6a0dc82SMarcel Holtmann 		} else {
1577b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1578b6a0dc82SMarcel Holtmann 
1579b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1580a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1581b6a0dc82SMarcel Holtmann 
1582b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1583b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1584b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1585b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1586b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1587b6a0dc82SMarcel Holtmann 
1588b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1589b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1590b6a0dc82SMarcel Holtmann 		}
15911da177e4SLinus Torvalds 	} else {
15921da177e4SLinus Torvalds 		/* Connection rejected */
15931da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
15941da177e4SLinus Torvalds 
15951da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
15969f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1597a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
15981da177e4SLinus Torvalds 	}
15991da177e4SLinus Torvalds }
16001da177e4SLinus Torvalds 
16011da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16021da177e4SLinus Torvalds {
1603a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
160404837f64SMarcel Holtmann 	struct hci_conn *conn;
16051da177e4SLinus Torvalds 
16061da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
16071da177e4SLinus Torvalds 
16081da177e4SLinus Torvalds 	hci_dev_lock(hdev);
16091da177e4SLinus Torvalds 
161004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1611f7520543SJohan Hedberg 	if (!conn)
1612f7520543SJohan Hedberg 		goto unlock;
1613f7520543SJohan Hedberg 
161437d9ef76SJohan Hedberg 	if (ev->status == 0)
16151da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
16167d0db0a3SMarcel Holtmann 
161737d9ef76SJohan Hedberg 	if (conn->type == ACL_LINK || conn->type == LE_LINK) {
161837d9ef76SJohan Hedberg 		if (ev->status != 0)
161937d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
162037d9ef76SJohan Hedberg 		else
162148264f06SJohan Hedberg 			mgmt_disconnected(hdev, &conn->dst, conn->type,
162248264f06SJohan Hedberg 							conn->dst_type);
162337d9ef76SJohan Hedberg 	}
1624f7520543SJohan Hedberg 
162537d9ef76SJohan Hedberg 	if (ev->status == 0) {
16262950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
16271da177e4SLinus Torvalds 		hci_conn_del(conn);
162837d9ef76SJohan Hedberg 	}
16291da177e4SLinus Torvalds 
1630f7520543SJohan Hedberg unlock:
16311da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16321da177e4SLinus Torvalds }
16331da177e4SLinus Torvalds 
1634a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1635a9de9248SMarcel Holtmann {
1636a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1637a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1638a9de9248SMarcel Holtmann 
1639a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1640a9de9248SMarcel Holtmann 
1641a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1642a9de9248SMarcel Holtmann 
1643a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1644d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1645d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1646d7556e20SWaldemar Rymarkiewicz 
1647765c2a96SJohan Hedberg 	if (!ev->status) {
164819f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1649d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1650d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
165119f8def0SWaldemar Rymarkiewicz 		} else {
1652a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1653765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
165419f8def0SWaldemar Rymarkiewicz 		}
16552a611692SJohan Hedberg 	} else {
1656744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
16572a611692SJohan Hedberg 	}
1658a9de9248SMarcel Holtmann 
1659a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
166019f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1661a9de9248SMarcel Holtmann 
1662f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1663d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1664f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1665f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1666f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1667d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1668d7556e20SWaldemar Rymarkiewicz 									&cp);
1669f8558555SMarcel Holtmann 		} else {
1670f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1671f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1672f8558555SMarcel Holtmann 			hci_conn_put(conn);
1673f8558555SMarcel Holtmann 		}
1674052b30b0SMarcel Holtmann 	} else {
1675a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1676a9de9248SMarcel Holtmann 
1677052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1678052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1679052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1680052b30b0SMarcel Holtmann 	}
1681052b30b0SMarcel Holtmann 
1682a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1683a9de9248SMarcel Holtmann 		if (!ev->status) {
1684a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1685f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1686f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1687d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1688d7556e20SWaldemar Rymarkiewicz 									&cp);
1689a9de9248SMarcel Holtmann 		} else {
1690a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1691a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1692a9de9248SMarcel Holtmann 		}
1693a9de9248SMarcel Holtmann 	}
1694a9de9248SMarcel Holtmann 
1695d7556e20SWaldemar Rymarkiewicz unlock:
1696a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1697a9de9248SMarcel Holtmann }
1698a9de9248SMarcel Holtmann 
1699a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1700a9de9248SMarcel Holtmann {
1701127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1702127178d2SJohan Hedberg 	struct hci_conn *conn;
1703127178d2SJohan Hedberg 
1704a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1705a9de9248SMarcel Holtmann 
1706a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1707127178d2SJohan Hedberg 
1708127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1709127178d2SJohan Hedberg 
1710a88a9652SJohan Hedberg 	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
1711744cf19eSJohan Hedberg 		mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
1712a88a9652SJohan Hedberg 
1713127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
171479c6c70cSJohan Hedberg 	if (!conn)
171579c6c70cSJohan Hedberg 		goto unlock;
171679c6c70cSJohan Hedberg 
171779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
171879c6c70cSJohan Hedberg 		goto unlock;
171979c6c70cSJohan Hedberg 
172079c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1721127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1722127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1723127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1724127178d2SJohan Hedberg 	}
1725127178d2SJohan Hedberg 
172679c6c70cSJohan Hedberg unlock:
1727127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1728a9de9248SMarcel Holtmann }
1729a9de9248SMarcel Holtmann 
1730a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1731a9de9248SMarcel Holtmann {
1732a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1733a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1734a9de9248SMarcel Holtmann 
1735a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1736a9de9248SMarcel Holtmann 
1737a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1738a9de9248SMarcel Holtmann 
1739a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1740a9de9248SMarcel Holtmann 	if (conn) {
1741a9de9248SMarcel Holtmann 		if (!ev->status) {
1742ae293196SMarcel Holtmann 			if (ev->encrypt) {
1743ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1744ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1745a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1746da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1747ae293196SMarcel Holtmann 			} else
1748a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1749a9de9248SMarcel Holtmann 		}
1750a9de9248SMarcel Holtmann 
1751a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1752a9de9248SMarcel Holtmann 
1753f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1754f8558555SMarcel Holtmann 			if (!ev->status)
1755f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1756f8558555SMarcel Holtmann 
1757f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1758f8558555SMarcel Holtmann 			hci_conn_put(conn);
1759f8558555SMarcel Holtmann 		} else
1760a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1761a9de9248SMarcel Holtmann 	}
1762a9de9248SMarcel Holtmann 
1763a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1764a9de9248SMarcel Holtmann }
1765a9de9248SMarcel Holtmann 
1766a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1767a9de9248SMarcel Holtmann {
1768a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1769a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1770a9de9248SMarcel Holtmann 
1771a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1772a9de9248SMarcel Holtmann 
1773a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1774a9de9248SMarcel Holtmann 
1775a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1776a9de9248SMarcel Holtmann 	if (conn) {
1777a9de9248SMarcel Holtmann 		if (!ev->status)
1778a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1779a9de9248SMarcel Holtmann 
1780a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1781a9de9248SMarcel Holtmann 
1782a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1783a9de9248SMarcel Holtmann 	}
1784a9de9248SMarcel Holtmann 
1785a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1786a9de9248SMarcel Holtmann }
1787a9de9248SMarcel Holtmann 
1788a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1789a9de9248SMarcel Holtmann {
1790a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1791a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1792a9de9248SMarcel Holtmann 
1793a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1794a9de9248SMarcel Holtmann 
1795a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1796a9de9248SMarcel Holtmann 
1797a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1798ccd556feSJohan Hedberg 	if (!conn)
1799ccd556feSJohan Hedberg 		goto unlock;
1800ccd556feSJohan Hedberg 
1801769be974SMarcel Holtmann 	if (!ev->status)
1802a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1803a9de9248SMarcel Holtmann 
1804ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1805ccd556feSJohan Hedberg 		goto unlock;
1806ccd556feSJohan Hedberg 
1807ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1808769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1809769be974SMarcel Holtmann 		cp.handle = ev->handle;
1810769be974SMarcel Holtmann 		cp.page = 0x01;
1811ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1812769be974SMarcel Holtmann 							sizeof(cp), &cp);
1813392599b9SJohan Hedberg 		goto unlock;
1814392599b9SJohan Hedberg 	}
1815392599b9SJohan Hedberg 
1816127178d2SJohan Hedberg 	if (!ev->status) {
1817127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1818127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1819127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1820127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1821127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1822127178d2SJohan Hedberg 	}
1823392599b9SJohan Hedberg 
1824127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1825769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1826769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1827769be974SMarcel Holtmann 		hci_conn_put(conn);
1828769be974SMarcel Holtmann 	}
1829769be974SMarcel Holtmann 
1830ccd556feSJohan Hedberg unlock:
1831a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1832a9de9248SMarcel Holtmann }
1833a9de9248SMarcel Holtmann 
1834a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1835a9de9248SMarcel Holtmann {
1836a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1837a9de9248SMarcel Holtmann }
1838a9de9248SMarcel Holtmann 
1839a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1840a9de9248SMarcel Holtmann {
1841a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1842a9de9248SMarcel Holtmann }
1843a9de9248SMarcel Holtmann 
1844a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1845a9de9248SMarcel Holtmann {
1846a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1847a9de9248SMarcel Holtmann 	__u16 opcode;
1848a9de9248SMarcel Holtmann 
1849a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1850a9de9248SMarcel Holtmann 
1851a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1852a9de9248SMarcel Holtmann 
1853a9de9248SMarcel Holtmann 	switch (opcode) {
1854a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1855a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1856a9de9248SMarcel Holtmann 		break;
1857a9de9248SMarcel Holtmann 
1858a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1859a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1860a9de9248SMarcel Holtmann 		break;
1861a9de9248SMarcel Holtmann 
1862a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1863a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1864a9de9248SMarcel Holtmann 		break;
1865a9de9248SMarcel Holtmann 
1866a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1867a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1868a9de9248SMarcel Holtmann 		break;
1869a9de9248SMarcel Holtmann 
1870e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1871e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1872e4e8e37cSMarcel Holtmann 		break;
1873e4e8e37cSMarcel Holtmann 
1874a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1875a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1876a9de9248SMarcel Holtmann 		break;
1877a9de9248SMarcel Holtmann 
1878e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1879e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1880e4e8e37cSMarcel Holtmann 		break;
1881e4e8e37cSMarcel Holtmann 
1882e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1883e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1884e4e8e37cSMarcel Holtmann 		break;
1885e4e8e37cSMarcel Holtmann 
1886a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1887a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1888a9de9248SMarcel Holtmann 		break;
1889a9de9248SMarcel Holtmann 
1890a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1891a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1892a9de9248SMarcel Holtmann 		break;
1893a9de9248SMarcel Holtmann 
1894a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1895a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1896a9de9248SMarcel Holtmann 		break;
1897a9de9248SMarcel Holtmann 
1898a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1899a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1900a9de9248SMarcel Holtmann 		break;
1901a9de9248SMarcel Holtmann 
1902a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1903a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1904a9de9248SMarcel Holtmann 		break;
1905a9de9248SMarcel Holtmann 
1906a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1907a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1908a9de9248SMarcel Holtmann 		break;
1909a9de9248SMarcel Holtmann 
1910a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1911a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1912a9de9248SMarcel Holtmann 		break;
1913a9de9248SMarcel Holtmann 
1914a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1915a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1916a9de9248SMarcel Holtmann 		break;
1917a9de9248SMarcel Holtmann 
1918a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1919a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1920a9de9248SMarcel Holtmann 		break;
1921a9de9248SMarcel Holtmann 
1922a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1923a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1924a9de9248SMarcel Holtmann 		break;
1925a9de9248SMarcel Holtmann 
1926a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1927a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1928a9de9248SMarcel Holtmann 		break;
1929a9de9248SMarcel Holtmann 
1930333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1931333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1932333140b5SMarcel Holtmann 		break;
1933333140b5SMarcel Holtmann 
1934333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1935333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1936333140b5SMarcel Holtmann 		break;
1937333140b5SMarcel Holtmann 
1938a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1939a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1940a9de9248SMarcel Holtmann 		break;
1941a9de9248SMarcel Holtmann 
1942a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1943a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1944a9de9248SMarcel Holtmann 		break;
1945a9de9248SMarcel Holtmann 
1946a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1947a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1948a9de9248SMarcel Holtmann 		break;
1949a9de9248SMarcel Holtmann 
1950971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
1951971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
1952971e3a4bSAndre Guedes 		break;
1953971e3a4bSAndre Guedes 
1954a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
1955a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
1956a9de9248SMarcel Holtmann 		break;
1957a9de9248SMarcel Holtmann 
1958a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
1959a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
1960a9de9248SMarcel Holtmann 		break;
1961a9de9248SMarcel Holtmann 
196223bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
196323bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
196423bb5763SJohan Hedberg 		break;
196523bb5763SJohan Hedberg 
1966928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
1967928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
1968928abaa7SAndrei Emeltchenko 		break;
1969928abaa7SAndrei Emeltchenko 
1970b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
1971b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
1972b0916ea0SJohan Hedberg 		break;
1973b0916ea0SJohan Hedberg 
1974d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
1975d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
1976d5859e22SJohan Hedberg 		break;
1977d5859e22SJohan Hedberg 
1978d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
1979d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
1980d5859e22SJohan Hedberg 		break;
1981d5859e22SJohan Hedberg 
1982d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
1983d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
1984d5859e22SJohan Hedberg 		break;
1985d5859e22SJohan Hedberg 
1986d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
1987d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
1988d5859e22SJohan Hedberg 		break;
1989d5859e22SJohan Hedberg 
1990980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
1991980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
1992980e1a53SJohan Hedberg 		break;
1993980e1a53SJohan Hedberg 
1994980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
1995980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
1996980e1a53SJohan Hedberg 		break;
1997980e1a53SJohan Hedberg 
1998c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
1999c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2000c35938b2SSzymon Janc 		break;
2001c35938b2SSzymon Janc 
20026ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
20036ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
20046ed58ec5SVille Tervo 		break;
20056ed58ec5SVille Tervo 
2006a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2007a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2008a5c29683SJohan Hedberg 		break;
2009a5c29683SJohan Hedberg 
2010a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2011a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2012a5c29683SJohan Hedberg 		break;
2013a5c29683SJohan Hedberg 
2014eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2015eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2016eb9d91f5SAndre Guedes 		break;
2017eb9d91f5SAndre Guedes 
2018a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2019a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2020a7a595f6SVinicius Costa Gomes 		break;
2021a7a595f6SVinicius Costa Gomes 
2022a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2023a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2024a7a595f6SVinicius Costa Gomes 		break;
2025a7a595f6SVinicius Costa Gomes 
2026f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2027f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2028f9b49306SAndre Guedes 		break;
2029f9b49306SAndre Guedes 
2030a9de9248SMarcel Holtmann 	default:
2031a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2032a9de9248SMarcel Holtmann 		break;
2033a9de9248SMarcel Holtmann 	}
2034a9de9248SMarcel Holtmann 
20356bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
20366bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
20376bd32326SVille Tervo 
2038a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2039a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2040a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2041c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2042a9de9248SMarcel Holtmann 	}
2043a9de9248SMarcel Holtmann }
2044a9de9248SMarcel Holtmann 
2045a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2046a9de9248SMarcel Holtmann {
2047a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2048a9de9248SMarcel Holtmann 	__u16 opcode;
2049a9de9248SMarcel Holtmann 
2050a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2051a9de9248SMarcel Holtmann 
2052a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2053a9de9248SMarcel Holtmann 
2054a9de9248SMarcel Holtmann 	switch (opcode) {
2055a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2056a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2057a9de9248SMarcel Holtmann 		break;
2058a9de9248SMarcel Holtmann 
2059a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2060a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2061a9de9248SMarcel Holtmann 		break;
2062a9de9248SMarcel Holtmann 
2063a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2064a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2065a9de9248SMarcel Holtmann 		break;
2066a9de9248SMarcel Holtmann 
2067f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2068f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2069f8558555SMarcel Holtmann 		break;
2070f8558555SMarcel Holtmann 
2071f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2072f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2073f8558555SMarcel Holtmann 		break;
2074f8558555SMarcel Holtmann 
2075a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2076a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2077a9de9248SMarcel Holtmann 		break;
2078a9de9248SMarcel Holtmann 
2079769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2080769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2081769be974SMarcel Holtmann 		break;
2082769be974SMarcel Holtmann 
2083769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2084769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2085769be974SMarcel Holtmann 		break;
2086769be974SMarcel Holtmann 
2087a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2088a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2089a9de9248SMarcel Holtmann 		break;
2090a9de9248SMarcel Holtmann 
2091a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2092a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2093a9de9248SMarcel Holtmann 		break;
2094a9de9248SMarcel Holtmann 
2095a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2096a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2097a9de9248SMarcel Holtmann 		break;
2098a9de9248SMarcel Holtmann 
20998962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
21008962ee74SJohan Hedberg 		if (ev->status != 0)
210137d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
21028962ee74SJohan Hedberg 		break;
21038962ee74SJohan Hedberg 
2104fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2105fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2106fcd89c09SVille Tervo 		break;
2107fcd89c09SVille Tervo 
2108a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2109a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2110a7a595f6SVinicius Costa Gomes 		break;
2111a7a595f6SVinicius Costa Gomes 
2112a9de9248SMarcel Holtmann 	default:
2113a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2114a9de9248SMarcel Holtmann 		break;
2115a9de9248SMarcel Holtmann 	}
2116a9de9248SMarcel Holtmann 
21176bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
21186bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
21196bd32326SVille Tervo 
212010572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2121a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2122a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2123c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2124a9de9248SMarcel Holtmann 	}
2125a9de9248SMarcel Holtmann }
2126a9de9248SMarcel Holtmann 
2127a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2128a9de9248SMarcel Holtmann {
2129a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2130a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2131a9de9248SMarcel Holtmann 
2132a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2133a9de9248SMarcel Holtmann 
2134a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2135a9de9248SMarcel Holtmann 
2136a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2137a9de9248SMarcel Holtmann 	if (conn) {
2138a9de9248SMarcel Holtmann 		if (!ev->status) {
2139a9de9248SMarcel Holtmann 			if (ev->role)
2140a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2141a9de9248SMarcel Holtmann 			else
2142a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2143a9de9248SMarcel Holtmann 		}
2144a9de9248SMarcel Holtmann 
2145a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2146a9de9248SMarcel Holtmann 
2147a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2148a9de9248SMarcel Holtmann 	}
2149a9de9248SMarcel Holtmann 
2150a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2151a9de9248SMarcel Holtmann }
2152a9de9248SMarcel Holtmann 
21531da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
21541da177e4SLinus Torvalds {
2155a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
21561ebb9252SMarcel Holtmann 	__le16 *ptr;
21571da177e4SLinus Torvalds 	int i;
21581da177e4SLinus Torvalds 
21591da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
21601da177e4SLinus Torvalds 
21611da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
21621da177e4SLinus Torvalds 
21631da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
21641da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
21651da177e4SLinus Torvalds 		return;
21661da177e4SLinus Torvalds 	}
21671da177e4SLinus Torvalds 
21681da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
21691da177e4SLinus Torvalds 
21701ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
21711da177e4SLinus Torvalds 		struct hci_conn *conn;
21721da177e4SLinus Torvalds 		__u16  handle, count;
21731da177e4SLinus Torvalds 
217483985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
217583985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
21761da177e4SLinus Torvalds 
21771da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
21781da177e4SLinus Torvalds 		if (conn) {
21791da177e4SLinus Torvalds 			conn->sent -= count;
21801da177e4SLinus Torvalds 
21815b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
218270f23020SAndrei Emeltchenko 				hdev->acl_cnt += count;
218370f23020SAndrei Emeltchenko 				if (hdev->acl_cnt > hdev->acl_pkts)
21841da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
21856ed58ec5SVille Tervo 			} else if (conn->type == LE_LINK) {
21866ed58ec5SVille Tervo 				if (hdev->le_pkts) {
21876ed58ec5SVille Tervo 					hdev->le_cnt += count;
21886ed58ec5SVille Tervo 					if (hdev->le_cnt > hdev->le_pkts)
21896ed58ec5SVille Tervo 						hdev->le_cnt = hdev->le_pkts;
21906ed58ec5SVille Tervo 				} else {
21916ed58ec5SVille Tervo 					hdev->acl_cnt += count;
21926ed58ec5SVille Tervo 					if (hdev->acl_cnt > hdev->acl_pkts)
21936ed58ec5SVille Tervo 						hdev->acl_cnt = hdev->acl_pkts;
21946ed58ec5SVille Tervo 				}
21955b7f9909SMarcel Holtmann 			} else {
219670f23020SAndrei Emeltchenko 				hdev->sco_cnt += count;
219770f23020SAndrei Emeltchenko 				if (hdev->sco_cnt > hdev->sco_pkts)
21985b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
21991da177e4SLinus Torvalds 			}
22001da177e4SLinus Torvalds 		}
22011da177e4SLinus Torvalds 	}
2202a9de9248SMarcel Holtmann 
2203c78ae283SMarcel Holtmann 	tasklet_schedule(&hdev->tx_task);
22041da177e4SLinus Torvalds 
22051da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
22061da177e4SLinus Torvalds }
22071da177e4SLinus Torvalds 
220804837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
22091da177e4SLinus Torvalds {
2210a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
221104837f64SMarcel Holtmann 	struct hci_conn *conn;
22121da177e4SLinus Torvalds 
22131da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
22141da177e4SLinus Torvalds 
22151da177e4SLinus Torvalds 	hci_dev_lock(hdev);
22161da177e4SLinus Torvalds 
221704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
221804837f64SMarcel Holtmann 	if (conn) {
221904837f64SMarcel Holtmann 		conn->mode = ev->mode;
222004837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
222104837f64SMarcel Holtmann 
222204837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
222304837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
222404837f64SMarcel Holtmann 				conn->power_save = 1;
222504837f64SMarcel Holtmann 			else
222604837f64SMarcel Holtmann 				conn->power_save = 0;
222704837f64SMarcel Holtmann 		}
2228e73439d8SMarcel Holtmann 
2229e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2230e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
223104837f64SMarcel Holtmann 	}
223204837f64SMarcel Holtmann 
223304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
223404837f64SMarcel Holtmann }
223504837f64SMarcel Holtmann 
22361da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
22371da177e4SLinus Torvalds {
2238052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2239052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2240052b30b0SMarcel Holtmann 
2241a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2242052b30b0SMarcel Holtmann 
2243052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2244052b30b0SMarcel Holtmann 
2245052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2246b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2247b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2248b6f98044SWaldemar Rymarkiewicz 
2249b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2250052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2251052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2252052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2253052b30b0SMarcel Holtmann 	}
2254052b30b0SMarcel Holtmann 
225503b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
225603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
225703b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2258582fbe9eSJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->flags)) {
2259a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2260a770bb5aSWaldemar Rymarkiewicz 
2261a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2262a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2263a770bb5aSWaldemar Rymarkiewicz 		else
2264a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2265a770bb5aSWaldemar Rymarkiewicz 
2266744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2267a770bb5aSWaldemar Rymarkiewicz 	}
2268980e1a53SJohan Hedberg 
2269b6f98044SWaldemar Rymarkiewicz unlock:
2270052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
22711da177e4SLinus Torvalds }
22721da177e4SLinus Torvalds 
22731da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
22741da177e4SLinus Torvalds {
227555ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
227655ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
227755ed8ca1SJohan Hedberg 	struct hci_conn *conn;
227855ed8ca1SJohan Hedberg 	struct link_key *key;
227955ed8ca1SJohan Hedberg 
2280a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
228155ed8ca1SJohan Hedberg 
228255ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
228355ed8ca1SJohan Hedberg 		return;
228455ed8ca1SJohan Hedberg 
228555ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
228655ed8ca1SJohan Hedberg 
228755ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
228855ed8ca1SJohan Hedberg 	if (!key) {
228955ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
229055ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
229155ed8ca1SJohan Hedberg 		goto not_found;
229255ed8ca1SJohan Hedberg 	}
229355ed8ca1SJohan Hedberg 
229455ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
229555ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
229655ed8ca1SJohan Hedberg 
2297b6020ba0SWaldemar Rymarkiewicz 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2298b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
229955ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
230055ed8ca1SJohan Hedberg 		goto not_found;
230155ed8ca1SJohan Hedberg 	}
230255ed8ca1SJohan Hedberg 
230355ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
230460b83f57SWaldemar Rymarkiewicz 	if (conn) {
230560b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
230660b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
230760b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
230855ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
230955ed8ca1SJohan Hedberg 			goto not_found;
231055ed8ca1SJohan Hedberg 		}
231155ed8ca1SJohan Hedberg 
231260b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
231360b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
231460b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
231560b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
231660b83f57SWaldemar Rymarkiewicz 			goto not_found;
231760b83f57SWaldemar Rymarkiewicz 		}
231860b83f57SWaldemar Rymarkiewicz 
231960b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
232060b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
232160b83f57SWaldemar Rymarkiewicz 	}
232260b83f57SWaldemar Rymarkiewicz 
232355ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
232455ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
232555ed8ca1SJohan Hedberg 
232655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
232755ed8ca1SJohan Hedberg 
232855ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
232955ed8ca1SJohan Hedberg 
233055ed8ca1SJohan Hedberg 	return;
233155ed8ca1SJohan Hedberg 
233255ed8ca1SJohan Hedberg not_found:
233355ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
233455ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
23351da177e4SLinus Torvalds }
23361da177e4SLinus Torvalds 
23371da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
23381da177e4SLinus Torvalds {
2339052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2340052b30b0SMarcel Holtmann 	struct hci_conn *conn;
234155ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2342052b30b0SMarcel Holtmann 
2343a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2344052b30b0SMarcel Holtmann 
2345052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2346052b30b0SMarcel Holtmann 
2347052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2348052b30b0SMarcel Holtmann 	if (conn) {
2349052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2350052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2351980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
235213d39315SWaldemar Rymarkiewicz 
235313d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
235413d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
235513d39315SWaldemar Rymarkiewicz 
2356052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2357052b30b0SMarcel Holtmann 	}
2358052b30b0SMarcel Holtmann 
235955ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2360d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
236155ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
236255ed8ca1SJohan Hedberg 
2363052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
23641da177e4SLinus Torvalds }
23651da177e4SLinus Torvalds 
236604837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
236704837f64SMarcel Holtmann {
2368a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
236904837f64SMarcel Holtmann 	struct hci_conn *conn;
237004837f64SMarcel Holtmann 
237104837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
237204837f64SMarcel Holtmann 
237304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
237404837f64SMarcel Holtmann 
237504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
23761da177e4SLinus Torvalds 	if (conn && !ev->status) {
23771da177e4SLinus Torvalds 		struct inquiry_entry *ie;
23781da177e4SLinus Torvalds 
2379cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2380cc11b9c1SAndrei Emeltchenko 		if (ie) {
23811da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
23821da177e4SLinus Torvalds 			ie->timestamp = jiffies;
23831da177e4SLinus Torvalds 		}
23841da177e4SLinus Torvalds 	}
23851da177e4SLinus Torvalds 
23861da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
23871da177e4SLinus Torvalds }
23881da177e4SLinus Torvalds 
2389a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2390a8746417SMarcel Holtmann {
2391a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2392a8746417SMarcel Holtmann 	struct hci_conn *conn;
2393a8746417SMarcel Holtmann 
2394a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2395a8746417SMarcel Holtmann 
2396a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2397a8746417SMarcel Holtmann 
2398a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2399a8746417SMarcel Holtmann 	if (conn && !ev->status)
2400a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2401a8746417SMarcel Holtmann 
2402a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2403a8746417SMarcel Holtmann }
2404a8746417SMarcel Holtmann 
240585a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
240685a1e930SMarcel Holtmann {
2407a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
240885a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
240985a1e930SMarcel Holtmann 
241085a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
241185a1e930SMarcel Holtmann 
241285a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
241385a1e930SMarcel Holtmann 
2414cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2415cc11b9c1SAndrei Emeltchenko 	if (ie) {
241685a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
241785a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
241885a1e930SMarcel Holtmann 	}
241985a1e930SMarcel Holtmann 
242085a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
242185a1e930SMarcel Holtmann }
242285a1e930SMarcel Holtmann 
2423a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2424a9de9248SMarcel Holtmann {
2425a9de9248SMarcel Holtmann 	struct inquiry_data data;
2426a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2427a9de9248SMarcel Holtmann 
2428a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2429a9de9248SMarcel Holtmann 
2430a9de9248SMarcel Holtmann 	if (!num_rsp)
2431a9de9248SMarcel Holtmann 		return;
2432a9de9248SMarcel Holtmann 
2433a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2434a9de9248SMarcel Holtmann 
2435a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2436138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2437138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2438a9de9248SMarcel Holtmann 
2439e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2440a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2441a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2442a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2443a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2444a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2445a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2446a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
244741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2448a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
244948264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2450e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2451e17acd40SJohan Hedberg 						NULL);
2452a9de9248SMarcel Holtmann 		}
2453a9de9248SMarcel Holtmann 	} else {
2454a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2455a9de9248SMarcel Holtmann 
2456e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2457a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2458a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2459a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2460a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2461a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2462a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2463a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
246441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2465a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
246648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2467e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2468e17acd40SJohan Hedberg 						NULL);
2469a9de9248SMarcel Holtmann 		}
2470a9de9248SMarcel Holtmann 	}
2471a9de9248SMarcel Holtmann 
2472a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2473a9de9248SMarcel Holtmann }
2474a9de9248SMarcel Holtmann 
2475a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2476a9de9248SMarcel Holtmann {
247741a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
247841a96212SMarcel Holtmann 	struct hci_conn *conn;
247941a96212SMarcel Holtmann 
2480a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
248141a96212SMarcel Holtmann 
248241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
248341a96212SMarcel Holtmann 
248441a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2485ccd556feSJohan Hedberg 	if (!conn)
2486ccd556feSJohan Hedberg 		goto unlock;
2487ccd556feSJohan Hedberg 
2488769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
248941a96212SMarcel Holtmann 		struct inquiry_entry *ie;
249041a96212SMarcel Holtmann 
2491cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2492cc11b9c1SAndrei Emeltchenko 		if (ie)
249341a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
249441a96212SMarcel Holtmann 
249541a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
249641a96212SMarcel Holtmann 	}
249741a96212SMarcel Holtmann 
2498ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2499ccd556feSJohan Hedberg 		goto unlock;
2500ccd556feSJohan Hedberg 
2501127178d2SJohan Hedberg 	if (!ev->status) {
2502127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2503127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2504127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2505127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2506127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2507127178d2SJohan Hedberg 	}
2508392599b9SJohan Hedberg 
2509127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2510769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2511769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2512769be974SMarcel Holtmann 		hci_conn_put(conn);
2513769be974SMarcel Holtmann 	}
2514769be974SMarcel Holtmann 
2515ccd556feSJohan Hedberg unlock:
251641a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2517a9de9248SMarcel Holtmann }
2518a9de9248SMarcel Holtmann 
2519a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2520a9de9248SMarcel Holtmann {
2521b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2522b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2523b6a0dc82SMarcel Holtmann 
2524b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2525b6a0dc82SMarcel Holtmann 
2526b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2527b6a0dc82SMarcel Holtmann 
2528b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
25299dc0a3afSMarcel Holtmann 	if (!conn) {
25309dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
25319dc0a3afSMarcel Holtmann 			goto unlock;
25329dc0a3afSMarcel Holtmann 
25339dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2534b6a0dc82SMarcel Holtmann 		if (!conn)
2535b6a0dc82SMarcel Holtmann 			goto unlock;
2536b6a0dc82SMarcel Holtmann 
25379dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
25389dc0a3afSMarcel Holtmann 	}
25399dc0a3afSMarcel Holtmann 
2540732547f9SMarcel Holtmann 	switch (ev->status) {
2541732547f9SMarcel Holtmann 	case 0x00:
2542732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2543732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2544732547f9SMarcel Holtmann 
25459eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2546732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2547732547f9SMarcel Holtmann 		break;
2548732547f9SMarcel Holtmann 
2549705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2550732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
25511038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2552732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2553732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2554efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2555efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2556efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2557efc7688bSMarcel Holtmann 			goto unlock;
2558efc7688bSMarcel Holtmann 		}
2559732547f9SMarcel Holtmann 		/* fall through */
2560efc7688bSMarcel Holtmann 
2561732547f9SMarcel Holtmann 	default:
2562b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2563732547f9SMarcel Holtmann 		break;
2564732547f9SMarcel Holtmann 	}
2565b6a0dc82SMarcel Holtmann 
2566b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2567b6a0dc82SMarcel Holtmann 	if (ev->status)
2568b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2569b6a0dc82SMarcel Holtmann 
2570b6a0dc82SMarcel Holtmann unlock:
2571b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2572a9de9248SMarcel Holtmann }
2573a9de9248SMarcel Holtmann 
2574a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2575a9de9248SMarcel Holtmann {
2576a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2577a9de9248SMarcel Holtmann }
2578a9de9248SMarcel Holtmann 
257904837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
258004837f64SMarcel Holtmann {
2581a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
258204837f64SMarcel Holtmann 
258304837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
258404837f64SMarcel Holtmann }
258504837f64SMarcel Holtmann 
2586a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2587a9de9248SMarcel Holtmann {
2588a9de9248SMarcel Holtmann 	struct inquiry_data data;
2589a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2590a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2591a9de9248SMarcel Holtmann 
2592a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2593a9de9248SMarcel Holtmann 
2594a9de9248SMarcel Holtmann 	if (!num_rsp)
2595a9de9248SMarcel Holtmann 		return;
2596a9de9248SMarcel Holtmann 
2597a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2598a9de9248SMarcel Holtmann 
2599e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2600a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2601a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2602a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2603a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2604a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2605a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2606a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
260741a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2608a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
260948264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
26104c659c39SJohan Hedberg 				info->dev_class, info->rssi, info->data);
2611a9de9248SMarcel Holtmann 	}
2612a9de9248SMarcel Holtmann 
2613a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2614a9de9248SMarcel Holtmann }
2615a9de9248SMarcel Holtmann 
261617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
261717fa4b9dSJohan Hedberg {
261817fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
261917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
262017fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
262117fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
262217fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
262317fa4b9dSJohan Hedberg 			return 0x02;
262417fa4b9dSJohan Hedberg 		else
262517fa4b9dSJohan Hedberg 			return 0x03;
262617fa4b9dSJohan Hedberg 	}
262717fa4b9dSJohan Hedberg 
262817fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
262917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
263058797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
263117fa4b9dSJohan Hedberg 
263217fa4b9dSJohan Hedberg 	return conn->auth_type;
263317fa4b9dSJohan Hedberg }
263417fa4b9dSJohan Hedberg 
26350493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26360493684eSMarcel Holtmann {
26370493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
26380493684eSMarcel Holtmann 	struct hci_conn *conn;
26390493684eSMarcel Holtmann 
26400493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
26410493684eSMarcel Holtmann 
26420493684eSMarcel Holtmann 	hci_dev_lock(hdev);
26430493684eSMarcel Holtmann 
26440493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
264503b555e1SJohan Hedberg 	if (!conn)
264603b555e1SJohan Hedberg 		goto unlock;
264703b555e1SJohan Hedberg 
26480493684eSMarcel Holtmann 	hci_conn_hold(conn);
26490493684eSMarcel Holtmann 
265003b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
265103b555e1SJohan Hedberg 		goto unlock;
265203b555e1SJohan Hedberg 
265303b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
265403b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
265517fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
265617fa4b9dSJohan Hedberg 
265717fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
265817fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
26597cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
26607cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
266117fa4b9dSJohan Hedberg 
2662ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2663ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2664ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2665ce85ee13SSzymon Janc 		else
2666ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2667ce85ee13SSzymon Janc 
266817fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
266917fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
267003b555e1SJohan Hedberg 	} else {
267103b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
267203b555e1SJohan Hedberg 
267303b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
26749f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
267503b555e1SJohan Hedberg 
267603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
267703b555e1SJohan Hedberg 							sizeof(cp), &cp);
267803b555e1SJohan Hedberg 	}
267903b555e1SJohan Hedberg 
268003b555e1SJohan Hedberg unlock:
268103b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
268203b555e1SJohan Hedberg }
268303b555e1SJohan Hedberg 
268403b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
268503b555e1SJohan Hedberg {
268603b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
268703b555e1SJohan Hedberg 	struct hci_conn *conn;
268803b555e1SJohan Hedberg 
268903b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
269003b555e1SJohan Hedberg 
269103b555e1SJohan Hedberg 	hci_dev_lock(hdev);
269203b555e1SJohan Hedberg 
269303b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
269403b555e1SJohan Hedberg 	if (!conn)
269503b555e1SJohan Hedberg 		goto unlock;
269603b555e1SJohan Hedberg 
269703b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
269803b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
269903b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
270003b555e1SJohan Hedberg 
270103b555e1SJohan Hedberg unlock:
27020493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
27030493684eSMarcel Holtmann }
27040493684eSMarcel Holtmann 
2705a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2706a5c29683SJohan Hedberg 							struct sk_buff *skb)
2707a5c29683SJohan Hedberg {
2708a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
270955bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
27107a828908SJohan Hedberg 	struct hci_conn *conn;
2711a5c29683SJohan Hedberg 
2712a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
2713a5c29683SJohan Hedberg 
2714a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
2715a5c29683SJohan Hedberg 
27167a828908SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
27177a828908SJohan Hedberg 		goto unlock;
27187a828908SJohan Hedberg 
27197a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
27207a828908SJohan Hedberg 	if (!conn)
27217a828908SJohan Hedberg 		goto unlock;
27227a828908SJohan Hedberg 
27237a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
27247a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
27257a828908SJohan Hedberg 
27267a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
27277a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
27287a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
27297a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
27307a828908SJohan Hedberg 	 * bit set. */
27317a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
27327a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
27337a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
27347a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
27357a828908SJohan Hedberg 		goto unlock;
27367a828908SJohan Hedberg 	}
27377a828908SJohan Hedberg 
27387a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
27397a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
27407a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
274155bc1a37SJohan Hedberg 
274255bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
274355bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
274455bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
274555bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
274655bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
274755bc1a37SJohan Hedberg 			confirm_hint = 1;
274855bc1a37SJohan Hedberg 			goto confirm;
274955bc1a37SJohan Hedberg 		}
275055bc1a37SJohan Hedberg 
27519f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
27529f61656aSJohan Hedberg 						hdev->auto_accept_delay);
27539f61656aSJohan Hedberg 
27549f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
27559f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
27569f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
27579f61656aSJohan Hedberg 			goto unlock;
27589f61656aSJohan Hedberg 		}
27599f61656aSJohan Hedberg 
27607a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
27617a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
27627a828908SJohan Hedberg 		goto unlock;
27637a828908SJohan Hedberg 	}
27647a828908SJohan Hedberg 
276555bc1a37SJohan Hedberg confirm:
2766744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
276755bc1a37SJohan Hedberg 								confirm_hint);
2768a5c29683SJohan Hedberg 
27697a828908SJohan Hedberg unlock:
2770a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
2771a5c29683SJohan Hedberg }
2772a5c29683SJohan Hedberg 
27730493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
27740493684eSMarcel Holtmann {
27750493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
27760493684eSMarcel Holtmann 	struct hci_conn *conn;
27770493684eSMarcel Holtmann 
27780493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
27790493684eSMarcel Holtmann 
27800493684eSMarcel Holtmann 	hci_dev_lock(hdev);
27810493684eSMarcel Holtmann 
27820493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
27832a611692SJohan Hedberg 	if (!conn)
27842a611692SJohan Hedberg 		goto unlock;
27852a611692SJohan Hedberg 
27862a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
27872a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
27882a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
27892a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
27902a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
27912a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
2792744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
27932a611692SJohan Hedberg 
27940493684eSMarcel Holtmann 	hci_conn_put(conn);
27950493684eSMarcel Holtmann 
27962a611692SJohan Hedberg unlock:
27970493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
27980493684eSMarcel Holtmann }
27990493684eSMarcel Holtmann 
280041a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
280141a96212SMarcel Holtmann {
280241a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
280341a96212SMarcel Holtmann 	struct inquiry_entry *ie;
280441a96212SMarcel Holtmann 
280541a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
280641a96212SMarcel Holtmann 
280741a96212SMarcel Holtmann 	hci_dev_lock(hdev);
280841a96212SMarcel Holtmann 
2809cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2810cc11b9c1SAndrei Emeltchenko 	if (ie)
281141a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
281241a96212SMarcel Holtmann 
281341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
281441a96212SMarcel Holtmann }
281541a96212SMarcel Holtmann 
28162763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
28172763eda6SSzymon Janc 							struct sk_buff *skb)
28182763eda6SSzymon Janc {
28192763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
28202763eda6SSzymon Janc 	struct oob_data *data;
28212763eda6SSzymon Janc 
28222763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
28232763eda6SSzymon Janc 
28242763eda6SSzymon Janc 	hci_dev_lock(hdev);
28252763eda6SSzymon Janc 
2826e1ba1f15SSzymon Janc 	if (!test_bit(HCI_MGMT, &hdev->flags))
2827e1ba1f15SSzymon Janc 		goto unlock;
2828e1ba1f15SSzymon Janc 
28292763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
28302763eda6SSzymon Janc 	if (data) {
28312763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
28322763eda6SSzymon Janc 
28332763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
28342763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
28352763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
28362763eda6SSzymon Janc 
28372763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
28382763eda6SSzymon Janc 									&cp);
28392763eda6SSzymon Janc 	} else {
28402763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
28412763eda6SSzymon Janc 
28422763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
28432763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
28442763eda6SSzymon Janc 									&cp);
28452763eda6SSzymon Janc 	}
28462763eda6SSzymon Janc 
2847e1ba1f15SSzymon Janc unlock:
28482763eda6SSzymon Janc 	hci_dev_unlock(hdev);
28492763eda6SSzymon Janc }
28502763eda6SSzymon Janc 
2851fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2852fcd89c09SVille Tervo {
2853fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2854fcd89c09SVille Tervo 	struct hci_conn *conn;
2855fcd89c09SVille Tervo 
2856fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
2857fcd89c09SVille Tervo 
2858fcd89c09SVille Tervo 	hci_dev_lock(hdev);
2859fcd89c09SVille Tervo 
2860fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2861b62f328bSVille Tervo 	if (!conn) {
2862b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2863b62f328bSVille Tervo 		if (!conn) {
2864b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
2865b62f328bSVille Tervo 			hci_dev_unlock(hdev);
2866b62f328bSVille Tervo 			return;
2867b62f328bSVille Tervo 		}
286829b7988aSAndre Guedes 
286929b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
2870b62f328bSVille Tervo 	}
2871fcd89c09SVille Tervo 
2872fcd89c09SVille Tervo 	if (ev->status) {
287348264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
287448264f06SJohan Hedberg 						conn->dst_type, ev->status);
2875fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
2876fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
2877fcd89c09SVille Tervo 		hci_conn_del(conn);
2878fcd89c09SVille Tervo 		goto unlock;
2879fcd89c09SVille Tervo 	}
2880fcd89c09SVille Tervo 
288148264f06SJohan Hedberg 	mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
288283bc71b4SVinicius Costa Gomes 
28837b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
2884fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
2885fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
2886fcd89c09SVille Tervo 
2887fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
2888fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
2889fcd89c09SVille Tervo 
2890fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
2891fcd89c09SVille Tervo 
2892fcd89c09SVille Tervo unlock:
2893fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
2894fcd89c09SVille Tervo }
2895fcd89c09SVille Tervo 
28969aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
28979aa04c91SAndre Guedes 						struct sk_buff *skb)
28989aa04c91SAndre Guedes {
2899e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
2900e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
29019aa04c91SAndre Guedes 
29029aa04c91SAndre Guedes 	hci_dev_lock(hdev);
29039aa04c91SAndre Guedes 
2904e95beb41SAndre Guedes 	while (num_reports--) {
2905e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
2906e95beb41SAndre Guedes 
29079aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
29089aa04c91SAndre Guedes 
2909e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
29109aa04c91SAndre Guedes 	}
29119aa04c91SAndre Guedes 
29129aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
29139aa04c91SAndre Guedes }
29149aa04c91SAndre Guedes 
2915a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
2916a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
2917a7a595f6SVinicius Costa Gomes {
2918a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
2919a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
2920bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
2921a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
2922bea710feSVinicius Costa Gomes 	struct link_key *ltk;
2923a7a595f6SVinicius Costa Gomes 
2924a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
2925a7a595f6SVinicius Costa Gomes 
2926a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
2927a7a595f6SVinicius Costa Gomes 
2928a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2929bea710feSVinicius Costa Gomes 	if (conn == NULL)
2930bea710feSVinicius Costa Gomes 		goto not_found;
2931a7a595f6SVinicius Costa Gomes 
2932bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
2933bea710feSVinicius Costa Gomes 	if (ltk == NULL)
2934bea710feSVinicius Costa Gomes 		goto not_found;
2935bea710feSVinicius Costa Gomes 
2936bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
2937a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
2938726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
2939a7a595f6SVinicius Costa Gomes 
2940a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
2941a7a595f6SVinicius Costa Gomes 
2942a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
2943bea710feSVinicius Costa Gomes 
2944bea710feSVinicius Costa Gomes 	return;
2945bea710feSVinicius Costa Gomes 
2946bea710feSVinicius Costa Gomes not_found:
2947bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
2948bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
2949bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
2950a7a595f6SVinicius Costa Gomes }
2951a7a595f6SVinicius Costa Gomes 
2952fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2953fcd89c09SVille Tervo {
2954fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
2955fcd89c09SVille Tervo 
2956fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
2957fcd89c09SVille Tervo 
2958fcd89c09SVille Tervo 	switch (le_ev->subevent) {
2959fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
2960fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
2961fcd89c09SVille Tervo 		break;
2962fcd89c09SVille Tervo 
29639aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
29649aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
29659aa04c91SAndre Guedes 		break;
29669aa04c91SAndre Guedes 
2967a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
2968a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
2969a7a595f6SVinicius Costa Gomes 		break;
2970a7a595f6SVinicius Costa Gomes 
2971fcd89c09SVille Tervo 	default:
2972fcd89c09SVille Tervo 		break;
2973fcd89c09SVille Tervo 	}
2974fcd89c09SVille Tervo }
2975fcd89c09SVille Tervo 
29761da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
29771da177e4SLinus Torvalds {
2978a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
2979a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
29801da177e4SLinus Torvalds 
29811da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
29821da177e4SLinus Torvalds 
2983a9de9248SMarcel Holtmann 	switch (event) {
29841da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
29851da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
29861da177e4SLinus Torvalds 		break;
29871da177e4SLinus Torvalds 
29881da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
29891da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
29901da177e4SLinus Torvalds 		break;
29911da177e4SLinus Torvalds 
2992a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
2993a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
299421d9e30eSMarcel Holtmann 		break;
299521d9e30eSMarcel Holtmann 
29961da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
29971da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
29981da177e4SLinus Torvalds 		break;
29991da177e4SLinus Torvalds 
30001da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
30011da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
30021da177e4SLinus Torvalds 		break;
30031da177e4SLinus Torvalds 
30041da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
30051da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
30061da177e4SLinus Torvalds 		break;
30071da177e4SLinus Torvalds 
3008a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3009a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3010a9de9248SMarcel Holtmann 		break;
3011a9de9248SMarcel Holtmann 
30121da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
30131da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
30141da177e4SLinus Torvalds 		break;
30151da177e4SLinus Torvalds 
3016a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3017a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3018a9de9248SMarcel Holtmann 		break;
3019a9de9248SMarcel Holtmann 
3020a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3021a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3022a9de9248SMarcel Holtmann 		break;
3023a9de9248SMarcel Holtmann 
3024a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3025a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3026a9de9248SMarcel Holtmann 		break;
3027a9de9248SMarcel Holtmann 
3028a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3029a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3030a9de9248SMarcel Holtmann 		break;
3031a9de9248SMarcel Holtmann 
3032a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3033a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3034a9de9248SMarcel Holtmann 		break;
3035a9de9248SMarcel Holtmann 
3036a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3037a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3038a9de9248SMarcel Holtmann 		break;
3039a9de9248SMarcel Holtmann 
3040a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3041a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3042a9de9248SMarcel Holtmann 		break;
3043a9de9248SMarcel Holtmann 
3044a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3045a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3046a9de9248SMarcel Holtmann 		break;
3047a9de9248SMarcel Holtmann 
3048a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3049a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
30501da177e4SLinus Torvalds 		break;
30511da177e4SLinus Torvalds 
30521da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
30531da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
30541da177e4SLinus Torvalds 		break;
30551da177e4SLinus Torvalds 
30561da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
30571da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
30581da177e4SLinus Torvalds 		break;
30591da177e4SLinus Torvalds 
30601da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
30611da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
30621da177e4SLinus Torvalds 		break;
30631da177e4SLinus Torvalds 
30641da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
30651da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
30661da177e4SLinus Torvalds 		break;
30671da177e4SLinus Torvalds 
3068a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3069a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3070a8746417SMarcel Holtmann 		break;
3071a8746417SMarcel Holtmann 
307285a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
307385a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
307485a1e930SMarcel Holtmann 		break;
307585a1e930SMarcel Holtmann 
3076a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3077a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3078a9de9248SMarcel Holtmann 		break;
3079a9de9248SMarcel Holtmann 
3080a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3081a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3082a9de9248SMarcel Holtmann 		break;
3083a9de9248SMarcel Holtmann 
3084a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3085a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3086a9de9248SMarcel Holtmann 		break;
3087a9de9248SMarcel Holtmann 
3088a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3089a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3090a9de9248SMarcel Holtmann 		break;
3091a9de9248SMarcel Holtmann 
309204837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
309304837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
309404837f64SMarcel Holtmann 		break;
309504837f64SMarcel Holtmann 
3096a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3097a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
30981da177e4SLinus Torvalds 		break;
30991da177e4SLinus Torvalds 
31000493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
31010493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
31020493684eSMarcel Holtmann 		break;
31030493684eSMarcel Holtmann 
310403b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
310503b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
310603b555e1SJohan Hedberg 		break;
310703b555e1SJohan Hedberg 
3108a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3109a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3110a5c29683SJohan Hedberg 		break;
3111a5c29683SJohan Hedberg 
31120493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
31130493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
31140493684eSMarcel Holtmann 		break;
31150493684eSMarcel Holtmann 
311641a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
311741a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
311841a96212SMarcel Holtmann 		break;
311941a96212SMarcel Holtmann 
3120fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3121fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3122fcd89c09SVille Tervo 		break;
3123fcd89c09SVille Tervo 
31242763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
31252763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
31262763eda6SSzymon Janc 		break;
31272763eda6SSzymon Janc 
31281da177e4SLinus Torvalds 	default:
3129a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
31301da177e4SLinus Torvalds 		break;
31311da177e4SLinus Torvalds 	}
31321da177e4SLinus Torvalds 
31331da177e4SLinus Torvalds 	kfree_skb(skb);
31341da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
31351da177e4SLinus Torvalds }
31361da177e4SLinus Torvalds 
31371da177e4SLinus Torvalds /* Generate internal stack event */
31381da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
31391da177e4SLinus Torvalds {
31401da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
31411da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
31421da177e4SLinus Torvalds 	struct sk_buff *skb;
31431da177e4SLinus Torvalds 
31441da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
31451da177e4SLinus Torvalds 	if (!skb)
31461da177e4SLinus Torvalds 		return;
31471da177e4SLinus Torvalds 
31481da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
31491da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
31501da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
31511da177e4SLinus Torvalds 
31521da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
31531da177e4SLinus Torvalds 	ev->type = type;
31541da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
31551da177e4SLinus Torvalds 
3156576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3157a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3158576c7d85SMarcel Holtmann 
31590d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
31601da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3161eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
31621da177e4SLinus Torvalds 	kfree_skb(skb);
31631da177e4SLinus Torvalds }
3164e6100a25SAndre Guedes 
3165669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3166e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3167