xref: /openbmc/linux/net/bluetooth/hci_event.c (revision c599008f)
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 
48eb939922SRusty Russell static bool 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);
68ff9ef578SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
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);
197d23264a8SAndre Guedes 
1987005ff17SJohan Hedberg 	/* Reset all flags, except persistent ones */
19995947a39SHemant Gupta 	hdev->dev_flags &= BIT(HCI_MGMT) | BIT(HCI_SETUP) | BIT(HCI_AUTO_OFF) |
20095947a39SHemant Gupta 				BIT(HCI_LINK_KEYS) | BIT(HCI_DEBUG_KEYS);
201a9de9248SMarcel Holtmann }
202a9de9248SMarcel Holtmann 
203a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
204a9de9248SMarcel Holtmann {
205a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2061da177e4SLinus Torvalds 	void *sent;
2071da177e4SLinus Torvalds 
208a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2091da177e4SLinus Torvalds 
210a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2111da177e4SLinus Torvalds 	if (!sent)
212a9de9248SMarcel Holtmann 		return;
2131da177e4SLinus Torvalds 
21456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21556e5cb86SJohan Hedberg 
216a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
217744cf19eSJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
218b312b161SJohan Hedberg 
21956e5cb86SJohan Hedberg 	if (status == 0)
2201f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
22156e5cb86SJohan Hedberg 
22256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
223a9de9248SMarcel Holtmann }
224a9de9248SMarcel Holtmann 
225a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
226a9de9248SMarcel Holtmann {
227a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
228a9de9248SMarcel Holtmann 
229a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
230a9de9248SMarcel Holtmann 
231a9de9248SMarcel Holtmann 	if (rp->status)
232a9de9248SMarcel Holtmann 		return;
233a9de9248SMarcel Holtmann 
2341f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
235a9de9248SMarcel Holtmann }
236a9de9248SMarcel Holtmann 
237a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
238a9de9248SMarcel Holtmann {
239a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
240a9de9248SMarcel Holtmann 	void *sent;
241a9de9248SMarcel Holtmann 
242a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
243a9de9248SMarcel Holtmann 
244a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
245a9de9248SMarcel Holtmann 	if (!sent)
246a9de9248SMarcel Holtmann 		return;
2471da177e4SLinus Torvalds 
2481da177e4SLinus Torvalds 	if (!status) {
249a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
250a9de9248SMarcel Holtmann 
2511da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2521da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2531da177e4SLinus Torvalds 		else
2541da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2551da177e4SLinus Torvalds 	}
256a9de9248SMarcel Holtmann 
25723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
258a9de9248SMarcel Holtmann }
2591da177e4SLinus Torvalds 
260a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
261a9de9248SMarcel Holtmann {
262a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
263a9de9248SMarcel Holtmann 	void *sent;
264a9de9248SMarcel Holtmann 
265a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
266a9de9248SMarcel Holtmann 
267a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2681da177e4SLinus Torvalds 	if (!sent)
269a9de9248SMarcel Holtmann 		return;
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds 	if (!status) {
272a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
273a9de9248SMarcel Holtmann 
2741da177e4SLinus Torvalds 		if (param)
2751da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2761da177e4SLinus Torvalds 		else
2771da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2781da177e4SLinus Torvalds 	}
279a9de9248SMarcel Holtmann 
28023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2811da177e4SLinus Torvalds }
2821da177e4SLinus Torvalds 
283a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
284a9de9248SMarcel Holtmann {
28536f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28636f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
287a9de9248SMarcel Holtmann 	void *sent;
2881da177e4SLinus Torvalds 
289a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
290a9de9248SMarcel Holtmann 
291a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2921da177e4SLinus Torvalds 	if (!sent)
293a9de9248SMarcel Holtmann 		return;
2941da177e4SLinus Torvalds 
29536f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
296a9de9248SMarcel Holtmann 
29756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29856e5cb86SJohan Hedberg 
2992d7cee58SJohan Hedberg 	if (status != 0) {
300744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3012d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3022d7cee58SJohan Hedberg 		goto done;
3032d7cee58SJohan Hedberg 	}
3042d7cee58SJohan Hedberg 
3059fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3069fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
307a9de9248SMarcel Holtmann 
30873f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3091da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3109fbcbb45SJohan Hedberg 		if (!old_iscan)
311744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31216ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
31316ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31416ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31516ab91abSJohan Hedberg 									to);
31616ab91abSJohan Hedberg 		}
3179fbcbb45SJohan Hedberg 	} else if (old_iscan)
318744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3191da177e4SLinus Torvalds 
3209fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3211da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3229fbcbb45SJohan Hedberg 		if (!old_pscan)
323744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3249fbcbb45SJohan Hedberg 	} else if (old_pscan)
325744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
326a9de9248SMarcel Holtmann 
32736f7fc7eSJohan Hedberg done:
32856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
32923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
332a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
333a9de9248SMarcel Holtmann {
334a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
335a9de9248SMarcel Holtmann 
336a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
337a9de9248SMarcel Holtmann 
338a9de9248SMarcel Holtmann 	if (rp->status)
339a9de9248SMarcel Holtmann 		return;
340a9de9248SMarcel Holtmann 
341a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
344a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
345a9de9248SMarcel Holtmann }
346a9de9248SMarcel Holtmann 
347a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
348a9de9248SMarcel Holtmann {
349a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
350a9de9248SMarcel Holtmann 	void *sent;
351a9de9248SMarcel Holtmann 
352a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
353a9de9248SMarcel Holtmann 
354f383f275SMarcel Holtmann 	if (status)
355f383f275SMarcel Holtmann 		return;
356f383f275SMarcel Holtmann 
357a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
358a9de9248SMarcel Holtmann 	if (!sent)
359a9de9248SMarcel Holtmann 		return;
360a9de9248SMarcel Holtmann 
361a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
362a9de9248SMarcel Holtmann }
363a9de9248SMarcel Holtmann 
364a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
365a9de9248SMarcel Holtmann {
366a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
367a9de9248SMarcel Holtmann 	__u16 setting;
368a9de9248SMarcel Holtmann 
369a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
370a9de9248SMarcel Holtmann 
371a9de9248SMarcel Holtmann 	if (rp->status)
372a9de9248SMarcel Holtmann 		return;
373a9de9248SMarcel Holtmann 
374a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
375a9de9248SMarcel Holtmann 
376a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
377a9de9248SMarcel Holtmann 		return;
378a9de9248SMarcel Holtmann 
379a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
380a9de9248SMarcel Holtmann 
381a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
382a9de9248SMarcel Holtmann 
3833c54711cSGustavo F. Padovan 	if (hdev->notify)
384a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
385a9de9248SMarcel Holtmann }
386a9de9248SMarcel Holtmann 
387a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
388a9de9248SMarcel Holtmann {
389a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
390f383f275SMarcel Holtmann 	__u16 setting;
391a9de9248SMarcel Holtmann 	void *sent;
392a9de9248SMarcel Holtmann 
393a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
394a9de9248SMarcel Holtmann 
395f383f275SMarcel Holtmann 	if (status)
396f383f275SMarcel Holtmann 		return;
397f383f275SMarcel Holtmann 
398a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
399a9de9248SMarcel Holtmann 	if (!sent)
400a9de9248SMarcel Holtmann 		return;
401a9de9248SMarcel Holtmann 
402f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4031da177e4SLinus Torvalds 
404f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
405f383f275SMarcel Holtmann 		return;
406f383f275SMarcel Holtmann 
4071da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4081da177e4SLinus Torvalds 
409a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4101da177e4SLinus Torvalds 
4113c54711cSGustavo F. Padovan 	if (hdev->notify)
4121da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4131da177e4SLinus Torvalds }
4141da177e4SLinus Torvalds 
415a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4161da177e4SLinus Torvalds {
417a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4181da177e4SLinus Torvalds 
419a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4201da177e4SLinus Torvalds 
42123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4221143e5a6SMarcel Holtmann }
4231143e5a6SMarcel Holtmann 
424333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
425333140b5SMarcel Holtmann {
426333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
427333140b5SMarcel Holtmann 
428333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
429333140b5SMarcel Holtmann 
430333140b5SMarcel Holtmann 	if (rp->status)
431333140b5SMarcel Holtmann 		return;
432333140b5SMarcel Holtmann 
43384bde9d6SJohan Hedberg 	if (rp->mode)
43484bde9d6SJohan Hedberg 		set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
43584bde9d6SJohan Hedberg 	else
43684bde9d6SJohan Hedberg 		clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
437333140b5SMarcel Holtmann }
438333140b5SMarcel Holtmann 
439333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
440333140b5SMarcel Holtmann {
441333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
442333140b5SMarcel Holtmann 	void *sent;
443333140b5SMarcel Holtmann 
444333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
445333140b5SMarcel Holtmann 
446333140b5SMarcel Holtmann 	if (status)
447333140b5SMarcel Holtmann 		return;
448333140b5SMarcel Holtmann 
449333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
450333140b5SMarcel Holtmann 	if (!sent)
451333140b5SMarcel Holtmann 		return;
452333140b5SMarcel Holtmann 
45384bde9d6SJohan Hedberg 	if (*((u8 *) sent))
45484bde9d6SJohan Hedberg 		set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
45584bde9d6SJohan Hedberg 	else
45684bde9d6SJohan Hedberg 		clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
457333140b5SMarcel Holtmann }
458333140b5SMarcel Holtmann 
459d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
460d5859e22SJohan Hedberg {
461d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
462d5859e22SJohan Hedberg 		return 2;
463d5859e22SJohan Hedberg 
464d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
465d5859e22SJohan Hedberg 		return 1;
466d5859e22SJohan Hedberg 
467d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
468d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
469d5859e22SJohan Hedberg 		return 1;
470d5859e22SJohan Hedberg 
471d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
472d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
473d5859e22SJohan Hedberg 			return 1;
474d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
475d5859e22SJohan Hedberg 			return 1;
476d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
477d5859e22SJohan Hedberg 			return 1;
478d5859e22SJohan Hedberg 	}
479d5859e22SJohan Hedberg 
480d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
481d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
482d5859e22SJohan Hedberg 		return 1;
483d5859e22SJohan Hedberg 
484d5859e22SJohan Hedberg 	return 0;
485d5859e22SJohan Hedberg }
486d5859e22SJohan Hedberg 
487d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
488d5859e22SJohan Hedberg {
489d5859e22SJohan Hedberg 	u8 mode;
490d5859e22SJohan Hedberg 
491d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
492d5859e22SJohan Hedberg 
493d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
494d5859e22SJohan Hedberg }
495d5859e22SJohan Hedberg 
496d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
497d5859e22SJohan Hedberg {
498d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
499d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
500d5859e22SJohan Hedberg 	 * command otherwise */
501d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
502d5859e22SJohan Hedberg 
5036de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5046de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5055a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
5066de6c18dSVille Tervo 		return;
5076de6c18dSVille Tervo 
508d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
509d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
510d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
511d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
512d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
513d5859e22SJohan Hedberg 
514d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
515d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
516d5859e22SJohan Hedberg 
517d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
518d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
519d5859e22SJohan Hedberg 
520d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
521d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
522d5859e22SJohan Hedberg 
523d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
524d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
525d5859e22SJohan Hedberg 
526d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
527d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
528d5859e22SJohan Hedberg 
529d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
530d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
531d5859e22SJohan Hedberg 
532d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
533d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
534d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
535d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
536d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
537d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
538d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
539d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
540d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
541d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
542d5859e22SJohan Hedberg 					 * Features Notification */
543d5859e22SJohan Hedberg 	}
544d5859e22SJohan Hedberg 
545d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
546d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
547d5859e22SJohan Hedberg 
548d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
549d5859e22SJohan Hedberg }
550d5859e22SJohan Hedberg 
551e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
552e6100a25SAndre Guedes {
553e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
554e6100a25SAndre Guedes 
555e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
556e6100a25SAndre Guedes 
557e6100a25SAndre Guedes 	if (enable_le) {
558e6100a25SAndre Guedes 		cp.le = 1;
559e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
560e6100a25SAndre Guedes 	}
561e6100a25SAndre Guedes 
562e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
563e6100a25SAndre Guedes }
564e6100a25SAndre Guedes 
565d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
566d5859e22SJohan Hedberg {
567e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
568e61ef499SAndrei Emeltchenko 		return;
569e61ef499SAndrei Emeltchenko 
570d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
571d5859e22SJohan Hedberg 
572d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
573d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
574d5859e22SJohan Hedberg 
575d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
576d5859e22SJohan Hedberg 		u8 mode = 0x01;
577d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
578d5859e22SJohan Hedberg 	}
579d5859e22SJohan Hedberg 
580d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
581d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
582d5859e22SJohan Hedberg 
583d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
584d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
585971e3a4bSAndre Guedes 
586971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
587971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
588971e3a4bSAndre Guedes 
589971e3a4bSAndre Guedes 		cp.page = 0x01;
590971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
591971e3a4bSAndre Guedes 							sizeof(cp), &cp);
592971e3a4bSAndre Guedes 	}
593e6100a25SAndre Guedes 
594e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
595e6100a25SAndre Guedes 		hci_set_le_support(hdev);
596d5859e22SJohan Hedberg }
597d5859e22SJohan Hedberg 
598a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
599a9de9248SMarcel Holtmann {
600a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6011143e5a6SMarcel Holtmann 
602a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
6031143e5a6SMarcel Holtmann 
604a9de9248SMarcel Holtmann 	if (rp->status)
605a9de9248SMarcel Holtmann 		return;
6061143e5a6SMarcel Holtmann 
607a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
608e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
609d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
610e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
611d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6121da177e4SLinus Torvalds 
613a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
614a9de9248SMarcel Holtmann 					hdev->manufacturer,
615a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
616d5859e22SJohan Hedberg 
617d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
618d5859e22SJohan Hedberg 		hci_setup(hdev);
619d5859e22SJohan Hedberg }
620d5859e22SJohan Hedberg 
621d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
622d5859e22SJohan Hedberg {
623d5859e22SJohan Hedberg 	u16 link_policy = 0;
624d5859e22SJohan Hedberg 
625d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
626d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
627d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
628d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
629d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
630d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
631d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
632d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
633d5859e22SJohan Hedberg 
634d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
635d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
636d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6371da177e4SLinus Torvalds }
6381da177e4SLinus Torvalds 
639a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
640a9de9248SMarcel Holtmann {
641a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
642a9de9248SMarcel Holtmann 
643a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
644a9de9248SMarcel Holtmann 
645a9de9248SMarcel Holtmann 	if (rp->status)
646d5859e22SJohan Hedberg 		goto done;
647a9de9248SMarcel Holtmann 
648a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
649d5859e22SJohan Hedberg 
650d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
651d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
652d5859e22SJohan Hedberg 
653d5859e22SJohan Hedberg done:
654d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
655a9de9248SMarcel Holtmann }
656a9de9248SMarcel Holtmann 
657a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
658a9de9248SMarcel Holtmann {
659a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
660a9de9248SMarcel Holtmann 
661a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
662a9de9248SMarcel Holtmann 
663a9de9248SMarcel Holtmann 	if (rp->status)
664a9de9248SMarcel Holtmann 		return;
665a9de9248SMarcel Holtmann 
666a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6671da177e4SLinus Torvalds 
6681da177e4SLinus Torvalds 	/* Adjust default settings according to features
6691da177e4SLinus Torvalds 	 * supported by device. */
670a9de9248SMarcel Holtmann 
6711da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6721da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6731da177e4SLinus Torvalds 
6741da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6751da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6761da177e4SLinus Torvalds 
6775b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6781da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6795b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6805b7f9909SMarcel Holtmann 	}
6811da177e4SLinus Torvalds 
6825b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6831da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6845b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6855b7f9909SMarcel Holtmann 	}
6865b7f9909SMarcel Holtmann 
6875b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6885b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6895b7f9909SMarcel Holtmann 
6905b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6915b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6925b7f9909SMarcel Holtmann 
6935b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6945b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6951da177e4SLinus Torvalds 
696efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
697efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
698efc7688bSMarcel Holtmann 
699efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
700efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
701efc7688bSMarcel Holtmann 
702efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
703efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
704efc7688bSMarcel Holtmann 
705a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
706a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
707a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
708a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
709a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7101da177e4SLinus Torvalds }
7111da177e4SLinus Torvalds 
712971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
713971e3a4bSAndre Guedes 							struct sk_buff *skb)
714971e3a4bSAndre Guedes {
715971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
716971e3a4bSAndre Guedes 
717971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
718971e3a4bSAndre Guedes 
719971e3a4bSAndre Guedes 	if (rp->status)
720971e3a4bSAndre Guedes 		return;
721971e3a4bSAndre Guedes 
722b5b32b65SAndre Guedes 	switch (rp->page) {
723b5b32b65SAndre Guedes 	case 0:
724b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
725b5b32b65SAndre Guedes 		break;
726b5b32b65SAndre Guedes 	case 1:
72759e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
728b5b32b65SAndre Guedes 		break;
729b5b32b65SAndre Guedes 	}
730971e3a4bSAndre Guedes 
731971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
732971e3a4bSAndre Guedes }
733971e3a4bSAndre Guedes 
7341e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7351e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7361e89cffbSAndrei Emeltchenko {
7371e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7381e89cffbSAndrei Emeltchenko 
7391e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7401e89cffbSAndrei Emeltchenko 
7411e89cffbSAndrei Emeltchenko 	if (rp->status)
7421e89cffbSAndrei Emeltchenko 		return;
7431e89cffbSAndrei Emeltchenko 
7441e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7451e89cffbSAndrei Emeltchenko 
7461e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7471e89cffbSAndrei Emeltchenko }
7481e89cffbSAndrei Emeltchenko 
749a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
750a9de9248SMarcel Holtmann {
751a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
752a9de9248SMarcel Holtmann 
753a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
754a9de9248SMarcel Holtmann 
755a9de9248SMarcel Holtmann 	if (rp->status)
756a9de9248SMarcel Holtmann 		return;
757a9de9248SMarcel Holtmann 
758a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
759a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
760a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
761a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
762da1f5198SMarcel Holtmann 
763da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
764da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
765da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
766da1f5198SMarcel Holtmann 	}
767da1f5198SMarcel Holtmann 
768da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
769da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7701da177e4SLinus Torvalds 
771a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
772a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
773a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7741da177e4SLinus Torvalds }
7751da177e4SLinus Torvalds 
776a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
777a9de9248SMarcel Holtmann {
778a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7791da177e4SLinus Torvalds 
780a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
781a9de9248SMarcel Holtmann 
782a9de9248SMarcel Holtmann 	if (!rp->status)
783a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
784a9de9248SMarcel Holtmann 
78523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
78623bb5763SJohan Hedberg }
78723bb5763SJohan Hedberg 
788350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
789350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
790350ee4cfSAndrei Emeltchenko {
791350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
792350ee4cfSAndrei Emeltchenko 
793350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
794350ee4cfSAndrei Emeltchenko 
795350ee4cfSAndrei Emeltchenko 	if (rp->status)
796350ee4cfSAndrei Emeltchenko 		return;
797350ee4cfSAndrei Emeltchenko 
798350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
799350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
800350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
801350ee4cfSAndrei Emeltchenko 
802350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
803350ee4cfSAndrei Emeltchenko 
804350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
805350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
806350ee4cfSAndrei Emeltchenko 
807350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
808350ee4cfSAndrei Emeltchenko }
809350ee4cfSAndrei Emeltchenko 
81023bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
81123bb5763SJohan Hedberg {
81223bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
81323bb5763SJohan Hedberg 
81423bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
81523bb5763SJohan Hedberg 
81623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8171da177e4SLinus Torvalds }
8181da177e4SLinus Torvalds 
819928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
820928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
821928abaa7SAndrei Emeltchenko {
822928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
823928abaa7SAndrei Emeltchenko 
824928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
825928abaa7SAndrei Emeltchenko 
826928abaa7SAndrei Emeltchenko 	if (rp->status)
827928abaa7SAndrei Emeltchenko 		return;
828928abaa7SAndrei Emeltchenko 
829928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
830928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
831928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
832928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
833928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
834928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
835928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
836928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
837928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
838928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
839928abaa7SAndrei Emeltchenko 
840928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
841928abaa7SAndrei Emeltchenko }
842928abaa7SAndrei Emeltchenko 
843b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
844b0916ea0SJohan Hedberg 							struct sk_buff *skb)
845b0916ea0SJohan Hedberg {
846b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
847b0916ea0SJohan Hedberg 
848b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
849b0916ea0SJohan Hedberg 
850b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
851b0916ea0SJohan Hedberg }
852b0916ea0SJohan Hedberg 
853d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
854d5859e22SJohan Hedberg {
855d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
856d5859e22SJohan Hedberg 
857d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
858d5859e22SJohan Hedberg 
859d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
860d5859e22SJohan Hedberg }
861d5859e22SJohan Hedberg 
862d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
863d5859e22SJohan Hedberg 							struct sk_buff *skb)
864d5859e22SJohan Hedberg {
865d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
866d5859e22SJohan Hedberg 
867d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
868d5859e22SJohan Hedberg 
869d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
870d5859e22SJohan Hedberg }
871d5859e22SJohan Hedberg 
872d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
873d5859e22SJohan Hedberg 							struct sk_buff *skb)
874d5859e22SJohan Hedberg {
875d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
876d5859e22SJohan Hedberg 
877d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
878d5859e22SJohan Hedberg 
879d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
880d5859e22SJohan Hedberg }
881d5859e22SJohan Hedberg 
882d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
883d5859e22SJohan Hedberg {
884d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
885d5859e22SJohan Hedberg 
886d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
887d5859e22SJohan Hedberg 
888d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
889d5859e22SJohan Hedberg }
890d5859e22SJohan Hedberg 
891980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
892980e1a53SJohan Hedberg {
893980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
894980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
895980e1a53SJohan Hedberg 	struct hci_conn *conn;
896980e1a53SJohan Hedberg 
897980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
898980e1a53SJohan Hedberg 
89956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
90056e5cb86SJohan Hedberg 
901a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
902744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
903980e1a53SJohan Hedberg 
904980e1a53SJohan Hedberg 	if (rp->status != 0)
90556e5cb86SJohan Hedberg 		goto unlock;
906980e1a53SJohan Hedberg 
907980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
908980e1a53SJohan Hedberg 	if (!cp)
90956e5cb86SJohan Hedberg 		goto unlock;
910980e1a53SJohan Hedberg 
911980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
912980e1a53SJohan Hedberg 	if (conn)
913980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
91456e5cb86SJohan Hedberg 
91556e5cb86SJohan Hedberg unlock:
91656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
917980e1a53SJohan Hedberg }
918980e1a53SJohan Hedberg 
919980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
920980e1a53SJohan Hedberg {
921980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
922980e1a53SJohan Hedberg 
923980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
924980e1a53SJohan Hedberg 
92556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92656e5cb86SJohan Hedberg 
927a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
928744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
929980e1a53SJohan Hedberg 								rp->status);
93056e5cb86SJohan Hedberg 
93156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
932980e1a53SJohan Hedberg }
93356e5cb86SJohan Hedberg 
9346ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9356ed58ec5SVille Tervo 				       struct sk_buff *skb)
9366ed58ec5SVille Tervo {
9376ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9386ed58ec5SVille Tervo 
9396ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9406ed58ec5SVille Tervo 
9416ed58ec5SVille Tervo 	if (rp->status)
9426ed58ec5SVille Tervo 		return;
9436ed58ec5SVille Tervo 
9446ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9456ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9466ed58ec5SVille Tervo 
9476ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9486ed58ec5SVille Tervo 
9496ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9506ed58ec5SVille Tervo 
9516ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9526ed58ec5SVille Tervo }
953980e1a53SJohan Hedberg 
954a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
955a5c29683SJohan Hedberg {
956a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
957a5c29683SJohan Hedberg 
958a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
959a5c29683SJohan Hedberg 
96056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96156e5cb86SJohan Hedberg 
962a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
963744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
964a5c29683SJohan Hedberg 								rp->status);
96556e5cb86SJohan Hedberg 
96656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
967a5c29683SJohan Hedberg }
968a5c29683SJohan Hedberg 
969a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
970a5c29683SJohan Hedberg 							struct sk_buff *skb)
971a5c29683SJohan Hedberg {
972a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
973a5c29683SJohan Hedberg 
974a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
975a5c29683SJohan Hedberg 
97656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
97756e5cb86SJohan Hedberg 
978a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
979744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
980a5c29683SJohan Hedberg 								rp->status);
98156e5cb86SJohan Hedberg 
98256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
983a5c29683SJohan Hedberg }
984a5c29683SJohan Hedberg 
9851143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9861143d458SBrian Gix {
9871143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9881143d458SBrian Gix 
9891143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9901143d458SBrian Gix 
9911143d458SBrian Gix 	hci_dev_lock(hdev);
9921143d458SBrian Gix 
993a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9941143d458SBrian Gix 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
9951143d458SBrian Gix 								rp->status);
9961143d458SBrian Gix 
9971143d458SBrian Gix 	hci_dev_unlock(hdev);
9981143d458SBrian Gix }
9991143d458SBrian Gix 
10001143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10011143d458SBrian Gix 							struct sk_buff *skb)
10021143d458SBrian Gix {
10031143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10041143d458SBrian Gix 
10051143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10061143d458SBrian Gix 
10071143d458SBrian Gix 	hci_dev_lock(hdev);
10081143d458SBrian Gix 
1009a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10101143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
10111143d458SBrian Gix 								rp->status);
10121143d458SBrian Gix 
10131143d458SBrian Gix 	hci_dev_unlock(hdev);
10141143d458SBrian Gix }
10151143d458SBrian Gix 
1016c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1017c35938b2SSzymon Janc 							struct sk_buff *skb)
1018c35938b2SSzymon Janc {
1019c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1020c35938b2SSzymon Janc 
1021c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1022c35938b2SSzymon Janc 
102356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1024744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1025c35938b2SSzymon Janc 						rp->randomizer, rp->status);
102656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1027c35938b2SSzymon Janc }
1028c35938b2SSzymon Janc 
102907f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
103007f7fa5dSAndre Guedes {
103107f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
103207f7fa5dSAndre Guedes 
103307f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
103407f7fa5dSAndre Guedes }
103507f7fa5dSAndre Guedes 
1036eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1037eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1038eb9d91f5SAndre Guedes {
1039eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1040eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1041eb9d91f5SAndre Guedes 
1042eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1043eb9d91f5SAndre Guedes 
1044eb9d91f5SAndre Guedes 	if (status)
1045eb9d91f5SAndre Guedes 		return;
1046eb9d91f5SAndre Guedes 
1047eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1048eb9d91f5SAndre Guedes 	if (!cp)
1049eb9d91f5SAndre Guedes 		return;
1050eb9d91f5SAndre Guedes 
105168a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
105268a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
1053d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1054d23264a8SAndre Guedes 
1055db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1056a8f13c8cSAndre Guedes 
1057a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1058eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1059c599008fSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_LE_SCAN);
1060a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
106168a8aea4SAndrei Emeltchenko 		break;
106268a8aea4SAndrei Emeltchenko 
106368a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1064d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1065d23264a8SAndre Guedes 
1066c599008fSAndre Guedes 		hci_dev_lock(hdev);
1067c599008fSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1068c599008fSAndre Guedes 		hci_dev_unlock(hdev);
1069c599008fSAndre Guedes 
1070d084329eSAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
107168a8aea4SAndrei Emeltchenko 		break;
107268a8aea4SAndrei Emeltchenko 
107368a8aea4SAndrei Emeltchenko 	default:
107468a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
107568a8aea4SAndrei Emeltchenko 		break;
107635815085SAndre Guedes 	}
1077eb9d91f5SAndre Guedes }
1078eb9d91f5SAndre Guedes 
1079a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1080a7a595f6SVinicius Costa Gomes {
1081a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1082a7a595f6SVinicius Costa Gomes 
1083a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1084a7a595f6SVinicius Costa Gomes 
1085a7a595f6SVinicius Costa Gomes 	if (rp->status)
1086a7a595f6SVinicius Costa Gomes 		return;
1087a7a595f6SVinicius Costa Gomes 
1088a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1089a7a595f6SVinicius Costa Gomes }
1090a7a595f6SVinicius Costa Gomes 
1091a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1092a7a595f6SVinicius Costa Gomes {
1093a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1094a7a595f6SVinicius Costa Gomes 
1095a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1096a7a595f6SVinicius Costa Gomes 
1097a7a595f6SVinicius Costa Gomes 	if (rp->status)
1098a7a595f6SVinicius Costa Gomes 		return;
1099a7a595f6SVinicius Costa Gomes 
1100a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1101a7a595f6SVinicius Costa Gomes }
1102a7a595f6SVinicius Costa Gomes 
1103f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1104f9b49306SAndre Guedes 							struct sk_buff *skb)
1105f9b49306SAndre Guedes {
1106f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1107f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1108f9b49306SAndre Guedes 
1109f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1110f9b49306SAndre Guedes 
1111f9b49306SAndre Guedes 	if (status)
1112f9b49306SAndre Guedes 		return;
1113f9b49306SAndre Guedes 
1114f9b49306SAndre Guedes 	cp.page = 0x01;
1115f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1116f9b49306SAndre Guedes }
1117f9b49306SAndre Guedes 
1118a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1119a9de9248SMarcel Holtmann {
1120a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1121a9de9248SMarcel Holtmann 
1122a9de9248SMarcel Holtmann 	if (status) {
112323bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1124a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
112556e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1126a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11277a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
112856e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1129314b2381SJohan Hedberg 		return;
1130314b2381SJohan Hedberg 	}
1131314b2381SJohan Hedberg 
113289352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
113389352e7dSAndre Guedes 
113456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
113530dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_INQUIRY);
113656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1137a9de9248SMarcel Holtmann }
1138a9de9248SMarcel Holtmann 
11391da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11401da177e4SLinus Torvalds {
1141a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11421da177e4SLinus Torvalds 	struct hci_conn *conn;
11431da177e4SLinus Torvalds 
1144a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1145a9de9248SMarcel Holtmann 
1146a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11471da177e4SLinus Torvalds 	if (!cp)
11481da177e4SLinus Torvalds 		return;
11491da177e4SLinus Torvalds 
11501da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11511da177e4SLinus Torvalds 
11521da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11531da177e4SLinus Torvalds 
1154a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11551da177e4SLinus Torvalds 
11561da177e4SLinus Torvalds 	if (status) {
11571da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11584c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11591da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11601da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11611da177e4SLinus Torvalds 				hci_conn_del(conn);
11624c67bc74SMarcel Holtmann 			} else
11634c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11641da177e4SLinus Torvalds 		}
11651da177e4SLinus Torvalds 	} else {
11661da177e4SLinus Torvalds 		if (!conn) {
11671da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11681da177e4SLinus Torvalds 			if (conn) {
1169a0c808b3SJohan Hedberg 				conn->out = true;
11701da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11711da177e4SLinus Torvalds 			} else
1172893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11731da177e4SLinus Torvalds 		}
11741da177e4SLinus Torvalds 	}
11751da177e4SLinus Torvalds 
11761da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11771da177e4SLinus Torvalds }
11781da177e4SLinus Torvalds 
1179a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11801da177e4SLinus Torvalds {
1181a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11821da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11831da177e4SLinus Torvalds 	__u16 handle;
11841da177e4SLinus Torvalds 
1185b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1186b6a0dc82SMarcel Holtmann 
1187a9de9248SMarcel Holtmann 	if (!status)
1188a9de9248SMarcel Holtmann 		return;
1189a9de9248SMarcel Holtmann 
1190a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11911da177e4SLinus Torvalds 	if (!cp)
1192a9de9248SMarcel Holtmann 		return;
11931da177e4SLinus Torvalds 
11941da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11951da177e4SLinus Torvalds 
1196a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
11971da177e4SLinus Torvalds 
11981da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11991da177e4SLinus Torvalds 
12001da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12015a08ecceSAndrei Emeltchenko 	if (acl) {
12025a08ecceSAndrei Emeltchenko 		sco = acl->link;
12035a08ecceSAndrei Emeltchenko 		if (sco) {
12041da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12051da177e4SLinus Torvalds 
12061da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12071da177e4SLinus Torvalds 			hci_conn_del(sco);
12081da177e4SLinus Torvalds 		}
12095a08ecceSAndrei Emeltchenko 	}
12101da177e4SLinus Torvalds 
12111da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12121da177e4SLinus Torvalds }
12131da177e4SLinus Torvalds 
1214f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1215f8558555SMarcel Holtmann {
1216f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1217f8558555SMarcel Holtmann 	struct hci_conn *conn;
1218f8558555SMarcel Holtmann 
1219f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1220f8558555SMarcel Holtmann 
1221f8558555SMarcel Holtmann 	if (!status)
1222f8558555SMarcel Holtmann 		return;
1223f8558555SMarcel Holtmann 
1224f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1225f8558555SMarcel Holtmann 	if (!cp)
1226f8558555SMarcel Holtmann 		return;
1227f8558555SMarcel Holtmann 
1228f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1229f8558555SMarcel Holtmann 
1230f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1231f8558555SMarcel Holtmann 	if (conn) {
1232f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1233f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1234f8558555SMarcel Holtmann 			hci_conn_put(conn);
1235f8558555SMarcel Holtmann 		}
1236f8558555SMarcel Holtmann 	}
1237f8558555SMarcel Holtmann 
1238f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1239f8558555SMarcel Holtmann }
1240f8558555SMarcel Holtmann 
1241f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1242f8558555SMarcel Holtmann {
1243f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1244f8558555SMarcel Holtmann 	struct hci_conn *conn;
1245f8558555SMarcel Holtmann 
1246f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1247f8558555SMarcel Holtmann 
1248f8558555SMarcel Holtmann 	if (!status)
1249f8558555SMarcel Holtmann 		return;
1250f8558555SMarcel Holtmann 
1251f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1252f8558555SMarcel Holtmann 	if (!cp)
1253f8558555SMarcel Holtmann 		return;
1254f8558555SMarcel Holtmann 
1255f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1256f8558555SMarcel Holtmann 
1257f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1258f8558555SMarcel Holtmann 	if (conn) {
1259f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1260f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1261f8558555SMarcel Holtmann 			hci_conn_put(conn);
1262f8558555SMarcel Holtmann 		}
1263f8558555SMarcel Holtmann 	}
1264f8558555SMarcel Holtmann 
1265f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1266f8558555SMarcel Holtmann }
1267f8558555SMarcel Holtmann 
1268127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1269392599b9SJohan Hedberg 							struct hci_conn *conn)
1270392599b9SJohan Hedberg {
1271392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1272392599b9SJohan Hedberg 		return 0;
1273392599b9SJohan Hedberg 
1274765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1275392599b9SJohan Hedberg 		return 0;
1276392599b9SJohan Hedberg 
1277392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1278e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1279aa64a8b5SJohan Hedberg 	if (!hci_conn_ssp_enabled(conn) &&
1280e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1281e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1282392599b9SJohan Hedberg 		return 0;
1283392599b9SJohan Hedberg 
1284392599b9SJohan Hedberg 	return 1;
1285392599b9SJohan Hedberg }
1286392599b9SJohan Hedberg 
128730dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
128830dc78e1SJohan Hedberg {
128930dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
129030dc78e1SJohan Hedberg 
129130dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
129230dc78e1SJohan Hedberg 
129330dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
129430dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
129530dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
129630dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
129730dc78e1SJohan Hedberg 
129830dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
129930dc78e1SJohan Hedberg }
130030dc78e1SJohan Hedberg 
1301b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
130230dc78e1SJohan Hedberg {
130330dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
130430dc78e1SJohan Hedberg 	struct inquiry_entry *e;
130530dc78e1SJohan Hedberg 
1306b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1307b644ba33SJohan Hedberg 		return false;
1308b644ba33SJohan Hedberg 
1309b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1310b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1311b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1312b644ba33SJohan Hedberg 		return true;
1313b644ba33SJohan Hedberg 	}
1314b644ba33SJohan Hedberg 
1315b644ba33SJohan Hedberg 	return false;
1316b644ba33SJohan Hedberg }
1317b644ba33SJohan Hedberg 
1318b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1319b644ba33SJohan Hedberg 					bdaddr_t *bdaddr, u8 *name, u8 name_len)
1320b644ba33SJohan Hedberg {
1321b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1322b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1323b644ba33SJohan Hedberg 
1324b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
1325b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00,
1326b644ba33SJohan Hedberg 					name, name_len, conn->dev_class);
1327b644ba33SJohan Hedberg 
1328b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1329b644ba33SJohan Hedberg 		return;
1330b644ba33SJohan Hedberg 
133130dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
133230dc78e1SJohan Hedberg 		goto discov_complete;
133330dc78e1SJohan Hedberg 
133430dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
133530dc78e1SJohan Hedberg 		return;
133630dc78e1SJohan Hedberg 
133730dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
133830dc78e1SJohan Hedberg 	if (e) {
133930dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
134030dc78e1SJohan Hedberg 		list_del(&e->list);
1341b644ba33SJohan Hedberg 		if (name)
1342b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1343b644ba33SJohan Hedberg 					e->data.rssi, name, name_len);
134430dc78e1SJohan Hedberg 	}
134530dc78e1SJohan Hedberg 
1346b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
134730dc78e1SJohan Hedberg 		return;
134830dc78e1SJohan Hedberg 
134930dc78e1SJohan Hedberg discov_complete:
135030dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
135130dc78e1SJohan Hedberg }
135230dc78e1SJohan Hedberg 
1353a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13541da177e4SLinus Torvalds {
1355127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1356127178d2SJohan Hedberg 	struct hci_conn *conn;
1357127178d2SJohan Hedberg 
1358a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1359127178d2SJohan Hedberg 
1360127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1361127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1362127178d2SJohan Hedberg 	if (!status)
1363127178d2SJohan Hedberg 		return;
1364127178d2SJohan Hedberg 
1365127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1366127178d2SJohan Hedberg 	if (!cp)
1367127178d2SJohan Hedberg 		return;
1368127178d2SJohan Hedberg 
1369127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1370127178d2SJohan Hedberg 
1371127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1372b644ba33SJohan Hedberg 
1373b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1374b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1375b644ba33SJohan Hedberg 
137679c6c70cSJohan Hedberg 	if (!conn)
137779c6c70cSJohan Hedberg 		goto unlock;
137879c6c70cSJohan Hedberg 
137979c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
138079c6c70cSJohan Hedberg 		goto unlock;
138179c6c70cSJohan Hedberg 
138251a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1383127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1384127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1385127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1386127178d2SJohan Hedberg 	}
1387127178d2SJohan Hedberg 
138879c6c70cSJohan Hedberg unlock:
1389127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1390a9de9248SMarcel Holtmann }
13911da177e4SLinus Torvalds 
1392769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1393769be974SMarcel Holtmann {
1394769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1395769be974SMarcel Holtmann 	struct hci_conn *conn;
1396769be974SMarcel Holtmann 
1397769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1398769be974SMarcel Holtmann 
1399769be974SMarcel Holtmann 	if (!status)
1400769be974SMarcel Holtmann 		return;
1401769be974SMarcel Holtmann 
1402769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1403769be974SMarcel Holtmann 	if (!cp)
1404769be974SMarcel Holtmann 		return;
1405769be974SMarcel Holtmann 
1406769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1407769be974SMarcel Holtmann 
1408769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1409769be974SMarcel Holtmann 	if (conn) {
1410769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1411769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1412769be974SMarcel Holtmann 			hci_conn_put(conn);
1413769be974SMarcel Holtmann 		}
1414769be974SMarcel Holtmann 	}
1415769be974SMarcel Holtmann 
1416769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1417769be974SMarcel Holtmann }
1418769be974SMarcel Holtmann 
1419769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1420769be974SMarcel Holtmann {
1421769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1422769be974SMarcel Holtmann 	struct hci_conn *conn;
1423769be974SMarcel Holtmann 
1424769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1425769be974SMarcel Holtmann 
1426769be974SMarcel Holtmann 	if (!status)
1427769be974SMarcel Holtmann 		return;
1428769be974SMarcel Holtmann 
1429769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1430769be974SMarcel Holtmann 	if (!cp)
1431769be974SMarcel Holtmann 		return;
1432769be974SMarcel Holtmann 
1433769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1434769be974SMarcel Holtmann 
1435769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1436769be974SMarcel Holtmann 	if (conn) {
1437769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1438769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1439769be974SMarcel Holtmann 			hci_conn_put(conn);
1440769be974SMarcel Holtmann 		}
1441769be974SMarcel Holtmann 	}
1442769be974SMarcel Holtmann 
1443769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1444769be974SMarcel Holtmann }
1445769be974SMarcel Holtmann 
1446a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1447a9de9248SMarcel Holtmann {
1448b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1449b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1450b6a0dc82SMarcel Holtmann 	__u16 handle;
1451b6a0dc82SMarcel Holtmann 
1452a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1453b6a0dc82SMarcel Holtmann 
1454b6a0dc82SMarcel Holtmann 	if (!status)
1455b6a0dc82SMarcel Holtmann 		return;
1456b6a0dc82SMarcel Holtmann 
1457b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1458b6a0dc82SMarcel Holtmann 	if (!cp)
1459b6a0dc82SMarcel Holtmann 		return;
1460b6a0dc82SMarcel Holtmann 
1461b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1462b6a0dc82SMarcel Holtmann 
1463b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1464b6a0dc82SMarcel Holtmann 
1465b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1466b6a0dc82SMarcel Holtmann 
1467b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14685a08ecceSAndrei Emeltchenko 	if (acl) {
14695a08ecceSAndrei Emeltchenko 		sco = acl->link;
14705a08ecceSAndrei Emeltchenko 		if (sco) {
1471b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1472b6a0dc82SMarcel Holtmann 
1473b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1474b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1475b6a0dc82SMarcel Holtmann 		}
14765a08ecceSAndrei Emeltchenko 	}
1477b6a0dc82SMarcel Holtmann 
1478b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1479a9de9248SMarcel Holtmann }
1480a9de9248SMarcel Holtmann 
1481a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1482a9de9248SMarcel Holtmann {
1483a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
148404837f64SMarcel Holtmann 	struct hci_conn *conn;
148504837f64SMarcel Holtmann 
1486a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1487a9de9248SMarcel Holtmann 
1488a9de9248SMarcel Holtmann 	if (!status)
1489a9de9248SMarcel Holtmann 		return;
1490a9de9248SMarcel Holtmann 
1491a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
149204837f64SMarcel Holtmann 	if (!cp)
1493a9de9248SMarcel Holtmann 		return;
149404837f64SMarcel Holtmann 
149504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
149604837f64SMarcel Holtmann 
149704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1498e73439d8SMarcel Holtmann 	if (conn) {
149951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
150004837f64SMarcel Holtmann 
150151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1502e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1503e73439d8SMarcel Holtmann 	}
1504e73439d8SMarcel Holtmann 
150504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
150604837f64SMarcel Holtmann }
150704837f64SMarcel Holtmann 
1508a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1509a9de9248SMarcel Holtmann {
1510a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
151104837f64SMarcel Holtmann 	struct hci_conn *conn;
151204837f64SMarcel Holtmann 
1513a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1514a9de9248SMarcel Holtmann 
1515a9de9248SMarcel Holtmann 	if (!status)
1516a9de9248SMarcel Holtmann 		return;
1517a9de9248SMarcel Holtmann 
1518a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
151904837f64SMarcel Holtmann 	if (!cp)
1520a9de9248SMarcel Holtmann 		return;
152104837f64SMarcel Holtmann 
152204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
152304837f64SMarcel Holtmann 
152404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1525e73439d8SMarcel Holtmann 	if (conn) {
152651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
152704837f64SMarcel Holtmann 
152851a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1529e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1530e73439d8SMarcel Holtmann 	}
1531e73439d8SMarcel Holtmann 
153204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
153304837f64SMarcel Holtmann }
153404837f64SMarcel Holtmann 
1535fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1536fcd89c09SVille Tervo {
1537fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1538fcd89c09SVille Tervo 	struct hci_conn *conn;
1539fcd89c09SVille Tervo 
1540fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1541fcd89c09SVille Tervo 
1542fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1543fcd89c09SVille Tervo 	if (!cp)
1544fcd89c09SVille Tervo 		return;
1545fcd89c09SVille Tervo 
1546fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1547fcd89c09SVille Tervo 
1548fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1549fcd89c09SVille Tervo 
1550fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1551fcd89c09SVille Tervo 		conn);
1552fcd89c09SVille Tervo 
1553fcd89c09SVille Tervo 	if (status) {
1554fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1555fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1556fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1557fcd89c09SVille Tervo 			hci_conn_del(conn);
1558fcd89c09SVille Tervo 		}
1559fcd89c09SVille Tervo 	} else {
1560fcd89c09SVille Tervo 		if (!conn) {
1561fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
156229b7988aSAndre Guedes 			if (conn) {
156329b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1564a0c808b3SJohan Hedberg 				conn->out = true;
156529b7988aSAndre Guedes 			} else {
1566fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1567fcd89c09SVille Tervo 			}
1568fcd89c09SVille Tervo 		}
156929b7988aSAndre Guedes 	}
1570fcd89c09SVille Tervo 
1571fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1572fcd89c09SVille Tervo }
1573fcd89c09SVille Tervo 
1574a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1575a7a595f6SVinicius Costa Gomes {
1576a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1577a7a595f6SVinicius Costa Gomes }
1578a7a595f6SVinicius Costa Gomes 
15791da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15801da177e4SLinus Torvalds {
15811da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
158230dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
158330dc78e1SJohan Hedberg 	struct inquiry_entry *e;
15841da177e4SLinus Torvalds 
15851da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
15861da177e4SLinus Torvalds 
158723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
15886bd57416SMarcel Holtmann 
1589a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
159089352e7dSAndre Guedes 
159189352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
159289352e7dSAndre Guedes 		return;
159389352e7dSAndre Guedes 
1594a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
159530dc78e1SJohan Hedberg 		return;
159630dc78e1SJohan Hedberg 
159756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
159830dc78e1SJohan Hedberg 
159930dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_INQUIRY)
160030dc78e1SJohan Hedberg 		goto unlock;
160130dc78e1SJohan Hedberg 
160230dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1603ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
160430dc78e1SJohan Hedberg 		goto unlock;
160530dc78e1SJohan Hedberg 	}
160630dc78e1SJohan Hedberg 
160730dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
160830dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
160930dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
161030dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
161130dc78e1SJohan Hedberg 	} else {
161230dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
161330dc78e1SJohan Hedberg 	}
161430dc78e1SJohan Hedberg 
161530dc78e1SJohan Hedberg unlock:
161656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16171da177e4SLinus Torvalds }
16181da177e4SLinus Torvalds 
16191da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16201da177e4SLinus Torvalds {
162145bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1622a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16231da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16241da177e4SLinus Torvalds 
16251da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16261da177e4SLinus Torvalds 
162745bb4bf0SMarcel Holtmann 	if (!num_rsp)
162845bb4bf0SMarcel Holtmann 		return;
162945bb4bf0SMarcel Holtmann 
16301da177e4SLinus Torvalds 	hci_dev_lock(hdev);
163145bb4bf0SMarcel Holtmann 
1632e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
16333175405bSJohan Hedberg 		bool name_known;
16343175405bSJohan Hedberg 
16351da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16361da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16371da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16381da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16391da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16401da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16411da177e4SLinus Torvalds 		data.rssi		= 0x00;
164241a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16433175405bSJohan Hedberg 
16443175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false);
164548264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
16467d262f86SAndre Guedes 					info->dev_class, 0, !name_known,
16477d262f86SAndre Guedes 					NULL, 0);
16481da177e4SLinus Torvalds 	}
164945bb4bf0SMarcel Holtmann 
16501da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16511da177e4SLinus Torvalds }
16521da177e4SLinus Torvalds 
1653a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16541da177e4SLinus Torvalds {
1655a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1656a9de9248SMarcel Holtmann 	struct hci_conn *conn;
16571da177e4SLinus Torvalds 
1658a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
165945bb4bf0SMarcel Holtmann 
16601da177e4SLinus Torvalds 	hci_dev_lock(hdev);
166145bb4bf0SMarcel Holtmann 
1662a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16639499237aSMarcel Holtmann 	if (!conn) {
16649499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16659499237aSMarcel Holtmann 			goto unlock;
16669499237aSMarcel Holtmann 
16679499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1668a9de9248SMarcel Holtmann 		if (!conn)
1669a9de9248SMarcel Holtmann 			goto unlock;
167045bb4bf0SMarcel Holtmann 
16719499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16729499237aSMarcel Holtmann 	}
16739499237aSMarcel Holtmann 
1674a9de9248SMarcel Holtmann 	if (!ev->status) {
1675a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1676769be974SMarcel Holtmann 
1677769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1678769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1679769be974SMarcel Holtmann 			hci_conn_hold(conn);
1680052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1681769be974SMarcel Holtmann 		} else
1682a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1683a9de9248SMarcel Holtmann 
16849eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
16857d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
16867d0db0a3SMarcel Holtmann 
1687a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1688a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1689a9de9248SMarcel Holtmann 
1690a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1691a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1692a9de9248SMarcel Holtmann 
1693a9de9248SMarcel Holtmann 		/* Get remote features */
1694a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1695a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1696a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1697769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1698769be974SMarcel Holtmann 							sizeof(cp), &cp);
169945bb4bf0SMarcel Holtmann 		}
1700a9de9248SMarcel Holtmann 
1701a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1702d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1703a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1704a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1705a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1706a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1707a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1708a9de9248SMarcel Holtmann 		}
170917d5c04cSJohan Hedberg 	} else {
1710a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
171117d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1712744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
171348264f06SJohan Hedberg 						conn->dst_type, ev->status);
171417d5c04cSJohan Hedberg 	}
171545bb4bf0SMarcel Holtmann 
1716e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1717e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
171845bb4bf0SMarcel Holtmann 
1719769be974SMarcel Holtmann 	if (ev->status) {
1720a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1721a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1722c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1723c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1724a9de9248SMarcel Holtmann 
1725a9de9248SMarcel Holtmann unlock:
17261da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1727a9de9248SMarcel Holtmann 
1728a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
17291da177e4SLinus Torvalds }
17301da177e4SLinus Torvalds 
17311da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17321da177e4SLinus Torvalds {
1733a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17341da177e4SLinus Torvalds 	int mask = hdev->link_mode;
17351da177e4SLinus Torvalds 
1736a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
17371da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
17381da177e4SLinus Torvalds 
17391da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
17401da177e4SLinus Torvalds 
1741138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1742138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
17431da177e4SLinus Torvalds 		/* Connection accepted */
1744c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17451da177e4SLinus Torvalds 		struct hci_conn *conn;
17461da177e4SLinus Torvalds 
17471da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1748b6a0dc82SMarcel Holtmann 
1749cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1750cc11b9c1SAndrei Emeltchenko 		if (ie)
1751c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1752c7bdd502SMarcel Holtmann 
17531da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17541da177e4SLinus Torvalds 		if (!conn) {
1755cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1756cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1757893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17581da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17591da177e4SLinus Torvalds 				return;
17601da177e4SLinus Torvalds 			}
17611da177e4SLinus Torvalds 		}
1762b6a0dc82SMarcel Holtmann 
17631da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
17641da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1765b6a0dc82SMarcel Holtmann 
17661da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17671da177e4SLinus Torvalds 
1768b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1769b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1770b6a0dc82SMarcel Holtmann 
17711da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17721da177e4SLinus Torvalds 
17731da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17741da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17751da177e4SLinus Torvalds 			else
17761da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17771da177e4SLinus Torvalds 
1778b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1779b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1780b6a0dc82SMarcel Holtmann 		} else {
1781b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1782b6a0dc82SMarcel Holtmann 
1783b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1784a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1785b6a0dc82SMarcel Holtmann 
1786b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1787b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1788b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1789b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1790b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1791b6a0dc82SMarcel Holtmann 
1792b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1793b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1794b6a0dc82SMarcel Holtmann 		}
17951da177e4SLinus Torvalds 	} else {
17961da177e4SLinus Torvalds 		/* Connection rejected */
17971da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
17981da177e4SLinus Torvalds 
17991da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18009f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1801a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18021da177e4SLinus Torvalds 	}
18031da177e4SLinus Torvalds }
18041da177e4SLinus Torvalds 
18051da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18061da177e4SLinus Torvalds {
1807a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
180804837f64SMarcel Holtmann 	struct hci_conn *conn;
18091da177e4SLinus Torvalds 
18101da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
18111da177e4SLinus Torvalds 
18121da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18131da177e4SLinus Torvalds 
181404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1815f7520543SJohan Hedberg 	if (!conn)
1816f7520543SJohan Hedberg 		goto unlock;
1817f7520543SJohan Hedberg 
181837d9ef76SJohan Hedberg 	if (ev->status == 0)
18191da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18207d0db0a3SMarcel Holtmann 
1821b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1822b644ba33SJohan Hedberg 			(conn->type == ACL_LINK || conn->type == LE_LINK)) {
182337d9ef76SJohan Hedberg 		if (ev->status != 0)
182437d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
182537d9ef76SJohan Hedberg 		else
1826afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
182748264f06SJohan Hedberg 							conn->dst_type);
182837d9ef76SJohan Hedberg 	}
1829f7520543SJohan Hedberg 
183037d9ef76SJohan Hedberg 	if (ev->status == 0) {
18312950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
18321da177e4SLinus Torvalds 		hci_conn_del(conn);
183337d9ef76SJohan Hedberg 	}
18341da177e4SLinus Torvalds 
1835f7520543SJohan Hedberg unlock:
18361da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18371da177e4SLinus Torvalds }
18381da177e4SLinus Torvalds 
1839a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1840a9de9248SMarcel Holtmann {
1841a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1842a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1843a9de9248SMarcel Holtmann 
1844a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1845a9de9248SMarcel Holtmann 
1846a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1847a9de9248SMarcel Holtmann 
1848a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1849d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1850d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1851d7556e20SWaldemar Rymarkiewicz 
1852765c2a96SJohan Hedberg 	if (!ev->status) {
1853aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
185451a8efd7SJohan Hedberg 				test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1855d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
185619f8def0SWaldemar Rymarkiewicz 		} else {
1857a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1858765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
185919f8def0SWaldemar Rymarkiewicz 		}
18602a611692SJohan Hedberg 	} else {
1861744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
18622a611692SJohan Hedberg 	}
1863a9de9248SMarcel Holtmann 
186451a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
186551a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1866a9de9248SMarcel Holtmann 
1867f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1868aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1869f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1870f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1871f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1872d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1873d7556e20SWaldemar Rymarkiewicz 									&cp);
1874f8558555SMarcel Holtmann 		} else {
1875f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1876f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1877f8558555SMarcel Holtmann 			hci_conn_put(conn);
1878f8558555SMarcel Holtmann 		}
1879052b30b0SMarcel Holtmann 	} else {
1880a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1881a9de9248SMarcel Holtmann 
1882052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1883052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1884052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1885052b30b0SMarcel Holtmann 	}
1886052b30b0SMarcel Holtmann 
188751a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1888a9de9248SMarcel Holtmann 		if (!ev->status) {
1889a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1890f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1891f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1892d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1893d7556e20SWaldemar Rymarkiewicz 									&cp);
1894a9de9248SMarcel Holtmann 		} else {
189551a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1896a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1897a9de9248SMarcel Holtmann 		}
1898a9de9248SMarcel Holtmann 	}
1899a9de9248SMarcel Holtmann 
1900d7556e20SWaldemar Rymarkiewicz unlock:
1901a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1902a9de9248SMarcel Holtmann }
1903a9de9248SMarcel Holtmann 
1904a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1905a9de9248SMarcel Holtmann {
1906127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1907127178d2SJohan Hedberg 	struct hci_conn *conn;
1908127178d2SJohan Hedberg 
1909a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1910a9de9248SMarcel Holtmann 
1911a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1912127178d2SJohan Hedberg 
1913127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1914127178d2SJohan Hedberg 
1915127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1916b644ba33SJohan Hedberg 
1917b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1918b644ba33SJohan Hedberg 		goto check_auth;
1919b644ba33SJohan Hedberg 
1920b644ba33SJohan Hedberg 	if (ev->status == 0)
1921b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1922b644ba33SJohan Hedberg 					strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1923b644ba33SJohan Hedberg 	else
1924b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1925b644ba33SJohan Hedberg 
1926b644ba33SJohan Hedberg check_auth:
192779c6c70cSJohan Hedberg 	if (!conn)
192879c6c70cSJohan Hedberg 		goto unlock;
192979c6c70cSJohan Hedberg 
193079c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
193179c6c70cSJohan Hedberg 		goto unlock;
193279c6c70cSJohan Hedberg 
193351a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1934127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1935127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1936127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1937127178d2SJohan Hedberg 	}
1938127178d2SJohan Hedberg 
193979c6c70cSJohan Hedberg unlock:
1940127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1941a9de9248SMarcel Holtmann }
1942a9de9248SMarcel Holtmann 
1943a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1944a9de9248SMarcel Holtmann {
1945a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1946a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1947a9de9248SMarcel Holtmann 
1948a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1949a9de9248SMarcel Holtmann 
1950a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1951a9de9248SMarcel Holtmann 
1952a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1953a9de9248SMarcel Holtmann 	if (conn) {
1954a9de9248SMarcel Holtmann 		if (!ev->status) {
1955ae293196SMarcel Holtmann 			if (ev->encrypt) {
1956ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1957ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1958a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1959da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1960ae293196SMarcel Holtmann 			} else
1961a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1962a9de9248SMarcel Holtmann 		}
1963a9de9248SMarcel Holtmann 
196451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1965a9de9248SMarcel Holtmann 
1966f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1967f8558555SMarcel Holtmann 			if (!ev->status)
1968f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1969f8558555SMarcel Holtmann 
1970f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1971f8558555SMarcel Holtmann 			hci_conn_put(conn);
1972f8558555SMarcel Holtmann 		} else
1973a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1974a9de9248SMarcel Holtmann 	}
1975a9de9248SMarcel Holtmann 
1976a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1977a9de9248SMarcel Holtmann }
1978a9de9248SMarcel Holtmann 
1979a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1980a9de9248SMarcel Holtmann {
1981a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1982a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1983a9de9248SMarcel Holtmann 
1984a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1985a9de9248SMarcel Holtmann 
1986a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1987a9de9248SMarcel Holtmann 
1988a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1989a9de9248SMarcel Holtmann 	if (conn) {
1990a9de9248SMarcel Holtmann 		if (!ev->status)
1991a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1992a9de9248SMarcel Holtmann 
199351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1994a9de9248SMarcel Holtmann 
1995a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1996a9de9248SMarcel Holtmann 	}
1997a9de9248SMarcel Holtmann 
1998a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1999a9de9248SMarcel Holtmann }
2000a9de9248SMarcel Holtmann 
2001a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2002a9de9248SMarcel Holtmann {
2003a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2004a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2005a9de9248SMarcel Holtmann 
2006a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2007a9de9248SMarcel Holtmann 
2008a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2009a9de9248SMarcel Holtmann 
2010a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2011ccd556feSJohan Hedberg 	if (!conn)
2012ccd556feSJohan Hedberg 		goto unlock;
2013ccd556feSJohan Hedberg 
2014769be974SMarcel Holtmann 	if (!ev->status)
2015a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2016a9de9248SMarcel Holtmann 
2017ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2018ccd556feSJohan Hedberg 		goto unlock;
2019ccd556feSJohan Hedberg 
2020ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2021769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2022769be974SMarcel Holtmann 		cp.handle = ev->handle;
2023769be974SMarcel Holtmann 		cp.page = 0x01;
2024ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2025769be974SMarcel Holtmann 							sizeof(cp), &cp);
2026392599b9SJohan Hedberg 		goto unlock;
2027392599b9SJohan Hedberg 	}
2028392599b9SJohan Hedberg 
2029127178d2SJohan Hedberg 	if (!ev->status) {
2030127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2031127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2032127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2033127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2034127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2035b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2036b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2037b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2038b644ba33SJohan Hedberg 						conn->dev_class);
2039392599b9SJohan Hedberg 
2040127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2041769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2042769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2043769be974SMarcel Holtmann 		hci_conn_put(conn);
2044769be974SMarcel Holtmann 	}
2045769be974SMarcel Holtmann 
2046ccd556feSJohan Hedberg unlock:
2047a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2048a9de9248SMarcel Holtmann }
2049a9de9248SMarcel Holtmann 
2050a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2051a9de9248SMarcel Holtmann {
2052a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2053a9de9248SMarcel Holtmann }
2054a9de9248SMarcel Holtmann 
2055a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2056a9de9248SMarcel Holtmann {
2057a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2058a9de9248SMarcel Holtmann }
2059a9de9248SMarcel Holtmann 
2060a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2061a9de9248SMarcel Holtmann {
2062a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2063a9de9248SMarcel Holtmann 	__u16 opcode;
2064a9de9248SMarcel Holtmann 
2065a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2066a9de9248SMarcel Holtmann 
2067a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2068a9de9248SMarcel Holtmann 
2069a9de9248SMarcel Holtmann 	switch (opcode) {
2070a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2071a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2072a9de9248SMarcel Holtmann 		break;
2073a9de9248SMarcel Holtmann 
2074a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2075a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2076a9de9248SMarcel Holtmann 		break;
2077a9de9248SMarcel Holtmann 
2078a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2079a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2080a9de9248SMarcel Holtmann 		break;
2081a9de9248SMarcel Holtmann 
2082a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2083a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2084a9de9248SMarcel Holtmann 		break;
2085a9de9248SMarcel Holtmann 
2086e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2087e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2088e4e8e37cSMarcel Holtmann 		break;
2089e4e8e37cSMarcel Holtmann 
2090a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2091a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2092a9de9248SMarcel Holtmann 		break;
2093a9de9248SMarcel Holtmann 
2094e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2095e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2096e4e8e37cSMarcel Holtmann 		break;
2097e4e8e37cSMarcel Holtmann 
2098e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2099e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2100e4e8e37cSMarcel Holtmann 		break;
2101e4e8e37cSMarcel Holtmann 
2102a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2103a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2104a9de9248SMarcel Holtmann 		break;
2105a9de9248SMarcel Holtmann 
2106a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2107a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2108a9de9248SMarcel Holtmann 		break;
2109a9de9248SMarcel Holtmann 
2110a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2111a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2112a9de9248SMarcel Holtmann 		break;
2113a9de9248SMarcel Holtmann 
2114a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2115a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2116a9de9248SMarcel Holtmann 		break;
2117a9de9248SMarcel Holtmann 
2118a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2119a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2120a9de9248SMarcel Holtmann 		break;
2121a9de9248SMarcel Holtmann 
2122a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2123a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2124a9de9248SMarcel Holtmann 		break;
2125a9de9248SMarcel Holtmann 
2126a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2127a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2128a9de9248SMarcel Holtmann 		break;
2129a9de9248SMarcel Holtmann 
2130a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2131a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2132a9de9248SMarcel Holtmann 		break;
2133a9de9248SMarcel Holtmann 
2134a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2135a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2136a9de9248SMarcel Holtmann 		break;
2137a9de9248SMarcel Holtmann 
2138a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2139a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2140a9de9248SMarcel Holtmann 		break;
2141a9de9248SMarcel Holtmann 
2142a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2143a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2144a9de9248SMarcel Holtmann 		break;
2145a9de9248SMarcel Holtmann 
2146333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
2147333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
2148333140b5SMarcel Holtmann 		break;
2149333140b5SMarcel Holtmann 
2150333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2151333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2152333140b5SMarcel Holtmann 		break;
2153333140b5SMarcel Holtmann 
2154a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2155a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2156a9de9248SMarcel Holtmann 		break;
2157a9de9248SMarcel Holtmann 
2158a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2159a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2160a9de9248SMarcel Holtmann 		break;
2161a9de9248SMarcel Holtmann 
2162a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2163a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2164a9de9248SMarcel Holtmann 		break;
2165a9de9248SMarcel Holtmann 
2166971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2167971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2168971e3a4bSAndre Guedes 		break;
2169971e3a4bSAndre Guedes 
2170a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2171a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2172a9de9248SMarcel Holtmann 		break;
2173a9de9248SMarcel Holtmann 
2174a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2175a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2176a9de9248SMarcel Holtmann 		break;
2177a9de9248SMarcel Holtmann 
2178350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2179350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2180350ee4cfSAndrei Emeltchenko 		break;
2181350ee4cfSAndrei Emeltchenko 
218223bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
218323bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
218423bb5763SJohan Hedberg 		break;
218523bb5763SJohan Hedberg 
21861e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
21871e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
21881e89cffbSAndrei Emeltchenko 		break;
21891e89cffbSAndrei Emeltchenko 
2190928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2191928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2192928abaa7SAndrei Emeltchenko 		break;
2193928abaa7SAndrei Emeltchenko 
2194b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2195b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2196b0916ea0SJohan Hedberg 		break;
2197b0916ea0SJohan Hedberg 
2198d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2199d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2200d5859e22SJohan Hedberg 		break;
2201d5859e22SJohan Hedberg 
2202d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2203d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2204d5859e22SJohan Hedberg 		break;
2205d5859e22SJohan Hedberg 
2206d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2207d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2208d5859e22SJohan Hedberg 		break;
2209d5859e22SJohan Hedberg 
2210d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2211d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2212d5859e22SJohan Hedberg 		break;
2213d5859e22SJohan Hedberg 
2214980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2215980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2216980e1a53SJohan Hedberg 		break;
2217980e1a53SJohan Hedberg 
2218980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2219980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2220980e1a53SJohan Hedberg 		break;
2221980e1a53SJohan Hedberg 
2222c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2223c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2224c35938b2SSzymon Janc 		break;
2225c35938b2SSzymon Janc 
22266ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22276ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22286ed58ec5SVille Tervo 		break;
22296ed58ec5SVille Tervo 
2230a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2231a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2232a5c29683SJohan Hedberg 		break;
2233a5c29683SJohan Hedberg 
2234a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2235a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2236a5c29683SJohan Hedberg 		break;
2237a5c29683SJohan Hedberg 
22381143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
22391143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
22401143d458SBrian Gix 		break;
22411143d458SBrian Gix 
22421143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
22431143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
224407f7fa5dSAndre Guedes 
224507f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
224607f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
22471143d458SBrian Gix 		break;
22481143d458SBrian Gix 
2249eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2250eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2251eb9d91f5SAndre Guedes 		break;
2252eb9d91f5SAndre Guedes 
2253a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2254a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2255a7a595f6SVinicius Costa Gomes 		break;
2256a7a595f6SVinicius Costa Gomes 
2257a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2258a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2259a7a595f6SVinicius Costa Gomes 		break;
2260a7a595f6SVinicius Costa Gomes 
2261f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2262f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2263f9b49306SAndre Guedes 		break;
2264f9b49306SAndre Guedes 
2265a9de9248SMarcel Holtmann 	default:
2266a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2267a9de9248SMarcel Holtmann 		break;
2268a9de9248SMarcel Holtmann 	}
2269a9de9248SMarcel Holtmann 
22706bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
22716bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
22726bd32326SVille Tervo 
2273a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2274a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2275a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2276c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2277a9de9248SMarcel Holtmann 	}
2278a9de9248SMarcel Holtmann }
2279a9de9248SMarcel Holtmann 
2280a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2281a9de9248SMarcel Holtmann {
2282a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2283a9de9248SMarcel Holtmann 	__u16 opcode;
2284a9de9248SMarcel Holtmann 
2285a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2286a9de9248SMarcel Holtmann 
2287a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2288a9de9248SMarcel Holtmann 
2289a9de9248SMarcel Holtmann 	switch (opcode) {
2290a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2291a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2292a9de9248SMarcel Holtmann 		break;
2293a9de9248SMarcel Holtmann 
2294a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2295a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2296a9de9248SMarcel Holtmann 		break;
2297a9de9248SMarcel Holtmann 
2298a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2299a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2300a9de9248SMarcel Holtmann 		break;
2301a9de9248SMarcel Holtmann 
2302f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2303f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2304f8558555SMarcel Holtmann 		break;
2305f8558555SMarcel Holtmann 
2306f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2307f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2308f8558555SMarcel Holtmann 		break;
2309f8558555SMarcel Holtmann 
2310a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2311a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2312a9de9248SMarcel Holtmann 		break;
2313a9de9248SMarcel Holtmann 
2314769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2315769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2316769be974SMarcel Holtmann 		break;
2317769be974SMarcel Holtmann 
2318769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2319769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2320769be974SMarcel Holtmann 		break;
2321769be974SMarcel Holtmann 
2322a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2323a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2324a9de9248SMarcel Holtmann 		break;
2325a9de9248SMarcel Holtmann 
2326a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2327a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2328a9de9248SMarcel Holtmann 		break;
2329a9de9248SMarcel Holtmann 
2330a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2331a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2332a9de9248SMarcel Holtmann 		break;
2333a9de9248SMarcel Holtmann 
23348962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
23358962ee74SJohan Hedberg 		if (ev->status != 0)
233637d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
23378962ee74SJohan Hedberg 		break;
23388962ee74SJohan Hedberg 
2339fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2340fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2341fcd89c09SVille Tervo 		break;
2342fcd89c09SVille Tervo 
2343a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2344a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2345a7a595f6SVinicius Costa Gomes 		break;
2346a7a595f6SVinicius Costa Gomes 
2347a9de9248SMarcel Holtmann 	default:
2348a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2349a9de9248SMarcel Holtmann 		break;
2350a9de9248SMarcel Holtmann 	}
2351a9de9248SMarcel Holtmann 
23526bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23536bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23546bd32326SVille Tervo 
235510572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2356a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2357a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2358c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2359a9de9248SMarcel Holtmann 	}
2360a9de9248SMarcel Holtmann }
2361a9de9248SMarcel Holtmann 
2362a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2363a9de9248SMarcel Holtmann {
2364a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2365a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2366a9de9248SMarcel Holtmann 
2367a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2368a9de9248SMarcel Holtmann 
2369a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2370a9de9248SMarcel Holtmann 
2371a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2372a9de9248SMarcel Holtmann 	if (conn) {
2373a9de9248SMarcel Holtmann 		if (!ev->status) {
2374a9de9248SMarcel Holtmann 			if (ev->role)
2375a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2376a9de9248SMarcel Holtmann 			else
2377a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2378a9de9248SMarcel Holtmann 		}
2379a9de9248SMarcel Holtmann 
238051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2381a9de9248SMarcel Holtmann 
2382a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2383a9de9248SMarcel Holtmann 	}
2384a9de9248SMarcel Holtmann 
2385a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2386a9de9248SMarcel Holtmann }
2387a9de9248SMarcel Holtmann 
23881da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
23891da177e4SLinus Torvalds {
2390a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
23911da177e4SLinus Torvalds 	int i;
23921da177e4SLinus Torvalds 
239332ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
239432ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
239532ac5b9bSAndrei Emeltchenko 		return;
239632ac5b9bSAndrei Emeltchenko 	}
239732ac5b9bSAndrei Emeltchenko 
2398c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2399c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24001da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24011da177e4SLinus Torvalds 		return;
24021da177e4SLinus Torvalds 	}
24031da177e4SLinus Torvalds 
2404c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2405c5993de8SAndrei Emeltchenko 
2406613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2407613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24081da177e4SLinus Torvalds 		struct hci_conn *conn;
24091da177e4SLinus Torvalds 		__u16  handle, count;
24101da177e4SLinus Torvalds 
2411613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2412613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24131da177e4SLinus Torvalds 
24141da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2415f4280918SAndrei Emeltchenko 		if (!conn)
2416f4280918SAndrei Emeltchenko 			continue;
2417f4280918SAndrei Emeltchenko 
24181da177e4SLinus Torvalds 		conn->sent -= count;
24191da177e4SLinus Torvalds 
2420f4280918SAndrei Emeltchenko 		switch (conn->type) {
2421f4280918SAndrei Emeltchenko 		case ACL_LINK:
242270f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
242370f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24241da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2425f4280918SAndrei Emeltchenko 			break;
2426f4280918SAndrei Emeltchenko 
2427f4280918SAndrei Emeltchenko 		case LE_LINK:
24286ed58ec5SVille Tervo 			if (hdev->le_pkts) {
24296ed58ec5SVille Tervo 				hdev->le_cnt += count;
24306ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
24316ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
24326ed58ec5SVille Tervo 			} else {
24336ed58ec5SVille Tervo 				hdev->acl_cnt += count;
24346ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
24356ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
24366ed58ec5SVille Tervo 			}
2437f4280918SAndrei Emeltchenko 			break;
2438f4280918SAndrei Emeltchenko 
2439f4280918SAndrei Emeltchenko 		case SCO_LINK:
244070f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
244170f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
24425b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2443f4280918SAndrei Emeltchenko 			break;
2444f4280918SAndrei Emeltchenko 
2445f4280918SAndrei Emeltchenko 		default:
2446f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2447f4280918SAndrei Emeltchenko 			break;
24481da177e4SLinus Torvalds 		}
24491da177e4SLinus Torvalds 	}
2450a9de9248SMarcel Holtmann 
24513eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
24521da177e4SLinus Torvalds }
24531da177e4SLinus Torvalds 
245425e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
245525e89e99SAndrei Emeltchenko 							struct sk_buff *skb)
245625e89e99SAndrei Emeltchenko {
245725e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
245825e89e99SAndrei Emeltchenko 	int i;
245925e89e99SAndrei Emeltchenko 
246025e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
246125e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
246225e89e99SAndrei Emeltchenko 		return;
246325e89e99SAndrei Emeltchenko 	}
246425e89e99SAndrei Emeltchenko 
246525e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
246625e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
246725e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
246825e89e99SAndrei Emeltchenko 		return;
246925e89e99SAndrei Emeltchenko 	}
247025e89e99SAndrei Emeltchenko 
247125e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
247225e89e99SAndrei Emeltchenko 								ev->num_hndl);
247325e89e99SAndrei Emeltchenko 
247425e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
247525e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
247625e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
247725e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
247825e89e99SAndrei Emeltchenko 
247925e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
248025e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
248125e89e99SAndrei Emeltchenko 
248225e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
248325e89e99SAndrei Emeltchenko 		if (!conn)
248425e89e99SAndrei Emeltchenko 			continue;
248525e89e99SAndrei Emeltchenko 
248625e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
248725e89e99SAndrei Emeltchenko 
248825e89e99SAndrei Emeltchenko 		switch (conn->type) {
248925e89e99SAndrei Emeltchenko 		case ACL_LINK:
249025e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
249125e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
249225e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
249325e89e99SAndrei Emeltchenko 			break;
249425e89e99SAndrei Emeltchenko 
249525e89e99SAndrei Emeltchenko 		default:
249625e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
249725e89e99SAndrei Emeltchenko 			break;
249825e89e99SAndrei Emeltchenko 		}
249925e89e99SAndrei Emeltchenko 	}
250025e89e99SAndrei Emeltchenko 
250125e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
250225e89e99SAndrei Emeltchenko }
250325e89e99SAndrei Emeltchenko 
250404837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25051da177e4SLinus Torvalds {
2506a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
250704837f64SMarcel Holtmann 	struct hci_conn *conn;
25081da177e4SLinus Torvalds 
25091da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
25101da177e4SLinus Torvalds 
25111da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25121da177e4SLinus Torvalds 
251304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
251404837f64SMarcel Holtmann 	if (conn) {
251504837f64SMarcel Holtmann 		conn->mode = ev->mode;
251604837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
251704837f64SMarcel Holtmann 
251851a8efd7SJohan Hedberg 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
251904837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
252058a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
252104837f64SMarcel Holtmann 			else
252258a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
252304837f64SMarcel Holtmann 		}
2524e73439d8SMarcel Holtmann 
252551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2526e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
252704837f64SMarcel Holtmann 	}
252804837f64SMarcel Holtmann 
252904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
253004837f64SMarcel Holtmann }
253104837f64SMarcel Holtmann 
25321da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25331da177e4SLinus Torvalds {
2534052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2535052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2536052b30b0SMarcel Holtmann 
2537a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2538052b30b0SMarcel Holtmann 
2539052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2540052b30b0SMarcel Holtmann 
2541052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2542b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2543b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2544b6f98044SWaldemar Rymarkiewicz 
2545b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2546052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2547052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2548052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2549052b30b0SMarcel Holtmann 	}
2550052b30b0SMarcel Holtmann 
2551a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
255203b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
255303b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2554a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2555a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2556a770bb5aSWaldemar Rymarkiewicz 
2557a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2558a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2559a770bb5aSWaldemar Rymarkiewicz 		else
2560a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2561a770bb5aSWaldemar Rymarkiewicz 
2562744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2563a770bb5aSWaldemar Rymarkiewicz 	}
2564980e1a53SJohan Hedberg 
2565b6f98044SWaldemar Rymarkiewicz unlock:
2566052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
25671da177e4SLinus Torvalds }
25681da177e4SLinus Torvalds 
25691da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25701da177e4SLinus Torvalds {
257155ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
257255ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
257355ed8ca1SJohan Hedberg 	struct hci_conn *conn;
257455ed8ca1SJohan Hedberg 	struct link_key *key;
257555ed8ca1SJohan Hedberg 
2576a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
257755ed8ca1SJohan Hedberg 
2578a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
257955ed8ca1SJohan Hedberg 		return;
258055ed8ca1SJohan Hedberg 
258155ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
258255ed8ca1SJohan Hedberg 
258355ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
258455ed8ca1SJohan Hedberg 	if (!key) {
258555ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
258655ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
258755ed8ca1SJohan Hedberg 		goto not_found;
258855ed8ca1SJohan Hedberg 	}
258955ed8ca1SJohan Hedberg 
259055ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
259155ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
259255ed8ca1SJohan Hedberg 
2593a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2594b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
259555ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
259655ed8ca1SJohan Hedberg 		goto not_found;
259755ed8ca1SJohan Hedberg 	}
259855ed8ca1SJohan Hedberg 
259955ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
260060b83f57SWaldemar Rymarkiewicz 	if (conn) {
260160b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
260260b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
260360b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
260455ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
260555ed8ca1SJohan Hedberg 			goto not_found;
260655ed8ca1SJohan Hedberg 		}
260755ed8ca1SJohan Hedberg 
260860b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
260960b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
261060b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
261160b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
261260b83f57SWaldemar Rymarkiewicz 			goto not_found;
261360b83f57SWaldemar Rymarkiewicz 		}
261460b83f57SWaldemar Rymarkiewicz 
261560b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
261660b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
261760b83f57SWaldemar Rymarkiewicz 	}
261860b83f57SWaldemar Rymarkiewicz 
261955ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
262055ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
262155ed8ca1SJohan Hedberg 
262255ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
262355ed8ca1SJohan Hedberg 
262455ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
262555ed8ca1SJohan Hedberg 
262655ed8ca1SJohan Hedberg 	return;
262755ed8ca1SJohan Hedberg 
262855ed8ca1SJohan Hedberg not_found:
262955ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
263055ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
26311da177e4SLinus Torvalds }
26321da177e4SLinus Torvalds 
26331da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
26341da177e4SLinus Torvalds {
2635052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2636052b30b0SMarcel Holtmann 	struct hci_conn *conn;
263755ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2638052b30b0SMarcel Holtmann 
2639a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2640052b30b0SMarcel Holtmann 
2641052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2642052b30b0SMarcel Holtmann 
2643052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2644052b30b0SMarcel Holtmann 	if (conn) {
2645052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2646052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2647980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
264813d39315SWaldemar Rymarkiewicz 
264913d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
265013d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
265113d39315SWaldemar Rymarkiewicz 
2652052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2653052b30b0SMarcel Holtmann 	}
2654052b30b0SMarcel Holtmann 
2655a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2656d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
265755ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
265855ed8ca1SJohan Hedberg 
2659052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26601da177e4SLinus Torvalds }
26611da177e4SLinus Torvalds 
266204837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
266304837f64SMarcel Holtmann {
2664a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
266504837f64SMarcel Holtmann 	struct hci_conn *conn;
266604837f64SMarcel Holtmann 
266704837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
266804837f64SMarcel Holtmann 
266904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
267004837f64SMarcel Holtmann 
267104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
26721da177e4SLinus Torvalds 	if (conn && !ev->status) {
26731da177e4SLinus Torvalds 		struct inquiry_entry *ie;
26741da177e4SLinus Torvalds 
2675cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2676cc11b9c1SAndrei Emeltchenko 		if (ie) {
26771da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
26781da177e4SLinus Torvalds 			ie->timestamp = jiffies;
26791da177e4SLinus Torvalds 		}
26801da177e4SLinus Torvalds 	}
26811da177e4SLinus Torvalds 
26821da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
26831da177e4SLinus Torvalds }
26841da177e4SLinus Torvalds 
2685a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2686a8746417SMarcel Holtmann {
2687a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2688a8746417SMarcel Holtmann 	struct hci_conn *conn;
2689a8746417SMarcel Holtmann 
2690a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2691a8746417SMarcel Holtmann 
2692a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2693a8746417SMarcel Holtmann 
2694a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2695a8746417SMarcel Holtmann 	if (conn && !ev->status)
2696a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2697a8746417SMarcel Holtmann 
2698a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2699a8746417SMarcel Holtmann }
2700a8746417SMarcel Holtmann 
270185a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
270285a1e930SMarcel Holtmann {
2703a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
270485a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
270585a1e930SMarcel Holtmann 
270685a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
270785a1e930SMarcel Holtmann 
270885a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
270985a1e930SMarcel Holtmann 
2710cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2711cc11b9c1SAndrei Emeltchenko 	if (ie) {
271285a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
271385a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
271485a1e930SMarcel Holtmann 	}
271585a1e930SMarcel Holtmann 
271685a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
271785a1e930SMarcel Holtmann }
271885a1e930SMarcel Holtmann 
2719a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2720a9de9248SMarcel Holtmann {
2721a9de9248SMarcel Holtmann 	struct inquiry_data data;
2722a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
27233175405bSJohan Hedberg 	bool name_known;
2724a9de9248SMarcel Holtmann 
2725a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2726a9de9248SMarcel Holtmann 
2727a9de9248SMarcel Holtmann 	if (!num_rsp)
2728a9de9248SMarcel Holtmann 		return;
2729a9de9248SMarcel Holtmann 
2730a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2731a9de9248SMarcel Holtmann 
2732a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2733138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2734138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2735a9de9248SMarcel Holtmann 
2736e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2737a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2738a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2739a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2740a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2741a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2742a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2743a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
274441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27453175405bSJohan Hedberg 
27463175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27473175405bSJohan Hedberg 								false);
274848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2749e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27507d262f86SAndre Guedes 						!name_known, NULL, 0);
2751a9de9248SMarcel Holtmann 		}
2752a9de9248SMarcel Holtmann 	} else {
2753a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2754a9de9248SMarcel Holtmann 
2755e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2756a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2757a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2758a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2759a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2760a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2761a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2762a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
276341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27643175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27653175405bSJohan Hedberg 								false);
276648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2767e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27687d262f86SAndre Guedes 						!name_known, NULL, 0);
2769a9de9248SMarcel Holtmann 		}
2770a9de9248SMarcel Holtmann 	}
2771a9de9248SMarcel Holtmann 
2772a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2773a9de9248SMarcel Holtmann }
2774a9de9248SMarcel Holtmann 
2775a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2776a9de9248SMarcel Holtmann {
277741a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
277841a96212SMarcel Holtmann 	struct hci_conn *conn;
277941a96212SMarcel Holtmann 
2780a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
278141a96212SMarcel Holtmann 
278241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
278341a96212SMarcel Holtmann 
278441a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2785ccd556feSJohan Hedberg 	if (!conn)
2786ccd556feSJohan Hedberg 		goto unlock;
2787ccd556feSJohan Hedberg 
2788769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
278941a96212SMarcel Holtmann 		struct inquiry_entry *ie;
279041a96212SMarcel Holtmann 
2791cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2792cc11b9c1SAndrei Emeltchenko 		if (ie)
279341a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
279441a96212SMarcel Holtmann 
279558a681efSJohan Hedberg 		if (ev->features[0] & 0x01)
279658a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
279741a96212SMarcel Holtmann 	}
279841a96212SMarcel Holtmann 
2799ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2800ccd556feSJohan Hedberg 		goto unlock;
2801ccd556feSJohan Hedberg 
2802127178d2SJohan Hedberg 	if (!ev->status) {
2803127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2804127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2805127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2806127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2807127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2808b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2809b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2810b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2811b644ba33SJohan Hedberg 						conn->dev_class);
2812392599b9SJohan Hedberg 
2813127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2814769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2815769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2816769be974SMarcel Holtmann 		hci_conn_put(conn);
2817769be974SMarcel Holtmann 	}
2818769be974SMarcel Holtmann 
2819ccd556feSJohan Hedberg unlock:
282041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2821a9de9248SMarcel Holtmann }
2822a9de9248SMarcel Holtmann 
2823a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2824a9de9248SMarcel Holtmann {
2825b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2826b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2827b6a0dc82SMarcel Holtmann 
2828b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2829b6a0dc82SMarcel Holtmann 
2830b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2831b6a0dc82SMarcel Holtmann 
2832b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
28339dc0a3afSMarcel Holtmann 	if (!conn) {
28349dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
28359dc0a3afSMarcel Holtmann 			goto unlock;
28369dc0a3afSMarcel Holtmann 
28379dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2838b6a0dc82SMarcel Holtmann 		if (!conn)
2839b6a0dc82SMarcel Holtmann 			goto unlock;
2840b6a0dc82SMarcel Holtmann 
28419dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
28429dc0a3afSMarcel Holtmann 	}
28439dc0a3afSMarcel Holtmann 
2844732547f9SMarcel Holtmann 	switch (ev->status) {
2845732547f9SMarcel Holtmann 	case 0x00:
2846732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2847732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2848732547f9SMarcel Holtmann 
28499eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2850732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2851732547f9SMarcel Holtmann 		break;
2852732547f9SMarcel Holtmann 
2853705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2854732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
28551038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2856732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2857732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2858efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2859efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2860efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2861efc7688bSMarcel Holtmann 			goto unlock;
2862efc7688bSMarcel Holtmann 		}
2863732547f9SMarcel Holtmann 		/* fall through */
2864efc7688bSMarcel Holtmann 
2865732547f9SMarcel Holtmann 	default:
2866b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2867732547f9SMarcel Holtmann 		break;
2868732547f9SMarcel Holtmann 	}
2869b6a0dc82SMarcel Holtmann 
2870b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2871b6a0dc82SMarcel Holtmann 	if (ev->status)
2872b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2873b6a0dc82SMarcel Holtmann 
2874b6a0dc82SMarcel Holtmann unlock:
2875b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2876a9de9248SMarcel Holtmann }
2877a9de9248SMarcel Holtmann 
2878a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2879a9de9248SMarcel Holtmann {
2880a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2881a9de9248SMarcel Holtmann }
2882a9de9248SMarcel Holtmann 
288304837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
288404837f64SMarcel Holtmann {
2885a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
288604837f64SMarcel Holtmann 
288704837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
288804837f64SMarcel Holtmann }
288904837f64SMarcel Holtmann 
2890a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2891a9de9248SMarcel Holtmann {
2892a9de9248SMarcel Holtmann 	struct inquiry_data data;
2893a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2894a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2895a9de9248SMarcel Holtmann 
2896a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2897a9de9248SMarcel Holtmann 
2898a9de9248SMarcel Holtmann 	if (!num_rsp)
2899a9de9248SMarcel Holtmann 		return;
2900a9de9248SMarcel Holtmann 
2901a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2902a9de9248SMarcel Holtmann 
2903e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2904561aafbcSJohan Hedberg 		bool name_known;
2905561aafbcSJohan Hedberg 
2906a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2907a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2908a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2909a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2910a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2911a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2912a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
291341a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2914561aafbcSJohan Hedberg 
2915a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29164ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29174ddb1930SJohan Hedberg 							sizeof(info->data),
29184ddb1930SJohan Hedberg 							EIR_NAME_COMPLETE);
2919561aafbcSJohan Hedberg 		else
2920561aafbcSJohan Hedberg 			name_known = true;
2921561aafbcSJohan Hedberg 
29223175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known);
292348264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2924561aafbcSJohan Hedberg 						info->dev_class, info->rssi,
29257d262f86SAndre Guedes 						!name_known, info->data,
29267d262f86SAndre Guedes 						sizeof(info->data));
2927a9de9248SMarcel Holtmann 	}
2928a9de9248SMarcel Holtmann 
2929a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2930a9de9248SMarcel Holtmann }
2931a9de9248SMarcel Holtmann 
293217fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
293317fa4b9dSJohan Hedberg {
293417fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
293517fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
293617fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
293717fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
293817fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
293917fa4b9dSJohan Hedberg 			return 0x02;
294017fa4b9dSJohan Hedberg 		else
294117fa4b9dSJohan Hedberg 			return 0x03;
294217fa4b9dSJohan Hedberg 	}
294317fa4b9dSJohan Hedberg 
294417fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
294517fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
294658797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
294717fa4b9dSJohan Hedberg 
294817fa4b9dSJohan Hedberg 	return conn->auth_type;
294917fa4b9dSJohan Hedberg }
295017fa4b9dSJohan Hedberg 
29510493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29520493684eSMarcel Holtmann {
29530493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
29540493684eSMarcel Holtmann 	struct hci_conn *conn;
29550493684eSMarcel Holtmann 
29560493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
29570493684eSMarcel Holtmann 
29580493684eSMarcel Holtmann 	hci_dev_lock(hdev);
29590493684eSMarcel Holtmann 
29600493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
296103b555e1SJohan Hedberg 	if (!conn)
296203b555e1SJohan Hedberg 		goto unlock;
296303b555e1SJohan Hedberg 
29640493684eSMarcel Holtmann 	hci_conn_hold(conn);
29650493684eSMarcel Holtmann 
2966a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
296703b555e1SJohan Hedberg 		goto unlock;
296803b555e1SJohan Hedberg 
2969a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
297003b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
297117fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
297217fa4b9dSJohan Hedberg 
297317fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
29747a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
29757a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
29767a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
29777a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
29787cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
29797cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
298017fa4b9dSJohan Hedberg 
298158a681efSJohan Hedberg 		if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
2982ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2983ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2984ce85ee13SSzymon Janc 		else
2985ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2986ce85ee13SSzymon Janc 
298717fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
298817fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
298903b555e1SJohan Hedberg 	} else {
299003b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
299103b555e1SJohan Hedberg 
299203b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
29939f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
299403b555e1SJohan Hedberg 
299503b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
299603b555e1SJohan Hedberg 							sizeof(cp), &cp);
299703b555e1SJohan Hedberg 	}
299803b555e1SJohan Hedberg 
299903b555e1SJohan Hedberg unlock:
300003b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
300103b555e1SJohan Hedberg }
300203b555e1SJohan Hedberg 
300303b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
300403b555e1SJohan Hedberg {
300503b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
300603b555e1SJohan Hedberg 	struct hci_conn *conn;
300703b555e1SJohan Hedberg 
300803b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
300903b555e1SJohan Hedberg 
301003b555e1SJohan Hedberg 	hci_dev_lock(hdev);
301103b555e1SJohan Hedberg 
301203b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
301303b555e1SJohan Hedberg 	if (!conn)
301403b555e1SJohan Hedberg 		goto unlock;
301503b555e1SJohan Hedberg 
301603b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
301703b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
301858a681efSJohan Hedberg 	if (ev->oob_data)
301958a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
302003b555e1SJohan Hedberg 
302103b555e1SJohan Hedberg unlock:
30220493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
30230493684eSMarcel Holtmann }
30240493684eSMarcel Holtmann 
3025a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3026a5c29683SJohan Hedberg 							struct sk_buff *skb)
3027a5c29683SJohan Hedberg {
3028a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
302955bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
30307a828908SJohan Hedberg 	struct hci_conn *conn;
3031a5c29683SJohan Hedberg 
3032a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3033a5c29683SJohan Hedberg 
3034a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3035a5c29683SJohan Hedberg 
3036a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
30377a828908SJohan Hedberg 		goto unlock;
30387a828908SJohan Hedberg 
30397a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
30407a828908SJohan Hedberg 	if (!conn)
30417a828908SJohan Hedberg 		goto unlock;
30427a828908SJohan Hedberg 
30437a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
30447a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
30457a828908SJohan Hedberg 
30467a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
30477a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
30487a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
30497a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
30507a828908SJohan Hedberg 	 * bit set. */
30517a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
30527a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
30537a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
30547a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
30557a828908SJohan Hedberg 		goto unlock;
30567a828908SJohan Hedberg 	}
30577a828908SJohan Hedberg 
30587a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
30597a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
30607a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
306155bc1a37SJohan Hedberg 
306255bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
306355bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
306455bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
306551a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
306655bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
306755bc1a37SJohan Hedberg 			confirm_hint = 1;
306855bc1a37SJohan Hedberg 			goto confirm;
306955bc1a37SJohan Hedberg 		}
307055bc1a37SJohan Hedberg 
30719f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
30729f61656aSJohan Hedberg 						hdev->auto_accept_delay);
30739f61656aSJohan Hedberg 
30749f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
30759f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
30769f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
30779f61656aSJohan Hedberg 			goto unlock;
30789f61656aSJohan Hedberg 		}
30799f61656aSJohan Hedberg 
30807a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
30817a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
30827a828908SJohan Hedberg 		goto unlock;
30837a828908SJohan Hedberg 	}
30847a828908SJohan Hedberg 
308555bc1a37SJohan Hedberg confirm:
3086744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
308755bc1a37SJohan Hedberg 								confirm_hint);
3088a5c29683SJohan Hedberg 
30897a828908SJohan Hedberg unlock:
3090a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3091a5c29683SJohan Hedberg }
3092a5c29683SJohan Hedberg 
30931143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
30941143d458SBrian Gix 							struct sk_buff *skb)
30951143d458SBrian Gix {
30961143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
30971143d458SBrian Gix 
30981143d458SBrian Gix 	BT_DBG("%s", hdev->name);
30991143d458SBrian Gix 
31001143d458SBrian Gix 	hci_dev_lock(hdev);
31011143d458SBrian Gix 
3102a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
31031143d458SBrian Gix 		mgmt_user_passkey_request(hdev, &ev->bdaddr);
31041143d458SBrian Gix 
31051143d458SBrian Gix 	hci_dev_unlock(hdev);
31061143d458SBrian Gix }
31071143d458SBrian Gix 
31080493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
31090493684eSMarcel Holtmann {
31100493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
31110493684eSMarcel Holtmann 	struct hci_conn *conn;
31120493684eSMarcel Holtmann 
31130493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31140493684eSMarcel Holtmann 
31150493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31160493684eSMarcel Holtmann 
31170493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31182a611692SJohan Hedberg 	if (!conn)
31192a611692SJohan Hedberg 		goto unlock;
31202a611692SJohan Hedberg 
31212a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
31222a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
31232a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
31242a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
31252a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
312651a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3127744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
31282a611692SJohan Hedberg 
31290493684eSMarcel Holtmann 	hci_conn_put(conn);
31300493684eSMarcel Holtmann 
31312a611692SJohan Hedberg unlock:
31320493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31330493684eSMarcel Holtmann }
31340493684eSMarcel Holtmann 
313541a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
313641a96212SMarcel Holtmann {
313741a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
313841a96212SMarcel Holtmann 	struct inquiry_entry *ie;
313941a96212SMarcel Holtmann 
314041a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
314141a96212SMarcel Holtmann 
314241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
314341a96212SMarcel Holtmann 
3144cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3145cc11b9c1SAndrei Emeltchenko 	if (ie)
314641a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
314741a96212SMarcel Holtmann 
314841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
314941a96212SMarcel Holtmann }
315041a96212SMarcel Holtmann 
31512763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
31522763eda6SSzymon Janc 							struct sk_buff *skb)
31532763eda6SSzymon Janc {
31542763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
31552763eda6SSzymon Janc 	struct oob_data *data;
31562763eda6SSzymon Janc 
31572763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
31582763eda6SSzymon Janc 
31592763eda6SSzymon Janc 	hci_dev_lock(hdev);
31602763eda6SSzymon Janc 
3161a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3162e1ba1f15SSzymon Janc 		goto unlock;
3163e1ba1f15SSzymon Janc 
31642763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
31652763eda6SSzymon Janc 	if (data) {
31662763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
31672763eda6SSzymon Janc 
31682763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31692763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
31702763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
31712763eda6SSzymon Janc 
31722763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
31732763eda6SSzymon Janc 									&cp);
31742763eda6SSzymon Janc 	} else {
31752763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
31762763eda6SSzymon Janc 
31772763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31782763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
31792763eda6SSzymon Janc 									&cp);
31802763eda6SSzymon Janc 	}
31812763eda6SSzymon Janc 
3182e1ba1f15SSzymon Janc unlock:
31832763eda6SSzymon Janc 	hci_dev_unlock(hdev);
31842763eda6SSzymon Janc }
31852763eda6SSzymon Janc 
3186fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3187fcd89c09SVille Tervo {
3188fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3189fcd89c09SVille Tervo 	struct hci_conn *conn;
3190fcd89c09SVille Tervo 
3191fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3192fcd89c09SVille Tervo 
3193fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3194fcd89c09SVille Tervo 
3195fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3196b62f328bSVille Tervo 	if (!conn) {
3197b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3198b62f328bSVille Tervo 		if (!conn) {
3199b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3200b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3201b62f328bSVille Tervo 			return;
3202b62f328bSVille Tervo 		}
320329b7988aSAndre Guedes 
320429b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3205b62f328bSVille Tervo 	}
3206fcd89c09SVille Tervo 
3207fcd89c09SVille Tervo 	if (ev->status) {
320848264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
320948264f06SJohan Hedberg 						conn->dst_type, ev->status);
3210fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3211fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3212fcd89c09SVille Tervo 		hci_conn_del(conn);
3213fcd89c09SVille Tervo 		goto unlock;
3214fcd89c09SVille Tervo 	}
3215fcd89c09SVille Tervo 
3216b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3217b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
3218b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0, 0);
321983bc71b4SVinicius Costa Gomes 
32207b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3221fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3222fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3223fcd89c09SVille Tervo 
3224fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3225fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3226fcd89c09SVille Tervo 
3227fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3228fcd89c09SVille Tervo 
3229fcd89c09SVille Tervo unlock:
3230fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3231fcd89c09SVille Tervo }
3232fcd89c09SVille Tervo 
32339aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
32349aa04c91SAndre Guedes 						struct sk_buff *skb)
32359aa04c91SAndre Guedes {
3236e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3237e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
32383c9e9195SAndre Guedes 	s8 rssi;
32399aa04c91SAndre Guedes 
32409aa04c91SAndre Guedes 	hci_dev_lock(hdev);
32419aa04c91SAndre Guedes 
3242e95beb41SAndre Guedes 	while (num_reports--) {
3243e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3244e95beb41SAndre Guedes 
32459aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
32469aa04c91SAndre Guedes 
32473c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
32483c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
32493c9e9195SAndre Guedes 					NULL, rssi, 0, ev->data, ev->length);
32503c9e9195SAndre Guedes 
3251e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
32529aa04c91SAndre Guedes 	}
32539aa04c91SAndre Guedes 
32549aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
32559aa04c91SAndre Guedes }
32569aa04c91SAndre Guedes 
3257a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3258a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3259a7a595f6SVinicius Costa Gomes {
3260a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3261a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3262bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3263a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3264c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3265a7a595f6SVinicius Costa Gomes 
3266a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3267a7a595f6SVinicius Costa Gomes 
3268a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3269a7a595f6SVinicius Costa Gomes 
3270a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3271bea710feSVinicius Costa Gomes 	if (conn == NULL)
3272bea710feSVinicius Costa Gomes 		goto not_found;
3273a7a595f6SVinicius Costa Gomes 
3274bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3275bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3276bea710feSVinicius Costa Gomes 		goto not_found;
3277bea710feSVinicius Costa Gomes 
3278bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3279a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3280c9839a11SVinicius Costa Gomes 
3281c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3282c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3283a7a595f6SVinicius Costa Gomes 
3284a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3285a7a595f6SVinicius Costa Gomes 
3286c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3287c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3288c9839a11SVinicius Costa Gomes 		kfree(ltk);
3289c9839a11SVinicius Costa Gomes 	}
3290c9839a11SVinicius Costa Gomes 
3291a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3292bea710feSVinicius Costa Gomes 
3293bea710feSVinicius Costa Gomes 	return;
3294bea710feSVinicius Costa Gomes 
3295bea710feSVinicius Costa Gomes not_found:
3296bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3297bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3298bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3299a7a595f6SVinicius Costa Gomes }
3300a7a595f6SVinicius Costa Gomes 
3301fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3302fcd89c09SVille Tervo {
3303fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3304fcd89c09SVille Tervo 
3305fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3306fcd89c09SVille Tervo 
3307fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3308fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3309fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3310fcd89c09SVille Tervo 		break;
3311fcd89c09SVille Tervo 
33129aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
33139aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
33149aa04c91SAndre Guedes 		break;
33159aa04c91SAndre Guedes 
3316a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3317a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3318a7a595f6SVinicius Costa Gomes 		break;
3319a7a595f6SVinicius Costa Gomes 
3320fcd89c09SVille Tervo 	default:
3321fcd89c09SVille Tervo 		break;
3322fcd89c09SVille Tervo 	}
3323fcd89c09SVille Tervo }
3324fcd89c09SVille Tervo 
33251da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
33261da177e4SLinus Torvalds {
3327a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3328a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
33291da177e4SLinus Torvalds 
33301da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
33311da177e4SLinus Torvalds 
3332a9de9248SMarcel Holtmann 	switch (event) {
33331da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
33341da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
33351da177e4SLinus Torvalds 		break;
33361da177e4SLinus Torvalds 
33371da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
33381da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
33391da177e4SLinus Torvalds 		break;
33401da177e4SLinus Torvalds 
3341a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3342a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
334321d9e30eSMarcel Holtmann 		break;
334421d9e30eSMarcel Holtmann 
33451da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
33461da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
33471da177e4SLinus Torvalds 		break;
33481da177e4SLinus Torvalds 
33491da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
33501da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
33511da177e4SLinus Torvalds 		break;
33521da177e4SLinus Torvalds 
33531da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
33541da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
33551da177e4SLinus Torvalds 		break;
33561da177e4SLinus Torvalds 
3357a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3358a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3359a9de9248SMarcel Holtmann 		break;
3360a9de9248SMarcel Holtmann 
33611da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
33621da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
33631da177e4SLinus Torvalds 		break;
33641da177e4SLinus Torvalds 
3365a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3366a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3367a9de9248SMarcel Holtmann 		break;
3368a9de9248SMarcel Holtmann 
3369a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3370a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3371a9de9248SMarcel Holtmann 		break;
3372a9de9248SMarcel Holtmann 
3373a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3374a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3375a9de9248SMarcel Holtmann 		break;
3376a9de9248SMarcel Holtmann 
3377a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3378a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3379a9de9248SMarcel Holtmann 		break;
3380a9de9248SMarcel Holtmann 
3381a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3382a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3383a9de9248SMarcel Holtmann 		break;
3384a9de9248SMarcel Holtmann 
3385a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3386a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3387a9de9248SMarcel Holtmann 		break;
3388a9de9248SMarcel Holtmann 
3389a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3390a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3391a9de9248SMarcel Holtmann 		break;
3392a9de9248SMarcel Holtmann 
3393a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3394a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3395a9de9248SMarcel Holtmann 		break;
3396a9de9248SMarcel Holtmann 
3397a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3398a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
33991da177e4SLinus Torvalds 		break;
34001da177e4SLinus Torvalds 
34011da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
34021da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
34031da177e4SLinus Torvalds 		break;
34041da177e4SLinus Torvalds 
34051da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
34061da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
34071da177e4SLinus Torvalds 		break;
34081da177e4SLinus Torvalds 
34091da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
34101da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
34111da177e4SLinus Torvalds 		break;
34121da177e4SLinus Torvalds 
34131da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
34141da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
34151da177e4SLinus Torvalds 		break;
34161da177e4SLinus Torvalds 
3417a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3418a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3419a8746417SMarcel Holtmann 		break;
3420a8746417SMarcel Holtmann 
342185a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
342285a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
342385a1e930SMarcel Holtmann 		break;
342485a1e930SMarcel Holtmann 
3425a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3426a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3427a9de9248SMarcel Holtmann 		break;
3428a9de9248SMarcel Holtmann 
3429a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3430a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3431a9de9248SMarcel Holtmann 		break;
3432a9de9248SMarcel Holtmann 
3433a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3434a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3435a9de9248SMarcel Holtmann 		break;
3436a9de9248SMarcel Holtmann 
3437a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3438a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3439a9de9248SMarcel Holtmann 		break;
3440a9de9248SMarcel Holtmann 
344104837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
344204837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
344304837f64SMarcel Holtmann 		break;
344404837f64SMarcel Holtmann 
3445a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3446a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
34471da177e4SLinus Torvalds 		break;
34481da177e4SLinus Torvalds 
34490493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
34500493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
34510493684eSMarcel Holtmann 		break;
34520493684eSMarcel Holtmann 
345303b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
345403b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
345503b555e1SJohan Hedberg 		break;
345603b555e1SJohan Hedberg 
3457a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3458a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3459a5c29683SJohan Hedberg 		break;
3460a5c29683SJohan Hedberg 
34611143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
34621143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
34631143d458SBrian Gix 		break;
34641143d458SBrian Gix 
34650493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
34660493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
34670493684eSMarcel Holtmann 		break;
34680493684eSMarcel Holtmann 
346941a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
347041a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
347141a96212SMarcel Holtmann 		break;
347241a96212SMarcel Holtmann 
3473fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3474fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3475fcd89c09SVille Tervo 		break;
3476fcd89c09SVille Tervo 
34772763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
34782763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
34792763eda6SSzymon Janc 		break;
34802763eda6SSzymon Janc 
348125e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
348225e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
348325e89e99SAndrei Emeltchenko 		break;
348425e89e99SAndrei Emeltchenko 
34851da177e4SLinus Torvalds 	default:
3486a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
34871da177e4SLinus Torvalds 		break;
34881da177e4SLinus Torvalds 	}
34891da177e4SLinus Torvalds 
34901da177e4SLinus Torvalds 	kfree_skb(skb);
34911da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
34921da177e4SLinus Torvalds }
34931da177e4SLinus Torvalds 
34941da177e4SLinus Torvalds /* Generate internal stack event */
34951da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
34961da177e4SLinus Torvalds {
34971da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
34981da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
34991da177e4SLinus Torvalds 	struct sk_buff *skb;
35001da177e4SLinus Torvalds 
35011da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
35021da177e4SLinus Torvalds 	if (!skb)
35031da177e4SLinus Torvalds 		return;
35041da177e4SLinus Torvalds 
35051da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
35061da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
35071da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
35081da177e4SLinus Torvalds 
35091da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
35101da177e4SLinus Torvalds 	ev->type = type;
35111da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
35121da177e4SLinus Torvalds 
3513576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3514a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3515576c7d85SMarcel Holtmann 
35160d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
35171da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3518eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
35191da177e4SLinus Torvalds 	kfree_skb(skb);
35201da177e4SLinus Torvalds }
3521e6100a25SAndre Guedes 
3522669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3523e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3524