xref: /openbmc/linux/net/bluetooth/hci_event.c (revision e6d465cb)
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 
58e6d465cbSAndre Guedes 	if (status) {
59e6d465cbSAndre Guedes 		hci_dev_lock(hdev);
60e6d465cbSAndre Guedes 		mgmt_stop_discovery_failed(hdev, status);
61e6d465cbSAndre Guedes 		hci_dev_unlock(hdev);
62a9de9248SMarcel Holtmann 		return;
63e6d465cbSAndre Guedes 	}
641da177e4SLinus Torvalds 
6589352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
6689352e7dSAndre Guedes 
6756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
68744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 0);
6956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
70a9de9248SMarcel Holtmann 
7123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
72a9de9248SMarcel Holtmann 
73a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
741da177e4SLinus Torvalds }
756bd57416SMarcel Holtmann 
76a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
771da177e4SLinus Torvalds {
78a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
79a9de9248SMarcel Holtmann 
80a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
81a9de9248SMarcel Holtmann 
82a9de9248SMarcel Holtmann 	if (status)
83a9de9248SMarcel Holtmann 		return;
84a9de9248SMarcel Holtmann 
85a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
86a9de9248SMarcel Holtmann }
87a9de9248SMarcel Holtmann 
88a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
89a9de9248SMarcel Holtmann {
90a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
91a9de9248SMarcel Holtmann }
92a9de9248SMarcel Holtmann 
93a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
94a9de9248SMarcel Holtmann {
95a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
961da177e4SLinus Torvalds 	struct hci_conn *conn;
971da177e4SLinus Torvalds 
98a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
991da177e4SLinus Torvalds 
100a9de9248SMarcel Holtmann 	if (rp->status)
101a9de9248SMarcel Holtmann 		return;
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1041da177e4SLinus Torvalds 
105a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1061da177e4SLinus Torvalds 	if (conn) {
107a9de9248SMarcel Holtmann 		if (rp->role)
1081da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1091da177e4SLinus Torvalds 		else
1101da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1111da177e4SLinus Torvalds 	}
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
114a9de9248SMarcel Holtmann }
1151da177e4SLinus Torvalds 
116e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
117e4e8e37cSMarcel Holtmann {
118e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
119e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
120e4e8e37cSMarcel Holtmann 
121e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
122e4e8e37cSMarcel Holtmann 
123e4e8e37cSMarcel Holtmann 	if (rp->status)
124e4e8e37cSMarcel Holtmann 		return;
125e4e8e37cSMarcel Holtmann 
126e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
127e4e8e37cSMarcel Holtmann 
128e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
129e4e8e37cSMarcel Holtmann 	if (conn)
130e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
131e4e8e37cSMarcel Holtmann 
132e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
133e4e8e37cSMarcel Holtmann }
134e4e8e37cSMarcel Holtmann 
135a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
136a9de9248SMarcel Holtmann {
137a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
138a9de9248SMarcel Holtmann 	struct hci_conn *conn;
139a9de9248SMarcel Holtmann 	void *sent;
140a9de9248SMarcel Holtmann 
141a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
142a9de9248SMarcel Holtmann 
143a9de9248SMarcel Holtmann 	if (rp->status)
144a9de9248SMarcel Holtmann 		return;
145a9de9248SMarcel Holtmann 
146a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14704837f64SMarcel Holtmann 	if (!sent)
148a9de9248SMarcel Holtmann 		return;
14904837f64SMarcel Holtmann 
15004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
15104837f64SMarcel Holtmann 
152a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
153e4e8e37cSMarcel Holtmann 	if (conn)
15483985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15504837f64SMarcel Holtmann 
15604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds 
159e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
160e4e8e37cSMarcel Holtmann {
161e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
162e4e8e37cSMarcel Holtmann 
163e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
164e4e8e37cSMarcel Holtmann 
165e4e8e37cSMarcel Holtmann 	if (rp->status)
166e4e8e37cSMarcel Holtmann 		return;
167e4e8e37cSMarcel Holtmann 
168e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
169e4e8e37cSMarcel Holtmann }
170e4e8e37cSMarcel Holtmann 
171e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
172e4e8e37cSMarcel Holtmann {
173e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
174e4e8e37cSMarcel Holtmann 	void *sent;
175e4e8e37cSMarcel Holtmann 
176e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
177e4e8e37cSMarcel Holtmann 
178e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
179e4e8e37cSMarcel Holtmann 	if (!sent)
180e4e8e37cSMarcel Holtmann 		return;
181e4e8e37cSMarcel Holtmann 
182e4e8e37cSMarcel Holtmann 	if (!status)
183e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
184e4e8e37cSMarcel Holtmann 
18523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
186e4e8e37cSMarcel Holtmann }
187e4e8e37cSMarcel Holtmann 
188a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1891da177e4SLinus Torvalds {
190a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
191a9de9248SMarcel Holtmann 
192a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
193a9de9248SMarcel Holtmann 
19410572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19510572132SGustavo F. Padovan 
19623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
197a9de9248SMarcel Holtmann }
198a9de9248SMarcel Holtmann 
199a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
200a9de9248SMarcel Holtmann {
201a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2021da177e4SLinus Torvalds 	void *sent;
2031da177e4SLinus Torvalds 
204a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2051da177e4SLinus Torvalds 
206a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2071da177e4SLinus Torvalds 	if (!sent)
208a9de9248SMarcel Holtmann 		return;
2091da177e4SLinus Torvalds 
21056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21156e5cb86SJohan Hedberg 
212b312b161SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
213744cf19eSJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
214b312b161SJohan Hedberg 
21556e5cb86SJohan Hedberg 	if (status == 0)
2161f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
21756e5cb86SJohan Hedberg 
21856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
219a9de9248SMarcel Holtmann }
220a9de9248SMarcel Holtmann 
221a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
222a9de9248SMarcel Holtmann {
223a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
224a9de9248SMarcel Holtmann 
225a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
226a9de9248SMarcel Holtmann 
227a9de9248SMarcel Holtmann 	if (rp->status)
228a9de9248SMarcel Holtmann 		return;
229a9de9248SMarcel Holtmann 
2301f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
231a9de9248SMarcel Holtmann }
232a9de9248SMarcel Holtmann 
233a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
234a9de9248SMarcel Holtmann {
235a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
236a9de9248SMarcel Holtmann 	void *sent;
237a9de9248SMarcel Holtmann 
238a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
239a9de9248SMarcel Holtmann 
240a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
241a9de9248SMarcel Holtmann 	if (!sent)
242a9de9248SMarcel Holtmann 		return;
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds 	if (!status) {
245a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
246a9de9248SMarcel Holtmann 
2471da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2481da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2491da177e4SLinus Torvalds 		else
2501da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2511da177e4SLinus Torvalds 	}
252a9de9248SMarcel Holtmann 
25323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
254a9de9248SMarcel Holtmann }
2551da177e4SLinus Torvalds 
256a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
257a9de9248SMarcel Holtmann {
258a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
259a9de9248SMarcel Holtmann 	void *sent;
260a9de9248SMarcel Holtmann 
261a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
262a9de9248SMarcel Holtmann 
263a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2641da177e4SLinus Torvalds 	if (!sent)
265a9de9248SMarcel Holtmann 		return;
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds 	if (!status) {
268a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
269a9de9248SMarcel Holtmann 
2701da177e4SLinus Torvalds 		if (param)
2711da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2721da177e4SLinus Torvalds 		else
2731da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2741da177e4SLinus Torvalds 	}
275a9de9248SMarcel Holtmann 
27623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2771da177e4SLinus Torvalds }
2781da177e4SLinus Torvalds 
279a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
280a9de9248SMarcel Holtmann {
28136f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28236f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
283a9de9248SMarcel Holtmann 	void *sent;
2841da177e4SLinus Torvalds 
285a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
286a9de9248SMarcel Holtmann 
287a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2881da177e4SLinus Torvalds 	if (!sent)
289a9de9248SMarcel Holtmann 		return;
2901da177e4SLinus Torvalds 
29136f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
292a9de9248SMarcel Holtmann 
29356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29456e5cb86SJohan Hedberg 
2952d7cee58SJohan Hedberg 	if (status != 0) {
296744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
2972d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
2982d7cee58SJohan Hedberg 		goto done;
2992d7cee58SJohan Hedberg 	}
3002d7cee58SJohan Hedberg 
3019fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3029fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
303a9de9248SMarcel Holtmann 
30473f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3051da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3069fbcbb45SJohan Hedberg 		if (!old_iscan)
307744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
30816ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
30916ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31016ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31116ab91abSJohan Hedberg 									to);
31216ab91abSJohan Hedberg 		}
3139fbcbb45SJohan Hedberg 	} else if (old_iscan)
314744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3151da177e4SLinus Torvalds 
3169fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3171da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3189fbcbb45SJohan Hedberg 		if (!old_pscan)
319744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3209fbcbb45SJohan Hedberg 	} else if (old_pscan)
321744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
322a9de9248SMarcel Holtmann 
32336f7fc7eSJohan Hedberg done:
32456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
32523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3261da177e4SLinus Torvalds }
3271da177e4SLinus Torvalds 
328a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
329a9de9248SMarcel Holtmann {
330a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
331a9de9248SMarcel Holtmann 
332a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
333a9de9248SMarcel Holtmann 
334a9de9248SMarcel Holtmann 	if (rp->status)
335a9de9248SMarcel Holtmann 		return;
336a9de9248SMarcel Holtmann 
337a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
338a9de9248SMarcel Holtmann 
339a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
340a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
341a9de9248SMarcel Holtmann }
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
344a9de9248SMarcel Holtmann {
345a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
346a9de9248SMarcel Holtmann 	void *sent;
347a9de9248SMarcel Holtmann 
348a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
349a9de9248SMarcel Holtmann 
350f383f275SMarcel Holtmann 	if (status)
351f383f275SMarcel Holtmann 		return;
352f383f275SMarcel Holtmann 
353a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
354a9de9248SMarcel Holtmann 	if (!sent)
355a9de9248SMarcel Holtmann 		return;
356a9de9248SMarcel Holtmann 
357a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
358a9de9248SMarcel Holtmann }
359a9de9248SMarcel Holtmann 
360a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
361a9de9248SMarcel Holtmann {
362a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
363a9de9248SMarcel Holtmann 	__u16 setting;
364a9de9248SMarcel Holtmann 
365a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
366a9de9248SMarcel Holtmann 
367a9de9248SMarcel Holtmann 	if (rp->status)
368a9de9248SMarcel Holtmann 		return;
369a9de9248SMarcel Holtmann 
370a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
371a9de9248SMarcel Holtmann 
372a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
373a9de9248SMarcel Holtmann 		return;
374a9de9248SMarcel Holtmann 
375a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
376a9de9248SMarcel Holtmann 
377a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
378a9de9248SMarcel Holtmann 
379a9de9248SMarcel Holtmann 	if (hdev->notify) {
380a9de9248SMarcel Holtmann 		tasklet_disable(&hdev->tx_task);
381a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
382a9de9248SMarcel Holtmann 		tasklet_enable(&hdev->tx_task);
383a9de9248SMarcel Holtmann 	}
384a9de9248SMarcel Holtmann }
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
387a9de9248SMarcel Holtmann {
388a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
389f383f275SMarcel Holtmann 	__u16 setting;
390a9de9248SMarcel Holtmann 	void *sent;
391a9de9248SMarcel Holtmann 
392a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
393a9de9248SMarcel Holtmann 
394f383f275SMarcel Holtmann 	if (status)
395f383f275SMarcel Holtmann 		return;
396f383f275SMarcel Holtmann 
397a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
398a9de9248SMarcel Holtmann 	if (!sent)
399a9de9248SMarcel Holtmann 		return;
400a9de9248SMarcel Holtmann 
401f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4021da177e4SLinus Torvalds 
403f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
404f383f275SMarcel Holtmann 		return;
405f383f275SMarcel Holtmann 
4061da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4071da177e4SLinus Torvalds 
408a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4091da177e4SLinus Torvalds 
4101da177e4SLinus Torvalds 	if (hdev->notify) {
4111da177e4SLinus Torvalds 		tasklet_disable(&hdev->tx_task);
4121da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4131da177e4SLinus Torvalds 		tasklet_enable(&hdev->tx_task);
4141da177e4SLinus Torvalds 	}
4151da177e4SLinus Torvalds }
4161da177e4SLinus Torvalds 
417a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4181da177e4SLinus Torvalds {
419a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4201da177e4SLinus Torvalds 
421a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4221da177e4SLinus Torvalds 
42323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4241143e5a6SMarcel Holtmann }
4251143e5a6SMarcel Holtmann 
426333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
427333140b5SMarcel Holtmann {
428333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
429333140b5SMarcel Holtmann 
430333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
431333140b5SMarcel Holtmann 
432333140b5SMarcel Holtmann 	if (rp->status)
433333140b5SMarcel Holtmann 		return;
434333140b5SMarcel Holtmann 
435333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
436333140b5SMarcel Holtmann }
437333140b5SMarcel Holtmann 
438333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
439333140b5SMarcel Holtmann {
440333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
441333140b5SMarcel Holtmann 	void *sent;
442333140b5SMarcel Holtmann 
443333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
444333140b5SMarcel Holtmann 
445333140b5SMarcel Holtmann 	if (status)
446333140b5SMarcel Holtmann 		return;
447333140b5SMarcel Holtmann 
448333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
449333140b5SMarcel Holtmann 	if (!sent)
450333140b5SMarcel Holtmann 		return;
451333140b5SMarcel Holtmann 
452333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
453333140b5SMarcel Holtmann }
454333140b5SMarcel Holtmann 
455d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
456d5859e22SJohan Hedberg {
457d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
458d5859e22SJohan Hedberg 		return 2;
459d5859e22SJohan Hedberg 
460d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
461d5859e22SJohan Hedberg 		return 1;
462d5859e22SJohan Hedberg 
463d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
464d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
465d5859e22SJohan Hedberg 		return 1;
466d5859e22SJohan Hedberg 
467d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
468d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
469d5859e22SJohan Hedberg 			return 1;
470d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
471d5859e22SJohan Hedberg 			return 1;
472d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
473d5859e22SJohan Hedberg 			return 1;
474d5859e22SJohan Hedberg 	}
475d5859e22SJohan Hedberg 
476d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
477d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
478d5859e22SJohan Hedberg 		return 1;
479d5859e22SJohan Hedberg 
480d5859e22SJohan Hedberg 	return 0;
481d5859e22SJohan Hedberg }
482d5859e22SJohan Hedberg 
483d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
484d5859e22SJohan Hedberg {
485d5859e22SJohan Hedberg 	u8 mode;
486d5859e22SJohan Hedberg 
487d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
488d5859e22SJohan Hedberg 
489d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
490d5859e22SJohan Hedberg }
491d5859e22SJohan Hedberg 
492d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
493d5859e22SJohan Hedberg {
494d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
495d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
496d5859e22SJohan Hedberg 	 * command otherwise */
497d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
498d5859e22SJohan Hedberg 
4996de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5006de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5016de6c18dSVille Tervo 	if (hdev->lmp_ver <= 1)
5026de6c18dSVille Tervo 		return;
5036de6c18dSVille Tervo 
504d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
505d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
506d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
507d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
508d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
509d5859e22SJohan Hedberg 
510d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
511d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
512d5859e22SJohan Hedberg 
513d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
514d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
515d5859e22SJohan Hedberg 
516d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
517d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
518d5859e22SJohan Hedberg 
519d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
520d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
521d5859e22SJohan Hedberg 
522d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
523d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
524d5859e22SJohan Hedberg 
525d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
526d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
527d5859e22SJohan Hedberg 
528d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
529d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
530d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
531d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
532d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
533d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
534d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
535d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
536d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
537d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
538d5859e22SJohan Hedberg 					 * Features Notification */
539d5859e22SJohan Hedberg 	}
540d5859e22SJohan Hedberg 
541d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
542d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
543d5859e22SJohan Hedberg 
544d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
545d5859e22SJohan Hedberg }
546d5859e22SJohan Hedberg 
547e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
548e6100a25SAndre Guedes {
549e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
550e6100a25SAndre Guedes 
551e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
552e6100a25SAndre Guedes 
553e6100a25SAndre Guedes 	if (enable_le) {
554e6100a25SAndre Guedes 		cp.le = 1;
555e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
556e6100a25SAndre Guedes 	}
557e6100a25SAndre Guedes 
558e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
559e6100a25SAndre Guedes }
560e6100a25SAndre Guedes 
561d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
562d5859e22SJohan Hedberg {
563d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
564d5859e22SJohan Hedberg 
565d5859e22SJohan Hedberg 	if (hdev->lmp_ver > 1)
566d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
567d5859e22SJohan Hedberg 
568d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
569d5859e22SJohan Hedberg 		u8 mode = 0x01;
570d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
571d5859e22SJohan Hedberg 	}
572d5859e22SJohan Hedberg 
573d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
574d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
575d5859e22SJohan Hedberg 
576d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
577d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
578971e3a4bSAndre Guedes 
579971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
580971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
581971e3a4bSAndre Guedes 
582971e3a4bSAndre Guedes 		cp.page = 0x01;
583971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
584971e3a4bSAndre Guedes 							sizeof(cp), &cp);
585971e3a4bSAndre Guedes 	}
586e6100a25SAndre Guedes 
587e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
588e6100a25SAndre Guedes 		hci_set_le_support(hdev);
589d5859e22SJohan Hedberg }
590d5859e22SJohan Hedberg 
591a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
592a9de9248SMarcel Holtmann {
593a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5941143e5a6SMarcel Holtmann 
595a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5961143e5a6SMarcel Holtmann 
597a9de9248SMarcel Holtmann 	if (rp->status)
598a9de9248SMarcel Holtmann 		return;
5991143e5a6SMarcel Holtmann 
600a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
601e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
602d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
603e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
604d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6051da177e4SLinus Torvalds 
606a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
607a9de9248SMarcel Holtmann 					hdev->manufacturer,
608a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
609d5859e22SJohan Hedberg 
610d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
611d5859e22SJohan Hedberg 		hci_setup(hdev);
612d5859e22SJohan Hedberg }
613d5859e22SJohan Hedberg 
614d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
615d5859e22SJohan Hedberg {
616d5859e22SJohan Hedberg 	u16 link_policy = 0;
617d5859e22SJohan Hedberg 
618d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
619d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
620d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
621d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
622d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
623d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
624d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
625d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
626d5859e22SJohan Hedberg 
627d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
628d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
629d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6301da177e4SLinus Torvalds }
6311da177e4SLinus Torvalds 
632a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
633a9de9248SMarcel Holtmann {
634a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
635a9de9248SMarcel Holtmann 
636a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
637a9de9248SMarcel Holtmann 
638a9de9248SMarcel Holtmann 	if (rp->status)
639d5859e22SJohan Hedberg 		goto done;
640a9de9248SMarcel Holtmann 
641a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
642d5859e22SJohan Hedberg 
643d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
644d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
645d5859e22SJohan Hedberg 
646d5859e22SJohan Hedberg done:
647d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
648a9de9248SMarcel Holtmann }
649a9de9248SMarcel Holtmann 
650a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
651a9de9248SMarcel Holtmann {
652a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
653a9de9248SMarcel Holtmann 
654a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
655a9de9248SMarcel Holtmann 
656a9de9248SMarcel Holtmann 	if (rp->status)
657a9de9248SMarcel Holtmann 		return;
658a9de9248SMarcel Holtmann 
659a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6601da177e4SLinus Torvalds 
6611da177e4SLinus Torvalds 	/* Adjust default settings according to features
6621da177e4SLinus Torvalds 	 * supported by device. */
663a9de9248SMarcel Holtmann 
6641da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6651da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6661da177e4SLinus Torvalds 
6671da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6681da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6691da177e4SLinus Torvalds 
6705b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6711da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6725b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6735b7f9909SMarcel Holtmann 	}
6741da177e4SLinus Torvalds 
6755b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6761da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6775b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6785b7f9909SMarcel Holtmann 	}
6795b7f9909SMarcel Holtmann 
6805b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6815b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6825b7f9909SMarcel Holtmann 
6835b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6845b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6855b7f9909SMarcel Holtmann 
6865b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6875b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6881da177e4SLinus Torvalds 
689efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
690efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
691efc7688bSMarcel Holtmann 
692efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
693efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
694efc7688bSMarcel Holtmann 
695efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
696efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
697efc7688bSMarcel Holtmann 
698a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
699a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
700a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
701a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
702a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7031da177e4SLinus Torvalds }
7041da177e4SLinus Torvalds 
705971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
706971e3a4bSAndre Guedes 							struct sk_buff *skb)
707971e3a4bSAndre Guedes {
708971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
709971e3a4bSAndre Guedes 
710971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
711971e3a4bSAndre Guedes 
712971e3a4bSAndre Guedes 	if (rp->status)
713971e3a4bSAndre Guedes 		return;
714971e3a4bSAndre Guedes 
715971e3a4bSAndre Guedes 	memcpy(hdev->extfeatures, rp->features, 8);
716971e3a4bSAndre Guedes 
717971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
718971e3a4bSAndre Guedes }
719971e3a4bSAndre Guedes 
720a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
721a9de9248SMarcel Holtmann {
722a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
723a9de9248SMarcel Holtmann 
724a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
725a9de9248SMarcel Holtmann 
726a9de9248SMarcel Holtmann 	if (rp->status)
727a9de9248SMarcel Holtmann 		return;
728a9de9248SMarcel Holtmann 
729a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
730a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
731a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
732a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
733da1f5198SMarcel Holtmann 
734da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
735da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
736da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
737da1f5198SMarcel Holtmann 	}
738da1f5198SMarcel Holtmann 
739da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
740da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7411da177e4SLinus Torvalds 
742a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
743a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
744a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7451da177e4SLinus Torvalds }
7461da177e4SLinus Torvalds 
747a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
748a9de9248SMarcel Holtmann {
749a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7501da177e4SLinus Torvalds 
751a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
752a9de9248SMarcel Holtmann 
753a9de9248SMarcel Holtmann 	if (!rp->status)
754a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
755a9de9248SMarcel Holtmann 
75623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
75723bb5763SJohan Hedberg }
75823bb5763SJohan Hedberg 
75923bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
76023bb5763SJohan Hedberg {
76123bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
76223bb5763SJohan Hedberg 
76323bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
76423bb5763SJohan Hedberg 
76523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
7661da177e4SLinus Torvalds }
7671da177e4SLinus Torvalds 
768928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
769928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
770928abaa7SAndrei Emeltchenko {
771928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
772928abaa7SAndrei Emeltchenko 
773928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
774928abaa7SAndrei Emeltchenko 
775928abaa7SAndrei Emeltchenko 	if (rp->status)
776928abaa7SAndrei Emeltchenko 		return;
777928abaa7SAndrei Emeltchenko 
778928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
779928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
780928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
781928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
782928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
783928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
784928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
785928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
786928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
787928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
788928abaa7SAndrei Emeltchenko 
789928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
790928abaa7SAndrei Emeltchenko }
791928abaa7SAndrei Emeltchenko 
792b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
793b0916ea0SJohan Hedberg 							struct sk_buff *skb)
794b0916ea0SJohan Hedberg {
795b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
796b0916ea0SJohan Hedberg 
797b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
798b0916ea0SJohan Hedberg 
799b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
800b0916ea0SJohan Hedberg }
801b0916ea0SJohan Hedberg 
802d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
803d5859e22SJohan Hedberg {
804d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
805d5859e22SJohan Hedberg 
806d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
807d5859e22SJohan Hedberg 
808d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
809d5859e22SJohan Hedberg }
810d5859e22SJohan Hedberg 
811d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
812d5859e22SJohan Hedberg 							struct sk_buff *skb)
813d5859e22SJohan Hedberg {
814d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
815d5859e22SJohan Hedberg 
816d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
817d5859e22SJohan Hedberg 
818d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
819d5859e22SJohan Hedberg }
820d5859e22SJohan Hedberg 
821d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
822d5859e22SJohan Hedberg 							struct sk_buff *skb)
823d5859e22SJohan Hedberg {
824d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
825d5859e22SJohan Hedberg 
826d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
827d5859e22SJohan Hedberg 
828d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
829d5859e22SJohan Hedberg }
830d5859e22SJohan Hedberg 
831d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
832d5859e22SJohan Hedberg {
833d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
834d5859e22SJohan Hedberg 
835d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
836d5859e22SJohan Hedberg 
837d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
838d5859e22SJohan Hedberg }
839d5859e22SJohan Hedberg 
840980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
841980e1a53SJohan Hedberg {
842980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
843980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
844980e1a53SJohan Hedberg 	struct hci_conn *conn;
845980e1a53SJohan Hedberg 
846980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
847980e1a53SJohan Hedberg 
84856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
84956e5cb86SJohan Hedberg 
850980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
851744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
852980e1a53SJohan Hedberg 
853980e1a53SJohan Hedberg 	if (rp->status != 0)
85456e5cb86SJohan Hedberg 		goto unlock;
855980e1a53SJohan Hedberg 
856980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
857980e1a53SJohan Hedberg 	if (!cp)
85856e5cb86SJohan Hedberg 		goto unlock;
859980e1a53SJohan Hedberg 
860980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
861980e1a53SJohan Hedberg 	if (conn)
862980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
86356e5cb86SJohan Hedberg 
86456e5cb86SJohan Hedberg unlock:
86556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
866980e1a53SJohan Hedberg }
867980e1a53SJohan Hedberg 
868980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
869980e1a53SJohan Hedberg {
870980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
871980e1a53SJohan Hedberg 
872980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
873980e1a53SJohan Hedberg 
87456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
87556e5cb86SJohan Hedberg 
876980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
877744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
878980e1a53SJohan Hedberg 								rp->status);
87956e5cb86SJohan Hedberg 
88056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
881980e1a53SJohan Hedberg }
88256e5cb86SJohan Hedberg 
8836ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8846ed58ec5SVille Tervo 				       struct sk_buff *skb)
8856ed58ec5SVille Tervo {
8866ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
8876ed58ec5SVille Tervo 
8886ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
8896ed58ec5SVille Tervo 
8906ed58ec5SVille Tervo 	if (rp->status)
8916ed58ec5SVille Tervo 		return;
8926ed58ec5SVille Tervo 
8936ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
8946ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8956ed58ec5SVille Tervo 
8966ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8976ed58ec5SVille Tervo 
8986ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8996ed58ec5SVille Tervo 
9006ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9016ed58ec5SVille Tervo }
902980e1a53SJohan Hedberg 
903a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
904a5c29683SJohan Hedberg {
905a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
906a5c29683SJohan Hedberg 
907a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
908a5c29683SJohan Hedberg 
90956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
91056e5cb86SJohan Hedberg 
911a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
912744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
913a5c29683SJohan Hedberg 								rp->status);
91456e5cb86SJohan Hedberg 
91556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
916a5c29683SJohan Hedberg }
917a5c29683SJohan Hedberg 
918a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
919a5c29683SJohan Hedberg 							struct sk_buff *skb)
920a5c29683SJohan Hedberg {
921a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
922a5c29683SJohan Hedberg 
923a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
924a5c29683SJohan Hedberg 
92556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92656e5cb86SJohan Hedberg 
927a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
928744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
929a5c29683SJohan Hedberg 								rp->status);
93056e5cb86SJohan Hedberg 
93156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
932a5c29683SJohan Hedberg }
933a5c29683SJohan Hedberg 
934c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
935c35938b2SSzymon Janc 							struct sk_buff *skb)
936c35938b2SSzymon Janc {
937c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
938c35938b2SSzymon Janc 
939c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
940c35938b2SSzymon Janc 
94156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
942744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
943c35938b2SSzymon Janc 						rp->randomizer, rp->status);
94456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
945c35938b2SSzymon Janc }
946c35938b2SSzymon Janc 
947eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
948eb9d91f5SAndre Guedes 					struct sk_buff *skb)
949eb9d91f5SAndre Guedes {
950eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
951eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
952eb9d91f5SAndre Guedes 
953eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
954eb9d91f5SAndre Guedes 
955eb9d91f5SAndre Guedes 	if (status)
956eb9d91f5SAndre Guedes 		return;
957eb9d91f5SAndre Guedes 
958eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
959eb9d91f5SAndre Guedes 	if (!cp)
960eb9d91f5SAndre Guedes 		return;
961eb9d91f5SAndre Guedes 
96235815085SAndre Guedes 	if (cp->enable == 0x01) {
96335815085SAndre Guedes 		del_timer(&hdev->adv_timer);
964a8f13c8cSAndre Guedes 
965a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
966eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
967a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
96835815085SAndre Guedes 	} else if (cp->enable == 0x00) {
96935815085SAndre Guedes 		mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
97035815085SAndre Guedes 	}
971eb9d91f5SAndre Guedes }
972eb9d91f5SAndre Guedes 
973a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
974a7a595f6SVinicius Costa Gomes {
975a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
976a7a595f6SVinicius Costa Gomes 
977a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
978a7a595f6SVinicius Costa Gomes 
979a7a595f6SVinicius Costa Gomes 	if (rp->status)
980a7a595f6SVinicius Costa Gomes 		return;
981a7a595f6SVinicius Costa Gomes 
982a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
983a7a595f6SVinicius Costa Gomes }
984a7a595f6SVinicius Costa Gomes 
985a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
986a7a595f6SVinicius Costa Gomes {
987a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
988a7a595f6SVinicius Costa Gomes 
989a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
990a7a595f6SVinicius Costa Gomes 
991a7a595f6SVinicius Costa Gomes 	if (rp->status)
992a7a595f6SVinicius Costa Gomes 		return;
993a7a595f6SVinicius Costa Gomes 
994a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
995a7a595f6SVinicius Costa Gomes }
996a7a595f6SVinicius Costa Gomes 
997f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
998f9b49306SAndre Guedes 							struct sk_buff *skb)
999f9b49306SAndre Guedes {
1000f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1001f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1002f9b49306SAndre Guedes 
1003f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1004f9b49306SAndre Guedes 
1005f9b49306SAndre Guedes 	if (status)
1006f9b49306SAndre Guedes 		return;
1007f9b49306SAndre Guedes 
1008f9b49306SAndre Guedes 	cp.page = 0x01;
1009f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1010f9b49306SAndre Guedes }
1011f9b49306SAndre Guedes 
1012a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1013a9de9248SMarcel Holtmann {
1014a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1015a9de9248SMarcel Holtmann 
1016a9de9248SMarcel Holtmann 	if (status) {
101723bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1018a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
101956e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1020164a6e78SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
10217a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
102256e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1023314b2381SJohan Hedberg 		return;
1024314b2381SJohan Hedberg 	}
1025314b2381SJohan Hedberg 
102689352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
102789352e7dSAndre Guedes 
102856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1029744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 1);
103056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1031a9de9248SMarcel Holtmann }
1032a9de9248SMarcel Holtmann 
10331da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
10341da177e4SLinus Torvalds {
1035a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
10361da177e4SLinus Torvalds 	struct hci_conn *conn;
10371da177e4SLinus Torvalds 
1038a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1039a9de9248SMarcel Holtmann 
1040a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
10411da177e4SLinus Torvalds 	if (!cp)
10421da177e4SLinus Torvalds 		return;
10431da177e4SLinus Torvalds 
10441da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10451da177e4SLinus Torvalds 
10461da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
10471da177e4SLinus Torvalds 
1048a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
10491da177e4SLinus Torvalds 
10501da177e4SLinus Torvalds 	if (status) {
10511da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
10524c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
10531da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
10541da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
10551da177e4SLinus Torvalds 				hci_conn_del(conn);
10564c67bc74SMarcel Holtmann 			} else
10574c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
10581da177e4SLinus Torvalds 		}
10591da177e4SLinus Torvalds 	} else {
10601da177e4SLinus Torvalds 		if (!conn) {
10611da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
10621da177e4SLinus Torvalds 			if (conn) {
10631da177e4SLinus Torvalds 				conn->out = 1;
10641da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
10651da177e4SLinus Torvalds 			} else
1066893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
10671da177e4SLinus Torvalds 		}
10681da177e4SLinus Torvalds 	}
10691da177e4SLinus Torvalds 
10701da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10711da177e4SLinus Torvalds }
10721da177e4SLinus Torvalds 
1073a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
10741da177e4SLinus Torvalds {
1075a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
10761da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
10771da177e4SLinus Torvalds 	__u16 handle;
10781da177e4SLinus Torvalds 
1079b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1080b6a0dc82SMarcel Holtmann 
1081a9de9248SMarcel Holtmann 	if (!status)
1082a9de9248SMarcel Holtmann 		return;
1083a9de9248SMarcel Holtmann 
1084a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
10851da177e4SLinus Torvalds 	if (!cp)
1086a9de9248SMarcel Holtmann 		return;
10871da177e4SLinus Torvalds 
10881da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
10891da177e4SLinus Torvalds 
1090a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
10911da177e4SLinus Torvalds 
10921da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10931da177e4SLinus Torvalds 
10941da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
10955a08ecceSAndrei Emeltchenko 	if (acl) {
10965a08ecceSAndrei Emeltchenko 		sco = acl->link;
10975a08ecceSAndrei Emeltchenko 		if (sco) {
10981da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
10991da177e4SLinus Torvalds 
11001da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11011da177e4SLinus Torvalds 			hci_conn_del(sco);
11021da177e4SLinus Torvalds 		}
11035a08ecceSAndrei Emeltchenko 	}
11041da177e4SLinus Torvalds 
11051da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11061da177e4SLinus Torvalds }
11071da177e4SLinus Torvalds 
1108f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1109f8558555SMarcel Holtmann {
1110f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1111f8558555SMarcel Holtmann 	struct hci_conn *conn;
1112f8558555SMarcel Holtmann 
1113f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1114f8558555SMarcel Holtmann 
1115f8558555SMarcel Holtmann 	if (!status)
1116f8558555SMarcel Holtmann 		return;
1117f8558555SMarcel Holtmann 
1118f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1119f8558555SMarcel Holtmann 	if (!cp)
1120f8558555SMarcel Holtmann 		return;
1121f8558555SMarcel Holtmann 
1122f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1123f8558555SMarcel Holtmann 
1124f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1125f8558555SMarcel Holtmann 	if (conn) {
1126f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1127f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1128f8558555SMarcel Holtmann 			hci_conn_put(conn);
1129f8558555SMarcel Holtmann 		}
1130f8558555SMarcel Holtmann 	}
1131f8558555SMarcel Holtmann 
1132f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1133f8558555SMarcel Holtmann }
1134f8558555SMarcel Holtmann 
1135f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1136f8558555SMarcel Holtmann {
1137f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1138f8558555SMarcel Holtmann 	struct hci_conn *conn;
1139f8558555SMarcel Holtmann 
1140f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1141f8558555SMarcel Holtmann 
1142f8558555SMarcel Holtmann 	if (!status)
1143f8558555SMarcel Holtmann 		return;
1144f8558555SMarcel Holtmann 
1145f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1146f8558555SMarcel Holtmann 	if (!cp)
1147f8558555SMarcel Holtmann 		return;
1148f8558555SMarcel Holtmann 
1149f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1150f8558555SMarcel Holtmann 
1151f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1152f8558555SMarcel Holtmann 	if (conn) {
1153f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1154f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1155f8558555SMarcel Holtmann 			hci_conn_put(conn);
1156f8558555SMarcel Holtmann 		}
1157f8558555SMarcel Holtmann 	}
1158f8558555SMarcel Holtmann 
1159f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1160f8558555SMarcel Holtmann }
1161f8558555SMarcel Holtmann 
1162127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1163392599b9SJohan Hedberg 							struct hci_conn *conn)
1164392599b9SJohan Hedberg {
1165392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1166392599b9SJohan Hedberg 		return 0;
1167392599b9SJohan Hedberg 
1168765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1169392599b9SJohan Hedberg 		return 0;
1170392599b9SJohan Hedberg 
1171392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1172e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1173392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1174e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1175e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1176392599b9SJohan Hedberg 		return 0;
1177392599b9SJohan Hedberg 
1178392599b9SJohan Hedberg 	return 1;
1179392599b9SJohan Hedberg }
1180392599b9SJohan Hedberg 
1181a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
11821da177e4SLinus Torvalds {
1183127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1184127178d2SJohan Hedberg 	struct hci_conn *conn;
1185127178d2SJohan Hedberg 
1186a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1187127178d2SJohan Hedberg 
1188127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1189127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1190127178d2SJohan Hedberg 	if (!status)
1191127178d2SJohan Hedberg 		return;
1192127178d2SJohan Hedberg 
1193127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1194127178d2SJohan Hedberg 	if (!cp)
1195127178d2SJohan Hedberg 		return;
1196127178d2SJohan Hedberg 
1197127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1198127178d2SJohan Hedberg 
1199127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
120079c6c70cSJohan Hedberg 	if (!conn)
120179c6c70cSJohan Hedberg 		goto unlock;
120279c6c70cSJohan Hedberg 
120379c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
120479c6c70cSJohan Hedberg 		goto unlock;
120579c6c70cSJohan Hedberg 
120679c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1207127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1208127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1209127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1210127178d2SJohan Hedberg 	}
1211127178d2SJohan Hedberg 
121279c6c70cSJohan Hedberg unlock:
1213127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1214a9de9248SMarcel Holtmann }
12151da177e4SLinus Torvalds 
1216769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1217769be974SMarcel Holtmann {
1218769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1219769be974SMarcel Holtmann 	struct hci_conn *conn;
1220769be974SMarcel Holtmann 
1221769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1222769be974SMarcel Holtmann 
1223769be974SMarcel Holtmann 	if (!status)
1224769be974SMarcel Holtmann 		return;
1225769be974SMarcel Holtmann 
1226769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1227769be974SMarcel Holtmann 	if (!cp)
1228769be974SMarcel Holtmann 		return;
1229769be974SMarcel Holtmann 
1230769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1231769be974SMarcel Holtmann 
1232769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1233769be974SMarcel Holtmann 	if (conn) {
1234769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1235769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1236769be974SMarcel Holtmann 			hci_conn_put(conn);
1237769be974SMarcel Holtmann 		}
1238769be974SMarcel Holtmann 	}
1239769be974SMarcel Holtmann 
1240769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1241769be974SMarcel Holtmann }
1242769be974SMarcel Holtmann 
1243769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1244769be974SMarcel Holtmann {
1245769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1246769be974SMarcel Holtmann 	struct hci_conn *conn;
1247769be974SMarcel Holtmann 
1248769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1249769be974SMarcel Holtmann 
1250769be974SMarcel Holtmann 	if (!status)
1251769be974SMarcel Holtmann 		return;
1252769be974SMarcel Holtmann 
1253769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1254769be974SMarcel Holtmann 	if (!cp)
1255769be974SMarcel Holtmann 		return;
1256769be974SMarcel Holtmann 
1257769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1258769be974SMarcel Holtmann 
1259769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1260769be974SMarcel Holtmann 	if (conn) {
1261769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1262769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1263769be974SMarcel Holtmann 			hci_conn_put(conn);
1264769be974SMarcel Holtmann 		}
1265769be974SMarcel Holtmann 	}
1266769be974SMarcel Holtmann 
1267769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1268769be974SMarcel Holtmann }
1269769be974SMarcel Holtmann 
1270a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1271a9de9248SMarcel Holtmann {
1272b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1273b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1274b6a0dc82SMarcel Holtmann 	__u16 handle;
1275b6a0dc82SMarcel Holtmann 
1276a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1277b6a0dc82SMarcel Holtmann 
1278b6a0dc82SMarcel Holtmann 	if (!status)
1279b6a0dc82SMarcel Holtmann 		return;
1280b6a0dc82SMarcel Holtmann 
1281b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1282b6a0dc82SMarcel Holtmann 	if (!cp)
1283b6a0dc82SMarcel Holtmann 		return;
1284b6a0dc82SMarcel Holtmann 
1285b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1286b6a0dc82SMarcel Holtmann 
1287b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1288b6a0dc82SMarcel Holtmann 
1289b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1290b6a0dc82SMarcel Holtmann 
1291b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12925a08ecceSAndrei Emeltchenko 	if (acl) {
12935a08ecceSAndrei Emeltchenko 		sco = acl->link;
12945a08ecceSAndrei Emeltchenko 		if (sco) {
1295b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1296b6a0dc82SMarcel Holtmann 
1297b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1298b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1299b6a0dc82SMarcel Holtmann 		}
13005a08ecceSAndrei Emeltchenko 	}
1301b6a0dc82SMarcel Holtmann 
1302b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1303a9de9248SMarcel Holtmann }
1304a9de9248SMarcel Holtmann 
1305a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1306a9de9248SMarcel Holtmann {
1307a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
130804837f64SMarcel Holtmann 	struct hci_conn *conn;
130904837f64SMarcel Holtmann 
1310a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1311a9de9248SMarcel Holtmann 
1312a9de9248SMarcel Holtmann 	if (!status)
1313a9de9248SMarcel Holtmann 		return;
1314a9de9248SMarcel Holtmann 
1315a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
131604837f64SMarcel Holtmann 	if (!cp)
1317a9de9248SMarcel Holtmann 		return;
131804837f64SMarcel Holtmann 
131904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
132004837f64SMarcel Holtmann 
132104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1322e73439d8SMarcel Holtmann 	if (conn) {
132304837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
132404837f64SMarcel Holtmann 
1325e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1326e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1327e73439d8SMarcel Holtmann 	}
1328e73439d8SMarcel Holtmann 
132904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
133004837f64SMarcel Holtmann }
133104837f64SMarcel Holtmann 
1332a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1333a9de9248SMarcel Holtmann {
1334a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
133504837f64SMarcel Holtmann 	struct hci_conn *conn;
133604837f64SMarcel Holtmann 
1337a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1338a9de9248SMarcel Holtmann 
1339a9de9248SMarcel Holtmann 	if (!status)
1340a9de9248SMarcel Holtmann 		return;
1341a9de9248SMarcel Holtmann 
1342a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
134304837f64SMarcel Holtmann 	if (!cp)
1344a9de9248SMarcel Holtmann 		return;
134504837f64SMarcel Holtmann 
134604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
134704837f64SMarcel Holtmann 
134804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1349e73439d8SMarcel Holtmann 	if (conn) {
135004837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
135104837f64SMarcel Holtmann 
1352e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1353e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1354e73439d8SMarcel Holtmann 	}
1355e73439d8SMarcel Holtmann 
135604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
135704837f64SMarcel Holtmann }
135804837f64SMarcel Holtmann 
1359fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1360fcd89c09SVille Tervo {
1361fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1362fcd89c09SVille Tervo 	struct hci_conn *conn;
1363fcd89c09SVille Tervo 
1364fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1365fcd89c09SVille Tervo 
1366fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1367fcd89c09SVille Tervo 	if (!cp)
1368fcd89c09SVille Tervo 		return;
1369fcd89c09SVille Tervo 
1370fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1371fcd89c09SVille Tervo 
1372fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1373fcd89c09SVille Tervo 
1374fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1375fcd89c09SVille Tervo 		conn);
1376fcd89c09SVille Tervo 
1377fcd89c09SVille Tervo 	if (status) {
1378fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1379fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1380fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1381fcd89c09SVille Tervo 			hci_conn_del(conn);
1382fcd89c09SVille Tervo 		}
1383fcd89c09SVille Tervo 	} else {
1384fcd89c09SVille Tervo 		if (!conn) {
1385fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
138629b7988aSAndre Guedes 			if (conn) {
138729b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1388fcd89c09SVille Tervo 				conn->out = 1;
138929b7988aSAndre Guedes 			} else {
1390fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1391fcd89c09SVille Tervo 			}
1392fcd89c09SVille Tervo 		}
139329b7988aSAndre Guedes 	}
1394fcd89c09SVille Tervo 
1395fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1396fcd89c09SVille Tervo }
1397fcd89c09SVille Tervo 
1398a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1399a7a595f6SVinicius Costa Gomes {
1400a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1401a7a595f6SVinicius Costa Gomes }
1402a7a595f6SVinicius Costa Gomes 
14031da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14041da177e4SLinus Torvalds {
14051da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
14061da177e4SLinus Torvalds 
14071da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
14081da177e4SLinus Torvalds 
140923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
14106bd57416SMarcel Holtmann 
1411a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
141289352e7dSAndre Guedes 
141389352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
141489352e7dSAndre Guedes 		return;
141589352e7dSAndre Guedes 
141656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1417744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 0);
141856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
14191da177e4SLinus Torvalds }
14201da177e4SLinus Torvalds 
14211da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
14221da177e4SLinus Torvalds {
142345bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1424a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
14251da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
14261da177e4SLinus Torvalds 
14271da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
14281da177e4SLinus Torvalds 
142945bb4bf0SMarcel Holtmann 	if (!num_rsp)
143045bb4bf0SMarcel Holtmann 		return;
143145bb4bf0SMarcel Holtmann 
14321da177e4SLinus Torvalds 	hci_dev_lock(hdev);
143345bb4bf0SMarcel Holtmann 
1434e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
14351da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
14361da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
14371da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
14381da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
14391da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
14401da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
14411da177e4SLinus Torvalds 		data.rssi		= 0x00;
144241a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
14431da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
144448264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
14454c659c39SJohan Hedberg 						info->dev_class, 0, NULL);
14461da177e4SLinus Torvalds 	}
144745bb4bf0SMarcel Holtmann 
14481da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14491da177e4SLinus Torvalds }
14501da177e4SLinus Torvalds 
1451a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14521da177e4SLinus Torvalds {
1453a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1454a9de9248SMarcel Holtmann 	struct hci_conn *conn;
14551da177e4SLinus Torvalds 
1456a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
145745bb4bf0SMarcel Holtmann 
14581da177e4SLinus Torvalds 	hci_dev_lock(hdev);
145945bb4bf0SMarcel Holtmann 
1460a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
14619499237aSMarcel Holtmann 	if (!conn) {
14629499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
14639499237aSMarcel Holtmann 			goto unlock;
14649499237aSMarcel Holtmann 
14659499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1466a9de9248SMarcel Holtmann 		if (!conn)
1467a9de9248SMarcel Holtmann 			goto unlock;
146845bb4bf0SMarcel Holtmann 
14699499237aSMarcel Holtmann 		conn->type = SCO_LINK;
14709499237aSMarcel Holtmann 	}
14719499237aSMarcel Holtmann 
1472a9de9248SMarcel Holtmann 	if (!ev->status) {
1473a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1474769be974SMarcel Holtmann 
1475769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1476769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1477769be974SMarcel Holtmann 			hci_conn_hold(conn);
1478052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
147948264f06SJohan Hedberg 			mgmt_connected(hdev, &ev->bdaddr, conn->type,
148048264f06SJohan Hedberg 							conn->dst_type);
1481769be974SMarcel Holtmann 		} else
1482a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1483a9de9248SMarcel Holtmann 
14849eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
14857d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
14867d0db0a3SMarcel Holtmann 
1487a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1488a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1489a9de9248SMarcel Holtmann 
1490a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1491a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1492a9de9248SMarcel Holtmann 
1493a9de9248SMarcel Holtmann 		/* Get remote features */
1494a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1495a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1496a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1497769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1498769be974SMarcel Holtmann 							sizeof(cp), &cp);
149945bb4bf0SMarcel Holtmann 		}
1500a9de9248SMarcel Holtmann 
1501a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1502a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
1503a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1504a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1505a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1506a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1507a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1508a9de9248SMarcel Holtmann 		}
150917d5c04cSJohan Hedberg 	} else {
1510a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
151117d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1512744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
151348264f06SJohan Hedberg 						conn->dst_type, ev->status);
151417d5c04cSJohan Hedberg 	}
151545bb4bf0SMarcel Holtmann 
1516e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1517e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
151845bb4bf0SMarcel Holtmann 
1519769be974SMarcel Holtmann 	if (ev->status) {
1520a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1521a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1522c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1523c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1524a9de9248SMarcel Holtmann 
1525a9de9248SMarcel Holtmann unlock:
15261da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1527a9de9248SMarcel Holtmann 
1528a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
15291da177e4SLinus Torvalds }
15301da177e4SLinus Torvalds 
15311da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
15321da177e4SLinus Torvalds {
1533a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
15341da177e4SLinus Torvalds 	int mask = hdev->link_mode;
15351da177e4SLinus Torvalds 
1536a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
15371da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
15381da177e4SLinus Torvalds 
15391da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
15401da177e4SLinus Torvalds 
1541138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1542138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
15431da177e4SLinus Torvalds 		/* Connection accepted */
1544c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
15451da177e4SLinus Torvalds 		struct hci_conn *conn;
15461da177e4SLinus Torvalds 
15471da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1548b6a0dc82SMarcel Holtmann 
1549cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1550cc11b9c1SAndrei Emeltchenko 		if (ie)
1551c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1552c7bdd502SMarcel Holtmann 
15531da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
15541da177e4SLinus Torvalds 		if (!conn) {
1555cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1556cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1557893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
15581da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
15591da177e4SLinus Torvalds 				return;
15601da177e4SLinus Torvalds 			}
15611da177e4SLinus Torvalds 		}
1562b6a0dc82SMarcel Holtmann 
15631da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
15641da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1565b6a0dc82SMarcel Holtmann 
15661da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
15671da177e4SLinus Torvalds 
1568b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1569b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1570b6a0dc82SMarcel Holtmann 
15711da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
15721da177e4SLinus Torvalds 
15731da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
15741da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
15751da177e4SLinus Torvalds 			else
15761da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
15771da177e4SLinus Torvalds 
1578b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1579b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1580b6a0dc82SMarcel Holtmann 		} else {
1581b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1582b6a0dc82SMarcel Holtmann 
1583b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1584a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1585b6a0dc82SMarcel Holtmann 
1586b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1587b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1588b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1589b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1590b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1591b6a0dc82SMarcel Holtmann 
1592b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1593b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1594b6a0dc82SMarcel Holtmann 		}
15951da177e4SLinus Torvalds 	} else {
15961da177e4SLinus Torvalds 		/* Connection rejected */
15971da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
15981da177e4SLinus Torvalds 
15991da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
16009f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1601a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
16021da177e4SLinus Torvalds 	}
16031da177e4SLinus Torvalds }
16041da177e4SLinus Torvalds 
16051da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16061da177e4SLinus Torvalds {
1607a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
160804837f64SMarcel Holtmann 	struct hci_conn *conn;
16091da177e4SLinus Torvalds 
16101da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
16111da177e4SLinus Torvalds 
16121da177e4SLinus Torvalds 	hci_dev_lock(hdev);
16131da177e4SLinus Torvalds 
161404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1615f7520543SJohan Hedberg 	if (!conn)
1616f7520543SJohan Hedberg 		goto unlock;
1617f7520543SJohan Hedberg 
161837d9ef76SJohan Hedberg 	if (ev->status == 0)
16191da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
16207d0db0a3SMarcel Holtmann 
162137d9ef76SJohan Hedberg 	if (conn->type == ACL_LINK || conn->type == LE_LINK) {
162237d9ef76SJohan Hedberg 		if (ev->status != 0)
162337d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
162437d9ef76SJohan Hedberg 		else
162548264f06SJohan Hedberg 			mgmt_disconnected(hdev, &conn->dst, conn->type,
162648264f06SJohan Hedberg 							conn->dst_type);
162737d9ef76SJohan Hedberg 	}
1628f7520543SJohan Hedberg 
162937d9ef76SJohan Hedberg 	if (ev->status == 0) {
16302950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
16311da177e4SLinus Torvalds 		hci_conn_del(conn);
163237d9ef76SJohan Hedberg 	}
16331da177e4SLinus Torvalds 
1634f7520543SJohan Hedberg unlock:
16351da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16361da177e4SLinus Torvalds }
16371da177e4SLinus Torvalds 
1638a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1639a9de9248SMarcel Holtmann {
1640a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1641a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1642a9de9248SMarcel Holtmann 
1643a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1644a9de9248SMarcel Holtmann 
1645a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1646a9de9248SMarcel Holtmann 
1647a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1648d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1649d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1650d7556e20SWaldemar Rymarkiewicz 
1651765c2a96SJohan Hedberg 	if (!ev->status) {
165219f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1653d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1654d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
165519f8def0SWaldemar Rymarkiewicz 		} else {
1656a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1657765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
165819f8def0SWaldemar Rymarkiewicz 		}
16592a611692SJohan Hedberg 	} else {
1660744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
16612a611692SJohan Hedberg 	}
1662a9de9248SMarcel Holtmann 
1663a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
166419f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1665a9de9248SMarcel Holtmann 
1666f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1667d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1668f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1669f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1670f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1671d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1672d7556e20SWaldemar Rymarkiewicz 									&cp);
1673f8558555SMarcel Holtmann 		} else {
1674f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1675f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1676f8558555SMarcel Holtmann 			hci_conn_put(conn);
1677f8558555SMarcel Holtmann 		}
1678052b30b0SMarcel Holtmann 	} else {
1679a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1680a9de9248SMarcel Holtmann 
1681052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1682052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1683052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1684052b30b0SMarcel Holtmann 	}
1685052b30b0SMarcel Holtmann 
1686a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1687a9de9248SMarcel Holtmann 		if (!ev->status) {
1688a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1689f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1690f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1691d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1692d7556e20SWaldemar Rymarkiewicz 									&cp);
1693a9de9248SMarcel Holtmann 		} else {
1694a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1695a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1696a9de9248SMarcel Holtmann 		}
1697a9de9248SMarcel Holtmann 	}
1698a9de9248SMarcel Holtmann 
1699d7556e20SWaldemar Rymarkiewicz unlock:
1700a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1701a9de9248SMarcel Holtmann }
1702a9de9248SMarcel Holtmann 
1703a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1704a9de9248SMarcel Holtmann {
1705127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1706127178d2SJohan Hedberg 	struct hci_conn *conn;
1707127178d2SJohan Hedberg 
1708a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1709a9de9248SMarcel Holtmann 
1710a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1711127178d2SJohan Hedberg 
1712127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1713127178d2SJohan Hedberg 
1714a88a9652SJohan Hedberg 	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
1715744cf19eSJohan Hedberg 		mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
1716a88a9652SJohan Hedberg 
1717127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
171879c6c70cSJohan Hedberg 	if (!conn)
171979c6c70cSJohan Hedberg 		goto unlock;
172079c6c70cSJohan Hedberg 
172179c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
172279c6c70cSJohan Hedberg 		goto unlock;
172379c6c70cSJohan Hedberg 
172479c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1725127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1726127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1727127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1728127178d2SJohan Hedberg 	}
1729127178d2SJohan Hedberg 
173079c6c70cSJohan Hedberg unlock:
1731127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1732a9de9248SMarcel Holtmann }
1733a9de9248SMarcel Holtmann 
1734a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1735a9de9248SMarcel Holtmann {
1736a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1737a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1738a9de9248SMarcel Holtmann 
1739a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1740a9de9248SMarcel Holtmann 
1741a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1742a9de9248SMarcel Holtmann 
1743a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1744a9de9248SMarcel Holtmann 	if (conn) {
1745a9de9248SMarcel Holtmann 		if (!ev->status) {
1746ae293196SMarcel Holtmann 			if (ev->encrypt) {
1747ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1748ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1749a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1750da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1751ae293196SMarcel Holtmann 			} else
1752a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1753a9de9248SMarcel Holtmann 		}
1754a9de9248SMarcel Holtmann 
1755a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1756a9de9248SMarcel Holtmann 
1757f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1758f8558555SMarcel Holtmann 			if (!ev->status)
1759f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1760f8558555SMarcel Holtmann 
1761f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1762f8558555SMarcel Holtmann 			hci_conn_put(conn);
1763f8558555SMarcel Holtmann 		} else
1764a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1765a9de9248SMarcel Holtmann 	}
1766a9de9248SMarcel Holtmann 
1767a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1768a9de9248SMarcel Holtmann }
1769a9de9248SMarcel Holtmann 
1770a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1771a9de9248SMarcel Holtmann {
1772a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1773a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1774a9de9248SMarcel Holtmann 
1775a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1776a9de9248SMarcel Holtmann 
1777a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1778a9de9248SMarcel Holtmann 
1779a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1780a9de9248SMarcel Holtmann 	if (conn) {
1781a9de9248SMarcel Holtmann 		if (!ev->status)
1782a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1783a9de9248SMarcel Holtmann 
1784a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1785a9de9248SMarcel Holtmann 
1786a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1787a9de9248SMarcel Holtmann 	}
1788a9de9248SMarcel Holtmann 
1789a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1790a9de9248SMarcel Holtmann }
1791a9de9248SMarcel Holtmann 
1792a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1793a9de9248SMarcel Holtmann {
1794a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1795a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1796a9de9248SMarcel Holtmann 
1797a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1798a9de9248SMarcel Holtmann 
1799a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1800a9de9248SMarcel Holtmann 
1801a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1802ccd556feSJohan Hedberg 	if (!conn)
1803ccd556feSJohan Hedberg 		goto unlock;
1804ccd556feSJohan Hedberg 
1805769be974SMarcel Holtmann 	if (!ev->status)
1806a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1807a9de9248SMarcel Holtmann 
1808ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1809ccd556feSJohan Hedberg 		goto unlock;
1810ccd556feSJohan Hedberg 
1811ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1812769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1813769be974SMarcel Holtmann 		cp.handle = ev->handle;
1814769be974SMarcel Holtmann 		cp.page = 0x01;
1815ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1816769be974SMarcel Holtmann 							sizeof(cp), &cp);
1817392599b9SJohan Hedberg 		goto unlock;
1818392599b9SJohan Hedberg 	}
1819392599b9SJohan Hedberg 
1820127178d2SJohan Hedberg 	if (!ev->status) {
1821127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1822127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1823127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1824127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1825127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1826127178d2SJohan Hedberg 	}
1827392599b9SJohan Hedberg 
1828127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1829769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1830769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1831769be974SMarcel Holtmann 		hci_conn_put(conn);
1832769be974SMarcel Holtmann 	}
1833769be974SMarcel Holtmann 
1834ccd556feSJohan Hedberg unlock:
1835a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1836a9de9248SMarcel Holtmann }
1837a9de9248SMarcel Holtmann 
1838a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1839a9de9248SMarcel Holtmann {
1840a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1841a9de9248SMarcel Holtmann }
1842a9de9248SMarcel Holtmann 
1843a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1844a9de9248SMarcel Holtmann {
1845a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1846a9de9248SMarcel Holtmann }
1847a9de9248SMarcel Holtmann 
1848a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1849a9de9248SMarcel Holtmann {
1850a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1851a9de9248SMarcel Holtmann 	__u16 opcode;
1852a9de9248SMarcel Holtmann 
1853a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1854a9de9248SMarcel Holtmann 
1855a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1856a9de9248SMarcel Holtmann 
1857a9de9248SMarcel Holtmann 	switch (opcode) {
1858a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1859a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1860a9de9248SMarcel Holtmann 		break;
1861a9de9248SMarcel Holtmann 
1862a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1863a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1864a9de9248SMarcel Holtmann 		break;
1865a9de9248SMarcel Holtmann 
1866a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1867a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1868a9de9248SMarcel Holtmann 		break;
1869a9de9248SMarcel Holtmann 
1870a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1871a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1872a9de9248SMarcel Holtmann 		break;
1873a9de9248SMarcel Holtmann 
1874e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1875e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1876e4e8e37cSMarcel Holtmann 		break;
1877e4e8e37cSMarcel Holtmann 
1878a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1879a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1880a9de9248SMarcel Holtmann 		break;
1881a9de9248SMarcel Holtmann 
1882e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1883e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1884e4e8e37cSMarcel Holtmann 		break;
1885e4e8e37cSMarcel Holtmann 
1886e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1887e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1888e4e8e37cSMarcel Holtmann 		break;
1889e4e8e37cSMarcel Holtmann 
1890a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1891a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1892a9de9248SMarcel Holtmann 		break;
1893a9de9248SMarcel Holtmann 
1894a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1895a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1896a9de9248SMarcel Holtmann 		break;
1897a9de9248SMarcel Holtmann 
1898a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1899a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1900a9de9248SMarcel Holtmann 		break;
1901a9de9248SMarcel Holtmann 
1902a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1903a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1904a9de9248SMarcel Holtmann 		break;
1905a9de9248SMarcel Holtmann 
1906a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1907a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1908a9de9248SMarcel Holtmann 		break;
1909a9de9248SMarcel Holtmann 
1910a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1911a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1912a9de9248SMarcel Holtmann 		break;
1913a9de9248SMarcel Holtmann 
1914a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1915a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1916a9de9248SMarcel Holtmann 		break;
1917a9de9248SMarcel Holtmann 
1918a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1919a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1920a9de9248SMarcel Holtmann 		break;
1921a9de9248SMarcel Holtmann 
1922a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1923a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1924a9de9248SMarcel Holtmann 		break;
1925a9de9248SMarcel Holtmann 
1926a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1927a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1928a9de9248SMarcel Holtmann 		break;
1929a9de9248SMarcel Holtmann 
1930a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1931a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1932a9de9248SMarcel Holtmann 		break;
1933a9de9248SMarcel Holtmann 
1934333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1935333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1936333140b5SMarcel Holtmann 		break;
1937333140b5SMarcel Holtmann 
1938333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1939333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1940333140b5SMarcel Holtmann 		break;
1941333140b5SMarcel Holtmann 
1942a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1943a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1944a9de9248SMarcel Holtmann 		break;
1945a9de9248SMarcel Holtmann 
1946a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1947a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1948a9de9248SMarcel Holtmann 		break;
1949a9de9248SMarcel Holtmann 
1950a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1951a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1952a9de9248SMarcel Holtmann 		break;
1953a9de9248SMarcel Holtmann 
1954971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
1955971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
1956971e3a4bSAndre Guedes 		break;
1957971e3a4bSAndre Guedes 
1958a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
1959a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
1960a9de9248SMarcel Holtmann 		break;
1961a9de9248SMarcel Holtmann 
1962a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
1963a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
1964a9de9248SMarcel Holtmann 		break;
1965a9de9248SMarcel Holtmann 
196623bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
196723bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
196823bb5763SJohan Hedberg 		break;
196923bb5763SJohan Hedberg 
1970928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
1971928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
1972928abaa7SAndrei Emeltchenko 		break;
1973928abaa7SAndrei Emeltchenko 
1974b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
1975b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
1976b0916ea0SJohan Hedberg 		break;
1977b0916ea0SJohan Hedberg 
1978d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
1979d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
1980d5859e22SJohan Hedberg 		break;
1981d5859e22SJohan Hedberg 
1982d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
1983d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
1984d5859e22SJohan Hedberg 		break;
1985d5859e22SJohan Hedberg 
1986d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
1987d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
1988d5859e22SJohan Hedberg 		break;
1989d5859e22SJohan Hedberg 
1990d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
1991d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
1992d5859e22SJohan Hedberg 		break;
1993d5859e22SJohan Hedberg 
1994980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
1995980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
1996980e1a53SJohan Hedberg 		break;
1997980e1a53SJohan Hedberg 
1998980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
1999980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2000980e1a53SJohan Hedberg 		break;
2001980e1a53SJohan Hedberg 
2002c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2003c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2004c35938b2SSzymon Janc 		break;
2005c35938b2SSzymon Janc 
20066ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
20076ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
20086ed58ec5SVille Tervo 		break;
20096ed58ec5SVille Tervo 
2010a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2011a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2012a5c29683SJohan Hedberg 		break;
2013a5c29683SJohan Hedberg 
2014a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2015a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2016a5c29683SJohan Hedberg 		break;
2017a5c29683SJohan Hedberg 
2018eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2019eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2020eb9d91f5SAndre Guedes 		break;
2021eb9d91f5SAndre Guedes 
2022a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2023a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2024a7a595f6SVinicius Costa Gomes 		break;
2025a7a595f6SVinicius Costa Gomes 
2026a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2027a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2028a7a595f6SVinicius Costa Gomes 		break;
2029a7a595f6SVinicius Costa Gomes 
2030f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2031f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2032f9b49306SAndre Guedes 		break;
2033f9b49306SAndre Guedes 
2034a9de9248SMarcel Holtmann 	default:
2035a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2036a9de9248SMarcel Holtmann 		break;
2037a9de9248SMarcel Holtmann 	}
2038a9de9248SMarcel Holtmann 
20396bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
20406bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
20416bd32326SVille Tervo 
2042a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2043a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2044a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2045c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2046a9de9248SMarcel Holtmann 	}
2047a9de9248SMarcel Holtmann }
2048a9de9248SMarcel Holtmann 
2049a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2050a9de9248SMarcel Holtmann {
2051a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2052a9de9248SMarcel Holtmann 	__u16 opcode;
2053a9de9248SMarcel Holtmann 
2054a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2055a9de9248SMarcel Holtmann 
2056a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2057a9de9248SMarcel Holtmann 
2058a9de9248SMarcel Holtmann 	switch (opcode) {
2059a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2060a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2061a9de9248SMarcel Holtmann 		break;
2062a9de9248SMarcel Holtmann 
2063a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2064a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2065a9de9248SMarcel Holtmann 		break;
2066a9de9248SMarcel Holtmann 
2067a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2068a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2069a9de9248SMarcel Holtmann 		break;
2070a9de9248SMarcel Holtmann 
2071f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2072f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2073f8558555SMarcel Holtmann 		break;
2074f8558555SMarcel Holtmann 
2075f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2076f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2077f8558555SMarcel Holtmann 		break;
2078f8558555SMarcel Holtmann 
2079a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2080a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2081a9de9248SMarcel Holtmann 		break;
2082a9de9248SMarcel Holtmann 
2083769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2084769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2085769be974SMarcel Holtmann 		break;
2086769be974SMarcel Holtmann 
2087769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2088769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2089769be974SMarcel Holtmann 		break;
2090769be974SMarcel Holtmann 
2091a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2092a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2093a9de9248SMarcel Holtmann 		break;
2094a9de9248SMarcel Holtmann 
2095a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2096a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2097a9de9248SMarcel Holtmann 		break;
2098a9de9248SMarcel Holtmann 
2099a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2100a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2101a9de9248SMarcel Holtmann 		break;
2102a9de9248SMarcel Holtmann 
21038962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
21048962ee74SJohan Hedberg 		if (ev->status != 0)
210537d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
21068962ee74SJohan Hedberg 		break;
21078962ee74SJohan Hedberg 
2108fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2109fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2110fcd89c09SVille Tervo 		break;
2111fcd89c09SVille Tervo 
2112a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2113a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2114a7a595f6SVinicius Costa Gomes 		break;
2115a7a595f6SVinicius Costa Gomes 
2116a9de9248SMarcel Holtmann 	default:
2117a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2118a9de9248SMarcel Holtmann 		break;
2119a9de9248SMarcel Holtmann 	}
2120a9de9248SMarcel Holtmann 
21216bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
21226bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
21236bd32326SVille Tervo 
212410572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2125a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2126a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2127c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2128a9de9248SMarcel Holtmann 	}
2129a9de9248SMarcel Holtmann }
2130a9de9248SMarcel Holtmann 
2131a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2132a9de9248SMarcel Holtmann {
2133a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2134a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2135a9de9248SMarcel Holtmann 
2136a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2137a9de9248SMarcel Holtmann 
2138a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2139a9de9248SMarcel Holtmann 
2140a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2141a9de9248SMarcel Holtmann 	if (conn) {
2142a9de9248SMarcel Holtmann 		if (!ev->status) {
2143a9de9248SMarcel Holtmann 			if (ev->role)
2144a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2145a9de9248SMarcel Holtmann 			else
2146a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2147a9de9248SMarcel Holtmann 		}
2148a9de9248SMarcel Holtmann 
2149a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2150a9de9248SMarcel Holtmann 
2151a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2152a9de9248SMarcel Holtmann 	}
2153a9de9248SMarcel Holtmann 
2154a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2155a9de9248SMarcel Holtmann }
2156a9de9248SMarcel Holtmann 
21571da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
21581da177e4SLinus Torvalds {
2159a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
21601ebb9252SMarcel Holtmann 	__le16 *ptr;
21611da177e4SLinus Torvalds 	int i;
21621da177e4SLinus Torvalds 
21631da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
21641da177e4SLinus Torvalds 
21651da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
21661da177e4SLinus Torvalds 
21671da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
21681da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
21691da177e4SLinus Torvalds 		return;
21701da177e4SLinus Torvalds 	}
21711da177e4SLinus Torvalds 
21721da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
21731da177e4SLinus Torvalds 
21741ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
21751da177e4SLinus Torvalds 		struct hci_conn *conn;
21761da177e4SLinus Torvalds 		__u16  handle, count;
21771da177e4SLinus Torvalds 
217883985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
217983985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
21801da177e4SLinus Torvalds 
21811da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
21821da177e4SLinus Torvalds 		if (conn) {
21831da177e4SLinus Torvalds 			conn->sent -= count;
21841da177e4SLinus Torvalds 
21855b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
218670f23020SAndrei Emeltchenko 				hdev->acl_cnt += count;
218770f23020SAndrei Emeltchenko 				if (hdev->acl_cnt > hdev->acl_pkts)
21881da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
21896ed58ec5SVille Tervo 			} else if (conn->type == LE_LINK) {
21906ed58ec5SVille Tervo 				if (hdev->le_pkts) {
21916ed58ec5SVille Tervo 					hdev->le_cnt += count;
21926ed58ec5SVille Tervo 					if (hdev->le_cnt > hdev->le_pkts)
21936ed58ec5SVille Tervo 						hdev->le_cnt = hdev->le_pkts;
21946ed58ec5SVille Tervo 				} else {
21956ed58ec5SVille Tervo 					hdev->acl_cnt += count;
21966ed58ec5SVille Tervo 					if (hdev->acl_cnt > hdev->acl_pkts)
21976ed58ec5SVille Tervo 						hdev->acl_cnt = hdev->acl_pkts;
21986ed58ec5SVille Tervo 				}
21995b7f9909SMarcel Holtmann 			} else {
220070f23020SAndrei Emeltchenko 				hdev->sco_cnt += count;
220170f23020SAndrei Emeltchenko 				if (hdev->sco_cnt > hdev->sco_pkts)
22025b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
22031da177e4SLinus Torvalds 			}
22041da177e4SLinus Torvalds 		}
22051da177e4SLinus Torvalds 	}
2206a9de9248SMarcel Holtmann 
2207c78ae283SMarcel Holtmann 	tasklet_schedule(&hdev->tx_task);
22081da177e4SLinus Torvalds 
22091da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
22101da177e4SLinus Torvalds }
22111da177e4SLinus Torvalds 
221204837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
22131da177e4SLinus Torvalds {
2214a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
221504837f64SMarcel Holtmann 	struct hci_conn *conn;
22161da177e4SLinus Torvalds 
22171da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
22181da177e4SLinus Torvalds 
22191da177e4SLinus Torvalds 	hci_dev_lock(hdev);
22201da177e4SLinus Torvalds 
222104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
222204837f64SMarcel Holtmann 	if (conn) {
222304837f64SMarcel Holtmann 		conn->mode = ev->mode;
222404837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
222504837f64SMarcel Holtmann 
222604837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
222704837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
222804837f64SMarcel Holtmann 				conn->power_save = 1;
222904837f64SMarcel Holtmann 			else
223004837f64SMarcel Holtmann 				conn->power_save = 0;
223104837f64SMarcel Holtmann 		}
2232e73439d8SMarcel Holtmann 
2233e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2234e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
223504837f64SMarcel Holtmann 	}
223604837f64SMarcel Holtmann 
223704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
223804837f64SMarcel Holtmann }
223904837f64SMarcel Holtmann 
22401da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
22411da177e4SLinus Torvalds {
2242052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2243052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2244052b30b0SMarcel Holtmann 
2245a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2246052b30b0SMarcel Holtmann 
2247052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2248052b30b0SMarcel Holtmann 
2249052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2250b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2251b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2252b6f98044SWaldemar Rymarkiewicz 
2253b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2254052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2255052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2256052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2257052b30b0SMarcel Holtmann 	}
2258052b30b0SMarcel Holtmann 
225903b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
226003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
226103b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2262582fbe9eSJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->flags)) {
2263a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2264a770bb5aSWaldemar Rymarkiewicz 
2265a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2266a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2267a770bb5aSWaldemar Rymarkiewicz 		else
2268a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2269a770bb5aSWaldemar Rymarkiewicz 
2270744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2271a770bb5aSWaldemar Rymarkiewicz 	}
2272980e1a53SJohan Hedberg 
2273b6f98044SWaldemar Rymarkiewicz unlock:
2274052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
22751da177e4SLinus Torvalds }
22761da177e4SLinus Torvalds 
22771da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
22781da177e4SLinus Torvalds {
227955ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
228055ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
228155ed8ca1SJohan Hedberg 	struct hci_conn *conn;
228255ed8ca1SJohan Hedberg 	struct link_key *key;
228355ed8ca1SJohan Hedberg 
2284a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
228555ed8ca1SJohan Hedberg 
228655ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
228755ed8ca1SJohan Hedberg 		return;
228855ed8ca1SJohan Hedberg 
228955ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
229055ed8ca1SJohan Hedberg 
229155ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
229255ed8ca1SJohan Hedberg 	if (!key) {
229355ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
229455ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
229555ed8ca1SJohan Hedberg 		goto not_found;
229655ed8ca1SJohan Hedberg 	}
229755ed8ca1SJohan Hedberg 
229855ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
229955ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
230055ed8ca1SJohan Hedberg 
2301b6020ba0SWaldemar Rymarkiewicz 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2302b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
230355ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
230455ed8ca1SJohan Hedberg 		goto not_found;
230555ed8ca1SJohan Hedberg 	}
230655ed8ca1SJohan Hedberg 
230755ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
230860b83f57SWaldemar Rymarkiewicz 	if (conn) {
230960b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
231060b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
231160b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
231255ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
231355ed8ca1SJohan Hedberg 			goto not_found;
231455ed8ca1SJohan Hedberg 		}
231555ed8ca1SJohan Hedberg 
231660b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
231760b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
231860b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
231960b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
232060b83f57SWaldemar Rymarkiewicz 			goto not_found;
232160b83f57SWaldemar Rymarkiewicz 		}
232260b83f57SWaldemar Rymarkiewicz 
232360b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
232460b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
232560b83f57SWaldemar Rymarkiewicz 	}
232660b83f57SWaldemar Rymarkiewicz 
232755ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
232855ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
232955ed8ca1SJohan Hedberg 
233055ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
233155ed8ca1SJohan Hedberg 
233255ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
233355ed8ca1SJohan Hedberg 
233455ed8ca1SJohan Hedberg 	return;
233555ed8ca1SJohan Hedberg 
233655ed8ca1SJohan Hedberg not_found:
233755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
233855ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
23391da177e4SLinus Torvalds }
23401da177e4SLinus Torvalds 
23411da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
23421da177e4SLinus Torvalds {
2343052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2344052b30b0SMarcel Holtmann 	struct hci_conn *conn;
234555ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2346052b30b0SMarcel Holtmann 
2347a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2348052b30b0SMarcel Holtmann 
2349052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2350052b30b0SMarcel Holtmann 
2351052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2352052b30b0SMarcel Holtmann 	if (conn) {
2353052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2354052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2355980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
235613d39315SWaldemar Rymarkiewicz 
235713d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
235813d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
235913d39315SWaldemar Rymarkiewicz 
2360052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2361052b30b0SMarcel Holtmann 	}
2362052b30b0SMarcel Holtmann 
236355ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2364d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
236555ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
236655ed8ca1SJohan Hedberg 
2367052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
23681da177e4SLinus Torvalds }
23691da177e4SLinus Torvalds 
237004837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
237104837f64SMarcel Holtmann {
2372a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
237304837f64SMarcel Holtmann 	struct hci_conn *conn;
237404837f64SMarcel Holtmann 
237504837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
237604837f64SMarcel Holtmann 
237704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
237804837f64SMarcel Holtmann 
237904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
23801da177e4SLinus Torvalds 	if (conn && !ev->status) {
23811da177e4SLinus Torvalds 		struct inquiry_entry *ie;
23821da177e4SLinus Torvalds 
2383cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2384cc11b9c1SAndrei Emeltchenko 		if (ie) {
23851da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
23861da177e4SLinus Torvalds 			ie->timestamp = jiffies;
23871da177e4SLinus Torvalds 		}
23881da177e4SLinus Torvalds 	}
23891da177e4SLinus Torvalds 
23901da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
23911da177e4SLinus Torvalds }
23921da177e4SLinus Torvalds 
2393a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2394a8746417SMarcel Holtmann {
2395a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2396a8746417SMarcel Holtmann 	struct hci_conn *conn;
2397a8746417SMarcel Holtmann 
2398a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2399a8746417SMarcel Holtmann 
2400a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2401a8746417SMarcel Holtmann 
2402a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2403a8746417SMarcel Holtmann 	if (conn && !ev->status)
2404a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2405a8746417SMarcel Holtmann 
2406a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2407a8746417SMarcel Holtmann }
2408a8746417SMarcel Holtmann 
240985a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
241085a1e930SMarcel Holtmann {
2411a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
241285a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
241385a1e930SMarcel Holtmann 
241485a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
241585a1e930SMarcel Holtmann 
241685a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
241785a1e930SMarcel Holtmann 
2418cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2419cc11b9c1SAndrei Emeltchenko 	if (ie) {
242085a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
242185a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
242285a1e930SMarcel Holtmann 	}
242385a1e930SMarcel Holtmann 
242485a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
242585a1e930SMarcel Holtmann }
242685a1e930SMarcel Holtmann 
2427a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2428a9de9248SMarcel Holtmann {
2429a9de9248SMarcel Holtmann 	struct inquiry_data data;
2430a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2431a9de9248SMarcel Holtmann 
2432a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2433a9de9248SMarcel Holtmann 
2434a9de9248SMarcel Holtmann 	if (!num_rsp)
2435a9de9248SMarcel Holtmann 		return;
2436a9de9248SMarcel Holtmann 
2437a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2438a9de9248SMarcel Holtmann 
2439a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2440138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2441138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2442a9de9248SMarcel Holtmann 
2443e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2444a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2445a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2446a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2447a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2448a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2449a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2450a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
245141a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2452a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
245348264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2454e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2455e17acd40SJohan Hedberg 						NULL);
2456a9de9248SMarcel Holtmann 		}
2457a9de9248SMarcel Holtmann 	} else {
2458a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2459a9de9248SMarcel Holtmann 
2460e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2461a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2462a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2463a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2464a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2465a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2466a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2467a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
246841a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2469a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
247048264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2471e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2472e17acd40SJohan Hedberg 						NULL);
2473a9de9248SMarcel Holtmann 		}
2474a9de9248SMarcel Holtmann 	}
2475a9de9248SMarcel Holtmann 
2476a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2477a9de9248SMarcel Holtmann }
2478a9de9248SMarcel Holtmann 
2479a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2480a9de9248SMarcel Holtmann {
248141a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
248241a96212SMarcel Holtmann 	struct hci_conn *conn;
248341a96212SMarcel Holtmann 
2484a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
248541a96212SMarcel Holtmann 
248641a96212SMarcel Holtmann 	hci_dev_lock(hdev);
248741a96212SMarcel Holtmann 
248841a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2489ccd556feSJohan Hedberg 	if (!conn)
2490ccd556feSJohan Hedberg 		goto unlock;
2491ccd556feSJohan Hedberg 
2492769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
249341a96212SMarcel Holtmann 		struct inquiry_entry *ie;
249441a96212SMarcel Holtmann 
2495cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2496cc11b9c1SAndrei Emeltchenko 		if (ie)
249741a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
249841a96212SMarcel Holtmann 
249941a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
250041a96212SMarcel Holtmann 	}
250141a96212SMarcel Holtmann 
2502ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2503ccd556feSJohan Hedberg 		goto unlock;
2504ccd556feSJohan Hedberg 
2505127178d2SJohan Hedberg 	if (!ev->status) {
2506127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2507127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2508127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2509127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2510127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2511127178d2SJohan Hedberg 	}
2512392599b9SJohan Hedberg 
2513127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2514769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2515769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2516769be974SMarcel Holtmann 		hci_conn_put(conn);
2517769be974SMarcel Holtmann 	}
2518769be974SMarcel Holtmann 
2519ccd556feSJohan Hedberg unlock:
252041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2521a9de9248SMarcel Holtmann }
2522a9de9248SMarcel Holtmann 
2523a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2524a9de9248SMarcel Holtmann {
2525b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2526b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2527b6a0dc82SMarcel Holtmann 
2528b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2529b6a0dc82SMarcel Holtmann 
2530b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2531b6a0dc82SMarcel Holtmann 
2532b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
25339dc0a3afSMarcel Holtmann 	if (!conn) {
25349dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
25359dc0a3afSMarcel Holtmann 			goto unlock;
25369dc0a3afSMarcel Holtmann 
25379dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2538b6a0dc82SMarcel Holtmann 		if (!conn)
2539b6a0dc82SMarcel Holtmann 			goto unlock;
2540b6a0dc82SMarcel Holtmann 
25419dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
25429dc0a3afSMarcel Holtmann 	}
25439dc0a3afSMarcel Holtmann 
2544732547f9SMarcel Holtmann 	switch (ev->status) {
2545732547f9SMarcel Holtmann 	case 0x00:
2546732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2547732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2548732547f9SMarcel Holtmann 
25499eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2550732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2551732547f9SMarcel Holtmann 		break;
2552732547f9SMarcel Holtmann 
2553705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2554732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
25551038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2556732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2557732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2558efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2559efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2560efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2561efc7688bSMarcel Holtmann 			goto unlock;
2562efc7688bSMarcel Holtmann 		}
2563732547f9SMarcel Holtmann 		/* fall through */
2564efc7688bSMarcel Holtmann 
2565732547f9SMarcel Holtmann 	default:
2566b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2567732547f9SMarcel Holtmann 		break;
2568732547f9SMarcel Holtmann 	}
2569b6a0dc82SMarcel Holtmann 
2570b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2571b6a0dc82SMarcel Holtmann 	if (ev->status)
2572b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2573b6a0dc82SMarcel Holtmann 
2574b6a0dc82SMarcel Holtmann unlock:
2575b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2576a9de9248SMarcel Holtmann }
2577a9de9248SMarcel Holtmann 
2578a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2579a9de9248SMarcel Holtmann {
2580a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2581a9de9248SMarcel Holtmann }
2582a9de9248SMarcel Holtmann 
258304837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
258404837f64SMarcel Holtmann {
2585a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
258604837f64SMarcel Holtmann 
258704837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
258804837f64SMarcel Holtmann }
258904837f64SMarcel Holtmann 
2590a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2591a9de9248SMarcel Holtmann {
2592a9de9248SMarcel Holtmann 	struct inquiry_data data;
2593a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2594a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2595a9de9248SMarcel Holtmann 
2596a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2597a9de9248SMarcel Holtmann 
2598a9de9248SMarcel Holtmann 	if (!num_rsp)
2599a9de9248SMarcel Holtmann 		return;
2600a9de9248SMarcel Holtmann 
2601a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2602a9de9248SMarcel Holtmann 
2603e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2604a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2605a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2606a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2607a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2608a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2609a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2610a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
261141a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2612a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
261348264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
26144c659c39SJohan Hedberg 				info->dev_class, info->rssi, info->data);
2615a9de9248SMarcel Holtmann 	}
2616a9de9248SMarcel Holtmann 
2617a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2618a9de9248SMarcel Holtmann }
2619a9de9248SMarcel Holtmann 
262017fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
262117fa4b9dSJohan Hedberg {
262217fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
262317fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
262417fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
262517fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
262617fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
262717fa4b9dSJohan Hedberg 			return 0x02;
262817fa4b9dSJohan Hedberg 		else
262917fa4b9dSJohan Hedberg 			return 0x03;
263017fa4b9dSJohan Hedberg 	}
263117fa4b9dSJohan Hedberg 
263217fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
263317fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
263458797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
263517fa4b9dSJohan Hedberg 
263617fa4b9dSJohan Hedberg 	return conn->auth_type;
263717fa4b9dSJohan Hedberg }
263817fa4b9dSJohan Hedberg 
26390493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26400493684eSMarcel Holtmann {
26410493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
26420493684eSMarcel Holtmann 	struct hci_conn *conn;
26430493684eSMarcel Holtmann 
26440493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
26450493684eSMarcel Holtmann 
26460493684eSMarcel Holtmann 	hci_dev_lock(hdev);
26470493684eSMarcel Holtmann 
26480493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
264903b555e1SJohan Hedberg 	if (!conn)
265003b555e1SJohan Hedberg 		goto unlock;
265103b555e1SJohan Hedberg 
26520493684eSMarcel Holtmann 	hci_conn_hold(conn);
26530493684eSMarcel Holtmann 
265403b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
265503b555e1SJohan Hedberg 		goto unlock;
265603b555e1SJohan Hedberg 
265703b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
265803b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
265917fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
266017fa4b9dSJohan Hedberg 
266117fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
266217fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
26637cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
26647cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
266517fa4b9dSJohan Hedberg 
2666ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2667ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2668ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2669ce85ee13SSzymon Janc 		else
2670ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2671ce85ee13SSzymon Janc 
267217fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
267317fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
267403b555e1SJohan Hedberg 	} else {
267503b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
267603b555e1SJohan Hedberg 
267703b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
26789f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
267903b555e1SJohan Hedberg 
268003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
268103b555e1SJohan Hedberg 							sizeof(cp), &cp);
268203b555e1SJohan Hedberg 	}
268303b555e1SJohan Hedberg 
268403b555e1SJohan Hedberg unlock:
268503b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
268603b555e1SJohan Hedberg }
268703b555e1SJohan Hedberg 
268803b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
268903b555e1SJohan Hedberg {
269003b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
269103b555e1SJohan Hedberg 	struct hci_conn *conn;
269203b555e1SJohan Hedberg 
269303b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
269403b555e1SJohan Hedberg 
269503b555e1SJohan Hedberg 	hci_dev_lock(hdev);
269603b555e1SJohan Hedberg 
269703b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
269803b555e1SJohan Hedberg 	if (!conn)
269903b555e1SJohan Hedberg 		goto unlock;
270003b555e1SJohan Hedberg 
270103b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
270203b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
270303b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
270403b555e1SJohan Hedberg 
270503b555e1SJohan Hedberg unlock:
27060493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
27070493684eSMarcel Holtmann }
27080493684eSMarcel Holtmann 
2709a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2710a5c29683SJohan Hedberg 							struct sk_buff *skb)
2711a5c29683SJohan Hedberg {
2712a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
271355bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
27147a828908SJohan Hedberg 	struct hci_conn *conn;
2715a5c29683SJohan Hedberg 
2716a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
2717a5c29683SJohan Hedberg 
2718a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
2719a5c29683SJohan Hedberg 
27207a828908SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
27217a828908SJohan Hedberg 		goto unlock;
27227a828908SJohan Hedberg 
27237a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
27247a828908SJohan Hedberg 	if (!conn)
27257a828908SJohan Hedberg 		goto unlock;
27267a828908SJohan Hedberg 
27277a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
27287a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
27297a828908SJohan Hedberg 
27307a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
27317a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
27327a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
27337a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
27347a828908SJohan Hedberg 	 * bit set. */
27357a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
27367a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
27377a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
27387a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
27397a828908SJohan Hedberg 		goto unlock;
27407a828908SJohan Hedberg 	}
27417a828908SJohan Hedberg 
27427a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
27437a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
27447a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
274555bc1a37SJohan Hedberg 
274655bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
274755bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
274855bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
274955bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
275055bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
275155bc1a37SJohan Hedberg 			confirm_hint = 1;
275255bc1a37SJohan Hedberg 			goto confirm;
275355bc1a37SJohan Hedberg 		}
275455bc1a37SJohan Hedberg 
27559f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
27569f61656aSJohan Hedberg 						hdev->auto_accept_delay);
27579f61656aSJohan Hedberg 
27589f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
27599f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
27609f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
27619f61656aSJohan Hedberg 			goto unlock;
27629f61656aSJohan Hedberg 		}
27639f61656aSJohan Hedberg 
27647a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
27657a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
27667a828908SJohan Hedberg 		goto unlock;
27677a828908SJohan Hedberg 	}
27687a828908SJohan Hedberg 
276955bc1a37SJohan Hedberg confirm:
2770744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
277155bc1a37SJohan Hedberg 								confirm_hint);
2772a5c29683SJohan Hedberg 
27737a828908SJohan Hedberg unlock:
2774a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
2775a5c29683SJohan Hedberg }
2776a5c29683SJohan Hedberg 
27770493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
27780493684eSMarcel Holtmann {
27790493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
27800493684eSMarcel Holtmann 	struct hci_conn *conn;
27810493684eSMarcel Holtmann 
27820493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
27830493684eSMarcel Holtmann 
27840493684eSMarcel Holtmann 	hci_dev_lock(hdev);
27850493684eSMarcel Holtmann 
27860493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
27872a611692SJohan Hedberg 	if (!conn)
27882a611692SJohan Hedberg 		goto unlock;
27892a611692SJohan Hedberg 
27902a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
27912a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
27922a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
27932a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
27942a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
27952a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
2796744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
27972a611692SJohan Hedberg 
27980493684eSMarcel Holtmann 	hci_conn_put(conn);
27990493684eSMarcel Holtmann 
28002a611692SJohan Hedberg unlock:
28010493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
28020493684eSMarcel Holtmann }
28030493684eSMarcel Holtmann 
280441a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
280541a96212SMarcel Holtmann {
280641a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
280741a96212SMarcel Holtmann 	struct inquiry_entry *ie;
280841a96212SMarcel Holtmann 
280941a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
281041a96212SMarcel Holtmann 
281141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
281241a96212SMarcel Holtmann 
2813cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2814cc11b9c1SAndrei Emeltchenko 	if (ie)
281541a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
281641a96212SMarcel Holtmann 
281741a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
281841a96212SMarcel Holtmann }
281941a96212SMarcel Holtmann 
28202763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
28212763eda6SSzymon Janc 							struct sk_buff *skb)
28222763eda6SSzymon Janc {
28232763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
28242763eda6SSzymon Janc 	struct oob_data *data;
28252763eda6SSzymon Janc 
28262763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
28272763eda6SSzymon Janc 
28282763eda6SSzymon Janc 	hci_dev_lock(hdev);
28292763eda6SSzymon Janc 
2830e1ba1f15SSzymon Janc 	if (!test_bit(HCI_MGMT, &hdev->flags))
2831e1ba1f15SSzymon Janc 		goto unlock;
2832e1ba1f15SSzymon Janc 
28332763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
28342763eda6SSzymon Janc 	if (data) {
28352763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
28362763eda6SSzymon Janc 
28372763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
28382763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
28392763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
28402763eda6SSzymon Janc 
28412763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
28422763eda6SSzymon Janc 									&cp);
28432763eda6SSzymon Janc 	} else {
28442763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
28452763eda6SSzymon Janc 
28462763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
28472763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
28482763eda6SSzymon Janc 									&cp);
28492763eda6SSzymon Janc 	}
28502763eda6SSzymon Janc 
2851e1ba1f15SSzymon Janc unlock:
28522763eda6SSzymon Janc 	hci_dev_unlock(hdev);
28532763eda6SSzymon Janc }
28542763eda6SSzymon Janc 
2855fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2856fcd89c09SVille Tervo {
2857fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2858fcd89c09SVille Tervo 	struct hci_conn *conn;
2859fcd89c09SVille Tervo 
2860fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
2861fcd89c09SVille Tervo 
2862fcd89c09SVille Tervo 	hci_dev_lock(hdev);
2863fcd89c09SVille Tervo 
2864fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2865b62f328bSVille Tervo 	if (!conn) {
2866b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2867b62f328bSVille Tervo 		if (!conn) {
2868b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
2869b62f328bSVille Tervo 			hci_dev_unlock(hdev);
2870b62f328bSVille Tervo 			return;
2871b62f328bSVille Tervo 		}
287229b7988aSAndre Guedes 
287329b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
2874b62f328bSVille Tervo 	}
2875fcd89c09SVille Tervo 
2876fcd89c09SVille Tervo 	if (ev->status) {
287748264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
287848264f06SJohan Hedberg 						conn->dst_type, ev->status);
2879fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
2880fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
2881fcd89c09SVille Tervo 		hci_conn_del(conn);
2882fcd89c09SVille Tervo 		goto unlock;
2883fcd89c09SVille Tervo 	}
2884fcd89c09SVille Tervo 
288548264f06SJohan Hedberg 	mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
288683bc71b4SVinicius Costa Gomes 
28877b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
2888fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
2889fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
2890fcd89c09SVille Tervo 
2891fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
2892fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
2893fcd89c09SVille Tervo 
2894fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
2895fcd89c09SVille Tervo 
2896fcd89c09SVille Tervo unlock:
2897fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
2898fcd89c09SVille Tervo }
2899fcd89c09SVille Tervo 
29009aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
29019aa04c91SAndre Guedes 						struct sk_buff *skb)
29029aa04c91SAndre Guedes {
2903e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
2904e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
29059aa04c91SAndre Guedes 
29069aa04c91SAndre Guedes 	hci_dev_lock(hdev);
29079aa04c91SAndre Guedes 
2908e95beb41SAndre Guedes 	while (num_reports--) {
2909e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
2910e95beb41SAndre Guedes 
29119aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
29129aa04c91SAndre Guedes 
2913e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
29149aa04c91SAndre Guedes 	}
29159aa04c91SAndre Guedes 
29169aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
29179aa04c91SAndre Guedes }
29189aa04c91SAndre Guedes 
2919a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
2920a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
2921a7a595f6SVinicius Costa Gomes {
2922a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
2923a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
2924bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
2925a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
2926bea710feSVinicius Costa Gomes 	struct link_key *ltk;
2927a7a595f6SVinicius Costa Gomes 
2928a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
2929a7a595f6SVinicius Costa Gomes 
2930a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
2931a7a595f6SVinicius Costa Gomes 
2932a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2933bea710feSVinicius Costa Gomes 	if (conn == NULL)
2934bea710feSVinicius Costa Gomes 		goto not_found;
2935a7a595f6SVinicius Costa Gomes 
2936bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
2937bea710feSVinicius Costa Gomes 	if (ltk == NULL)
2938bea710feSVinicius Costa Gomes 		goto not_found;
2939bea710feSVinicius Costa Gomes 
2940bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
2941a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
2942726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
2943a7a595f6SVinicius Costa Gomes 
2944a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
2945a7a595f6SVinicius Costa Gomes 
2946a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
2947bea710feSVinicius Costa Gomes 
2948bea710feSVinicius Costa Gomes 	return;
2949bea710feSVinicius Costa Gomes 
2950bea710feSVinicius Costa Gomes not_found:
2951bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
2952bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
2953bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
2954a7a595f6SVinicius Costa Gomes }
2955a7a595f6SVinicius Costa Gomes 
2956fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2957fcd89c09SVille Tervo {
2958fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
2959fcd89c09SVille Tervo 
2960fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
2961fcd89c09SVille Tervo 
2962fcd89c09SVille Tervo 	switch (le_ev->subevent) {
2963fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
2964fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
2965fcd89c09SVille Tervo 		break;
2966fcd89c09SVille Tervo 
29679aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
29689aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
29699aa04c91SAndre Guedes 		break;
29709aa04c91SAndre Guedes 
2971a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
2972a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
2973a7a595f6SVinicius Costa Gomes 		break;
2974a7a595f6SVinicius Costa Gomes 
2975fcd89c09SVille Tervo 	default:
2976fcd89c09SVille Tervo 		break;
2977fcd89c09SVille Tervo 	}
2978fcd89c09SVille Tervo }
2979fcd89c09SVille Tervo 
29801da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
29811da177e4SLinus Torvalds {
2982a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
2983a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
29841da177e4SLinus Torvalds 
29851da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
29861da177e4SLinus Torvalds 
2987a9de9248SMarcel Holtmann 	switch (event) {
29881da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
29891da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
29901da177e4SLinus Torvalds 		break;
29911da177e4SLinus Torvalds 
29921da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
29931da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
29941da177e4SLinus Torvalds 		break;
29951da177e4SLinus Torvalds 
2996a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
2997a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
299821d9e30eSMarcel Holtmann 		break;
299921d9e30eSMarcel Holtmann 
30001da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
30011da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
30021da177e4SLinus Torvalds 		break;
30031da177e4SLinus Torvalds 
30041da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
30051da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
30061da177e4SLinus Torvalds 		break;
30071da177e4SLinus Torvalds 
30081da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
30091da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
30101da177e4SLinus Torvalds 		break;
30111da177e4SLinus Torvalds 
3012a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3013a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3014a9de9248SMarcel Holtmann 		break;
3015a9de9248SMarcel Holtmann 
30161da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
30171da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
30181da177e4SLinus Torvalds 		break;
30191da177e4SLinus Torvalds 
3020a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3021a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3022a9de9248SMarcel Holtmann 		break;
3023a9de9248SMarcel Holtmann 
3024a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3025a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3026a9de9248SMarcel Holtmann 		break;
3027a9de9248SMarcel Holtmann 
3028a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3029a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3030a9de9248SMarcel Holtmann 		break;
3031a9de9248SMarcel Holtmann 
3032a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3033a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3034a9de9248SMarcel Holtmann 		break;
3035a9de9248SMarcel Holtmann 
3036a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3037a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3038a9de9248SMarcel Holtmann 		break;
3039a9de9248SMarcel Holtmann 
3040a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3041a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3042a9de9248SMarcel Holtmann 		break;
3043a9de9248SMarcel Holtmann 
3044a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3045a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3046a9de9248SMarcel Holtmann 		break;
3047a9de9248SMarcel Holtmann 
3048a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3049a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3050a9de9248SMarcel Holtmann 		break;
3051a9de9248SMarcel Holtmann 
3052a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3053a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
30541da177e4SLinus Torvalds 		break;
30551da177e4SLinus Torvalds 
30561da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
30571da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
30581da177e4SLinus Torvalds 		break;
30591da177e4SLinus Torvalds 
30601da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
30611da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
30621da177e4SLinus Torvalds 		break;
30631da177e4SLinus Torvalds 
30641da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
30651da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
30661da177e4SLinus Torvalds 		break;
30671da177e4SLinus Torvalds 
30681da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
30691da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
30701da177e4SLinus Torvalds 		break;
30711da177e4SLinus Torvalds 
3072a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3073a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3074a8746417SMarcel Holtmann 		break;
3075a8746417SMarcel Holtmann 
307685a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
307785a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
307885a1e930SMarcel Holtmann 		break;
307985a1e930SMarcel Holtmann 
3080a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3081a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3082a9de9248SMarcel Holtmann 		break;
3083a9de9248SMarcel Holtmann 
3084a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3085a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3086a9de9248SMarcel Holtmann 		break;
3087a9de9248SMarcel Holtmann 
3088a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3089a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3090a9de9248SMarcel Holtmann 		break;
3091a9de9248SMarcel Holtmann 
3092a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3093a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3094a9de9248SMarcel Holtmann 		break;
3095a9de9248SMarcel Holtmann 
309604837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
309704837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
309804837f64SMarcel Holtmann 		break;
309904837f64SMarcel Holtmann 
3100a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3101a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
31021da177e4SLinus Torvalds 		break;
31031da177e4SLinus Torvalds 
31040493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
31050493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
31060493684eSMarcel Holtmann 		break;
31070493684eSMarcel Holtmann 
310803b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
310903b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
311003b555e1SJohan Hedberg 		break;
311103b555e1SJohan Hedberg 
3112a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3113a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3114a5c29683SJohan Hedberg 		break;
3115a5c29683SJohan Hedberg 
31160493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
31170493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
31180493684eSMarcel Holtmann 		break;
31190493684eSMarcel Holtmann 
312041a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
312141a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
312241a96212SMarcel Holtmann 		break;
312341a96212SMarcel Holtmann 
3124fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3125fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3126fcd89c09SVille Tervo 		break;
3127fcd89c09SVille Tervo 
31282763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
31292763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
31302763eda6SSzymon Janc 		break;
31312763eda6SSzymon Janc 
31321da177e4SLinus Torvalds 	default:
3133a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
31341da177e4SLinus Torvalds 		break;
31351da177e4SLinus Torvalds 	}
31361da177e4SLinus Torvalds 
31371da177e4SLinus Torvalds 	kfree_skb(skb);
31381da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
31391da177e4SLinus Torvalds }
31401da177e4SLinus Torvalds 
31411da177e4SLinus Torvalds /* Generate internal stack event */
31421da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
31431da177e4SLinus Torvalds {
31441da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
31451da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
31461da177e4SLinus Torvalds 	struct sk_buff *skb;
31471da177e4SLinus Torvalds 
31481da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
31491da177e4SLinus Torvalds 	if (!skb)
31501da177e4SLinus Torvalds 		return;
31511da177e4SLinus Torvalds 
31521da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
31531da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
31541da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
31551da177e4SLinus Torvalds 
31561da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
31571da177e4SLinus Torvalds 	ev->type = type;
31581da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
31591da177e4SLinus Torvalds 
3160576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3161a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3162576c7d85SMarcel Holtmann 
31630d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
31641da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3165eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
31661da177e4SLinus Torvalds 	kfree_skb(skb);
31671da177e4SLinus Torvalds }
3168e6100a25SAndre Guedes 
3169669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3170e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3171