xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 3fd24153)
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);
10347ba8b4beSAndre Guedes 
10357ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
10363fd24153SAndre Guedes 
10373fd24153SAndre Guedes 	if (status) {
10383fd24153SAndre Guedes 		hci_dev_lock(hdev);
10393fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
10403fd24153SAndre Guedes 		hci_dev_unlock(hdev);
10413fd24153SAndre Guedes 		return;
10423fd24153SAndre Guedes 	}
104307f7fa5dSAndre Guedes }
104407f7fa5dSAndre Guedes 
1045eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1046eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1047eb9d91f5SAndre Guedes {
1048eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1049eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1050eb9d91f5SAndre Guedes 
1051eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1052eb9d91f5SAndre Guedes 
1053eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1054eb9d91f5SAndre Guedes 	if (!cp)
1055eb9d91f5SAndre Guedes 		return;
1056eb9d91f5SAndre Guedes 
105768a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
105868a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
10597ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
10607ba8b4beSAndre Guedes 
10613fd24153SAndre Guedes 		if (status) {
10623fd24153SAndre Guedes 			hci_dev_lock(hdev);
10633fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
10643fd24153SAndre Guedes 			hci_dev_unlock(hdev);
10657ba8b4beSAndre Guedes 			return;
10663fd24153SAndre Guedes 		}
10677ba8b4beSAndre Guedes 
1068d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1069d23264a8SAndre Guedes 
1070db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1071a8f13c8cSAndre Guedes 
1072a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1073eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1074c599008fSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_LE_SCAN);
1075a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
107668a8aea4SAndrei Emeltchenko 		break;
107768a8aea4SAndrei Emeltchenko 
107868a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
10797ba8b4beSAndre Guedes 		if (status)
10807ba8b4beSAndre Guedes 			return;
10817ba8b4beSAndre Guedes 
1082d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1083d23264a8SAndre Guedes 
1084c599008fSAndre Guedes 		hci_dev_lock(hdev);
1085c599008fSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1086c599008fSAndre Guedes 		hci_dev_unlock(hdev);
1087c599008fSAndre Guedes 
1088d084329eSAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
108968a8aea4SAndrei Emeltchenko 		break;
109068a8aea4SAndrei Emeltchenko 
109168a8aea4SAndrei Emeltchenko 	default:
109268a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
109368a8aea4SAndrei Emeltchenko 		break;
109435815085SAndre Guedes 	}
1095eb9d91f5SAndre Guedes }
1096eb9d91f5SAndre Guedes 
1097a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1098a7a595f6SVinicius Costa Gomes {
1099a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1100a7a595f6SVinicius Costa Gomes 
1101a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1102a7a595f6SVinicius Costa Gomes 
1103a7a595f6SVinicius Costa Gomes 	if (rp->status)
1104a7a595f6SVinicius Costa Gomes 		return;
1105a7a595f6SVinicius Costa Gomes 
1106a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1107a7a595f6SVinicius Costa Gomes }
1108a7a595f6SVinicius Costa Gomes 
1109a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1110a7a595f6SVinicius Costa Gomes {
1111a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1112a7a595f6SVinicius Costa Gomes 
1113a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1114a7a595f6SVinicius Costa Gomes 
1115a7a595f6SVinicius Costa Gomes 	if (rp->status)
1116a7a595f6SVinicius Costa Gomes 		return;
1117a7a595f6SVinicius Costa Gomes 
1118a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1119a7a595f6SVinicius Costa Gomes }
1120a7a595f6SVinicius Costa Gomes 
1121f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1122f9b49306SAndre Guedes 							struct sk_buff *skb)
1123f9b49306SAndre Guedes {
1124f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1125f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1126f9b49306SAndre Guedes 
1127f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1128f9b49306SAndre Guedes 
1129f9b49306SAndre Guedes 	if (status)
1130f9b49306SAndre Guedes 		return;
1131f9b49306SAndre Guedes 
1132f9b49306SAndre Guedes 	cp.page = 0x01;
1133f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1134f9b49306SAndre Guedes }
1135f9b49306SAndre Guedes 
1136a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1137a9de9248SMarcel Holtmann {
1138a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1139a9de9248SMarcel Holtmann 
1140a9de9248SMarcel Holtmann 	if (status) {
114123bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1142a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
114356e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1144a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11457a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
114656e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1147314b2381SJohan Hedberg 		return;
1148314b2381SJohan Hedberg 	}
1149314b2381SJohan Hedberg 
115089352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
115189352e7dSAndre Guedes 
115256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
115330dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_INQUIRY);
115456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1155a9de9248SMarcel Holtmann }
1156a9de9248SMarcel Holtmann 
11571da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11581da177e4SLinus Torvalds {
1159a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11601da177e4SLinus Torvalds 	struct hci_conn *conn;
11611da177e4SLinus Torvalds 
1162a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1163a9de9248SMarcel Holtmann 
1164a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11651da177e4SLinus Torvalds 	if (!cp)
11661da177e4SLinus Torvalds 		return;
11671da177e4SLinus Torvalds 
11681da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11691da177e4SLinus Torvalds 
11701da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11711da177e4SLinus Torvalds 
1172a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11731da177e4SLinus Torvalds 
11741da177e4SLinus Torvalds 	if (status) {
11751da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11764c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11771da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11781da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11791da177e4SLinus Torvalds 				hci_conn_del(conn);
11804c67bc74SMarcel Holtmann 			} else
11814c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11821da177e4SLinus Torvalds 		}
11831da177e4SLinus Torvalds 	} else {
11841da177e4SLinus Torvalds 		if (!conn) {
11851da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11861da177e4SLinus Torvalds 			if (conn) {
1187a0c808b3SJohan Hedberg 				conn->out = true;
11881da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11891da177e4SLinus Torvalds 			} else
1190893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11911da177e4SLinus Torvalds 		}
11921da177e4SLinus Torvalds 	}
11931da177e4SLinus Torvalds 
11941da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11951da177e4SLinus Torvalds }
11961da177e4SLinus Torvalds 
1197a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11981da177e4SLinus Torvalds {
1199a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12001da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12011da177e4SLinus Torvalds 	__u16 handle;
12021da177e4SLinus Torvalds 
1203b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1204b6a0dc82SMarcel Holtmann 
1205a9de9248SMarcel Holtmann 	if (!status)
1206a9de9248SMarcel Holtmann 		return;
1207a9de9248SMarcel Holtmann 
1208a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12091da177e4SLinus Torvalds 	if (!cp)
1210a9de9248SMarcel Holtmann 		return;
12111da177e4SLinus Torvalds 
12121da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12131da177e4SLinus Torvalds 
1214a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
12151da177e4SLinus Torvalds 
12161da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12171da177e4SLinus Torvalds 
12181da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12195a08ecceSAndrei Emeltchenko 	if (acl) {
12205a08ecceSAndrei Emeltchenko 		sco = acl->link;
12215a08ecceSAndrei Emeltchenko 		if (sco) {
12221da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12251da177e4SLinus Torvalds 			hci_conn_del(sco);
12261da177e4SLinus Torvalds 		}
12275a08ecceSAndrei Emeltchenko 	}
12281da177e4SLinus Torvalds 
12291da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12301da177e4SLinus Torvalds }
12311da177e4SLinus Torvalds 
1232f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1233f8558555SMarcel Holtmann {
1234f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1235f8558555SMarcel Holtmann 	struct hci_conn *conn;
1236f8558555SMarcel Holtmann 
1237f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1238f8558555SMarcel Holtmann 
1239f8558555SMarcel Holtmann 	if (!status)
1240f8558555SMarcel Holtmann 		return;
1241f8558555SMarcel Holtmann 
1242f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1243f8558555SMarcel Holtmann 	if (!cp)
1244f8558555SMarcel Holtmann 		return;
1245f8558555SMarcel Holtmann 
1246f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1247f8558555SMarcel Holtmann 
1248f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1249f8558555SMarcel Holtmann 	if (conn) {
1250f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1251f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1252f8558555SMarcel Holtmann 			hci_conn_put(conn);
1253f8558555SMarcel Holtmann 		}
1254f8558555SMarcel Holtmann 	}
1255f8558555SMarcel Holtmann 
1256f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1257f8558555SMarcel Holtmann }
1258f8558555SMarcel Holtmann 
1259f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1260f8558555SMarcel Holtmann {
1261f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1262f8558555SMarcel Holtmann 	struct hci_conn *conn;
1263f8558555SMarcel Holtmann 
1264f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1265f8558555SMarcel Holtmann 
1266f8558555SMarcel Holtmann 	if (!status)
1267f8558555SMarcel Holtmann 		return;
1268f8558555SMarcel Holtmann 
1269f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1270f8558555SMarcel Holtmann 	if (!cp)
1271f8558555SMarcel Holtmann 		return;
1272f8558555SMarcel Holtmann 
1273f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1274f8558555SMarcel Holtmann 
1275f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1276f8558555SMarcel Holtmann 	if (conn) {
1277f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1278f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1279f8558555SMarcel Holtmann 			hci_conn_put(conn);
1280f8558555SMarcel Holtmann 		}
1281f8558555SMarcel Holtmann 	}
1282f8558555SMarcel Holtmann 
1283f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1284f8558555SMarcel Holtmann }
1285f8558555SMarcel Holtmann 
1286127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1287392599b9SJohan Hedberg 							struct hci_conn *conn)
1288392599b9SJohan Hedberg {
1289392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1290392599b9SJohan Hedberg 		return 0;
1291392599b9SJohan Hedberg 
1292765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1293392599b9SJohan Hedberg 		return 0;
1294392599b9SJohan Hedberg 
1295392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1296e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1297aa64a8b5SJohan Hedberg 	if (!hci_conn_ssp_enabled(conn) &&
1298e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1299e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1300392599b9SJohan Hedberg 		return 0;
1301392599b9SJohan Hedberg 
1302392599b9SJohan Hedberg 	return 1;
1303392599b9SJohan Hedberg }
1304392599b9SJohan Hedberg 
130530dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
130630dc78e1SJohan Hedberg {
130730dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
130830dc78e1SJohan Hedberg 
130930dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
131030dc78e1SJohan Hedberg 
131130dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
131230dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
131330dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
131430dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
131530dc78e1SJohan Hedberg 
131630dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
131730dc78e1SJohan Hedberg }
131830dc78e1SJohan Hedberg 
1319b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
132030dc78e1SJohan Hedberg {
132130dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
132230dc78e1SJohan Hedberg 	struct inquiry_entry *e;
132330dc78e1SJohan Hedberg 
1324b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1325b644ba33SJohan Hedberg 		return false;
1326b644ba33SJohan Hedberg 
1327b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1328b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1329b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1330b644ba33SJohan Hedberg 		return true;
1331b644ba33SJohan Hedberg 	}
1332b644ba33SJohan Hedberg 
1333b644ba33SJohan Hedberg 	return false;
1334b644ba33SJohan Hedberg }
1335b644ba33SJohan Hedberg 
1336b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1337b644ba33SJohan Hedberg 					bdaddr_t *bdaddr, u8 *name, u8 name_len)
1338b644ba33SJohan Hedberg {
1339b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1340b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1341b644ba33SJohan Hedberg 
1342b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
1343b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00,
1344b644ba33SJohan Hedberg 					name, name_len, conn->dev_class);
1345b644ba33SJohan Hedberg 
1346b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1347b644ba33SJohan Hedberg 		return;
1348b644ba33SJohan Hedberg 
134930dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
135030dc78e1SJohan Hedberg 		goto discov_complete;
135130dc78e1SJohan Hedberg 
135230dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
135330dc78e1SJohan Hedberg 		return;
135430dc78e1SJohan Hedberg 
135530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
135630dc78e1SJohan Hedberg 	if (e) {
135730dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
135830dc78e1SJohan Hedberg 		list_del(&e->list);
1359b644ba33SJohan Hedberg 		if (name)
1360b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1361b644ba33SJohan Hedberg 					e->data.rssi, name, name_len);
136230dc78e1SJohan Hedberg 	}
136330dc78e1SJohan Hedberg 
1364b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
136530dc78e1SJohan Hedberg 		return;
136630dc78e1SJohan Hedberg 
136730dc78e1SJohan Hedberg discov_complete:
136830dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
136930dc78e1SJohan Hedberg }
137030dc78e1SJohan Hedberg 
1371a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13721da177e4SLinus Torvalds {
1373127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1374127178d2SJohan Hedberg 	struct hci_conn *conn;
1375127178d2SJohan Hedberg 
1376a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1377127178d2SJohan Hedberg 
1378127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1379127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1380127178d2SJohan Hedberg 	if (!status)
1381127178d2SJohan Hedberg 		return;
1382127178d2SJohan Hedberg 
1383127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1384127178d2SJohan Hedberg 	if (!cp)
1385127178d2SJohan Hedberg 		return;
1386127178d2SJohan Hedberg 
1387127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1388127178d2SJohan Hedberg 
1389127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1390b644ba33SJohan Hedberg 
1391b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1392b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1393b644ba33SJohan Hedberg 
139479c6c70cSJohan Hedberg 	if (!conn)
139579c6c70cSJohan Hedberg 		goto unlock;
139679c6c70cSJohan Hedberg 
139779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
139879c6c70cSJohan Hedberg 		goto unlock;
139979c6c70cSJohan Hedberg 
140051a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1401127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1402127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1403127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1404127178d2SJohan Hedberg 	}
1405127178d2SJohan Hedberg 
140679c6c70cSJohan Hedberg unlock:
1407127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1408a9de9248SMarcel Holtmann }
14091da177e4SLinus Torvalds 
1410769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1411769be974SMarcel Holtmann {
1412769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1413769be974SMarcel Holtmann 	struct hci_conn *conn;
1414769be974SMarcel Holtmann 
1415769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1416769be974SMarcel Holtmann 
1417769be974SMarcel Holtmann 	if (!status)
1418769be974SMarcel Holtmann 		return;
1419769be974SMarcel Holtmann 
1420769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1421769be974SMarcel Holtmann 	if (!cp)
1422769be974SMarcel Holtmann 		return;
1423769be974SMarcel Holtmann 
1424769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1425769be974SMarcel Holtmann 
1426769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1427769be974SMarcel Holtmann 	if (conn) {
1428769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1429769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1430769be974SMarcel Holtmann 			hci_conn_put(conn);
1431769be974SMarcel Holtmann 		}
1432769be974SMarcel Holtmann 	}
1433769be974SMarcel Holtmann 
1434769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1435769be974SMarcel Holtmann }
1436769be974SMarcel Holtmann 
1437769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1438769be974SMarcel Holtmann {
1439769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1440769be974SMarcel Holtmann 	struct hci_conn *conn;
1441769be974SMarcel Holtmann 
1442769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1443769be974SMarcel Holtmann 
1444769be974SMarcel Holtmann 	if (!status)
1445769be974SMarcel Holtmann 		return;
1446769be974SMarcel Holtmann 
1447769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1448769be974SMarcel Holtmann 	if (!cp)
1449769be974SMarcel Holtmann 		return;
1450769be974SMarcel Holtmann 
1451769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1452769be974SMarcel Holtmann 
1453769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1454769be974SMarcel Holtmann 	if (conn) {
1455769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1456769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1457769be974SMarcel Holtmann 			hci_conn_put(conn);
1458769be974SMarcel Holtmann 		}
1459769be974SMarcel Holtmann 	}
1460769be974SMarcel Holtmann 
1461769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1462769be974SMarcel Holtmann }
1463769be974SMarcel Holtmann 
1464a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1465a9de9248SMarcel Holtmann {
1466b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1467b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1468b6a0dc82SMarcel Holtmann 	__u16 handle;
1469b6a0dc82SMarcel Holtmann 
1470a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1471b6a0dc82SMarcel Holtmann 
1472b6a0dc82SMarcel Holtmann 	if (!status)
1473b6a0dc82SMarcel Holtmann 		return;
1474b6a0dc82SMarcel Holtmann 
1475b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1476b6a0dc82SMarcel Holtmann 	if (!cp)
1477b6a0dc82SMarcel Holtmann 		return;
1478b6a0dc82SMarcel Holtmann 
1479b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1480b6a0dc82SMarcel Holtmann 
1481b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1482b6a0dc82SMarcel Holtmann 
1483b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1484b6a0dc82SMarcel Holtmann 
1485b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14865a08ecceSAndrei Emeltchenko 	if (acl) {
14875a08ecceSAndrei Emeltchenko 		sco = acl->link;
14885a08ecceSAndrei Emeltchenko 		if (sco) {
1489b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1490b6a0dc82SMarcel Holtmann 
1491b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1492b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1493b6a0dc82SMarcel Holtmann 		}
14945a08ecceSAndrei Emeltchenko 	}
1495b6a0dc82SMarcel Holtmann 
1496b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1497a9de9248SMarcel Holtmann }
1498a9de9248SMarcel Holtmann 
1499a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1500a9de9248SMarcel Holtmann {
1501a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
150204837f64SMarcel Holtmann 	struct hci_conn *conn;
150304837f64SMarcel Holtmann 
1504a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1505a9de9248SMarcel Holtmann 
1506a9de9248SMarcel Holtmann 	if (!status)
1507a9de9248SMarcel Holtmann 		return;
1508a9de9248SMarcel Holtmann 
1509a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
151004837f64SMarcel Holtmann 	if (!cp)
1511a9de9248SMarcel Holtmann 		return;
151204837f64SMarcel Holtmann 
151304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
151404837f64SMarcel Holtmann 
151504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1516e73439d8SMarcel Holtmann 	if (conn) {
151751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
151804837f64SMarcel Holtmann 
151951a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1520e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1521e73439d8SMarcel Holtmann 	}
1522e73439d8SMarcel Holtmann 
152304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
152404837f64SMarcel Holtmann }
152504837f64SMarcel Holtmann 
1526a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1527a9de9248SMarcel Holtmann {
1528a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
152904837f64SMarcel Holtmann 	struct hci_conn *conn;
153004837f64SMarcel Holtmann 
1531a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1532a9de9248SMarcel Holtmann 
1533a9de9248SMarcel Holtmann 	if (!status)
1534a9de9248SMarcel Holtmann 		return;
1535a9de9248SMarcel Holtmann 
1536a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
153704837f64SMarcel Holtmann 	if (!cp)
1538a9de9248SMarcel Holtmann 		return;
153904837f64SMarcel Holtmann 
154004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
154104837f64SMarcel Holtmann 
154204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1543e73439d8SMarcel Holtmann 	if (conn) {
154451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
154504837f64SMarcel Holtmann 
154651a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1547e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1548e73439d8SMarcel Holtmann 	}
1549e73439d8SMarcel Holtmann 
155004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
155104837f64SMarcel Holtmann }
155204837f64SMarcel Holtmann 
1553fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1554fcd89c09SVille Tervo {
1555fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1556fcd89c09SVille Tervo 	struct hci_conn *conn;
1557fcd89c09SVille Tervo 
1558fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1559fcd89c09SVille Tervo 
1560fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1561fcd89c09SVille Tervo 	if (!cp)
1562fcd89c09SVille Tervo 		return;
1563fcd89c09SVille Tervo 
1564fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1565fcd89c09SVille Tervo 
1566fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1567fcd89c09SVille Tervo 
1568fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1569fcd89c09SVille Tervo 		conn);
1570fcd89c09SVille Tervo 
1571fcd89c09SVille Tervo 	if (status) {
1572fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1573fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1574fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1575fcd89c09SVille Tervo 			hci_conn_del(conn);
1576fcd89c09SVille Tervo 		}
1577fcd89c09SVille Tervo 	} else {
1578fcd89c09SVille Tervo 		if (!conn) {
1579fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
158029b7988aSAndre Guedes 			if (conn) {
158129b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1582a0c808b3SJohan Hedberg 				conn->out = true;
158329b7988aSAndre Guedes 			} else {
1584fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1585fcd89c09SVille Tervo 			}
1586fcd89c09SVille Tervo 		}
158729b7988aSAndre Guedes 	}
1588fcd89c09SVille Tervo 
1589fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1590fcd89c09SVille Tervo }
1591fcd89c09SVille Tervo 
1592a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1593a7a595f6SVinicius Costa Gomes {
1594a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1595a7a595f6SVinicius Costa Gomes }
1596a7a595f6SVinicius Costa Gomes 
15971da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15981da177e4SLinus Torvalds {
15991da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
160030dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
160130dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16021da177e4SLinus Torvalds 
16031da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
16041da177e4SLinus Torvalds 
160523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16066bd57416SMarcel Holtmann 
1607a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
160889352e7dSAndre Guedes 
160989352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
161089352e7dSAndre Guedes 		return;
161189352e7dSAndre Guedes 
1612a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
161330dc78e1SJohan Hedberg 		return;
161430dc78e1SJohan Hedberg 
161556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
161630dc78e1SJohan Hedberg 
161730dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_INQUIRY)
161830dc78e1SJohan Hedberg 		goto unlock;
161930dc78e1SJohan Hedberg 
162030dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1621ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
162230dc78e1SJohan Hedberg 		goto unlock;
162330dc78e1SJohan Hedberg 	}
162430dc78e1SJohan Hedberg 
162530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
162630dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
162730dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
162830dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
162930dc78e1SJohan Hedberg 	} else {
163030dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
163130dc78e1SJohan Hedberg 	}
163230dc78e1SJohan Hedberg 
163330dc78e1SJohan Hedberg unlock:
163456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16351da177e4SLinus Torvalds }
16361da177e4SLinus Torvalds 
16371da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16381da177e4SLinus Torvalds {
163945bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1640a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16411da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16421da177e4SLinus Torvalds 
16431da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16441da177e4SLinus Torvalds 
164545bb4bf0SMarcel Holtmann 	if (!num_rsp)
164645bb4bf0SMarcel Holtmann 		return;
164745bb4bf0SMarcel Holtmann 
16481da177e4SLinus Torvalds 	hci_dev_lock(hdev);
164945bb4bf0SMarcel Holtmann 
1650e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
16513175405bSJohan Hedberg 		bool name_known;
16523175405bSJohan Hedberg 
16531da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16541da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16551da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16561da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16571da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16581da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16591da177e4SLinus Torvalds 		data.rssi		= 0x00;
166041a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16613175405bSJohan Hedberg 
16623175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false);
166348264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
16647d262f86SAndre Guedes 					info->dev_class, 0, !name_known,
16657d262f86SAndre Guedes 					NULL, 0);
16661da177e4SLinus Torvalds 	}
166745bb4bf0SMarcel Holtmann 
16681da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16691da177e4SLinus Torvalds }
16701da177e4SLinus Torvalds 
1671a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16721da177e4SLinus Torvalds {
1673a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1674a9de9248SMarcel Holtmann 	struct hci_conn *conn;
16751da177e4SLinus Torvalds 
1676a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
167745bb4bf0SMarcel Holtmann 
16781da177e4SLinus Torvalds 	hci_dev_lock(hdev);
167945bb4bf0SMarcel Holtmann 
1680a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16819499237aSMarcel Holtmann 	if (!conn) {
16829499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16839499237aSMarcel Holtmann 			goto unlock;
16849499237aSMarcel Holtmann 
16859499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1686a9de9248SMarcel Holtmann 		if (!conn)
1687a9de9248SMarcel Holtmann 			goto unlock;
168845bb4bf0SMarcel Holtmann 
16899499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16909499237aSMarcel Holtmann 	}
16919499237aSMarcel Holtmann 
1692a9de9248SMarcel Holtmann 	if (!ev->status) {
1693a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1694769be974SMarcel Holtmann 
1695769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1696769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1697769be974SMarcel Holtmann 			hci_conn_hold(conn);
1698052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1699769be974SMarcel Holtmann 		} else
1700a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1701a9de9248SMarcel Holtmann 
17029eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
17037d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17047d0db0a3SMarcel Holtmann 
1705a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1706a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1707a9de9248SMarcel Holtmann 
1708a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1709a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1710a9de9248SMarcel Holtmann 
1711a9de9248SMarcel Holtmann 		/* Get remote features */
1712a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1713a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1714a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1715769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1716769be974SMarcel Holtmann 							sizeof(cp), &cp);
171745bb4bf0SMarcel Holtmann 		}
1718a9de9248SMarcel Holtmann 
1719a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1720d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1721a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1722a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1723a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1724a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1725a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1726a9de9248SMarcel Holtmann 		}
172717d5c04cSJohan Hedberg 	} else {
1728a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
172917d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1730744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
173148264f06SJohan Hedberg 						conn->dst_type, ev->status);
173217d5c04cSJohan Hedberg 	}
173345bb4bf0SMarcel Holtmann 
1734e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1735e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
173645bb4bf0SMarcel Holtmann 
1737769be974SMarcel Holtmann 	if (ev->status) {
1738a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1739a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1740c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1741c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1742a9de9248SMarcel Holtmann 
1743a9de9248SMarcel Holtmann unlock:
17441da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1745a9de9248SMarcel Holtmann 
1746a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
17471da177e4SLinus Torvalds }
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17501da177e4SLinus Torvalds {
1751a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17521da177e4SLinus Torvalds 	int mask = hdev->link_mode;
17531da177e4SLinus Torvalds 
1754a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
17551da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
17561da177e4SLinus Torvalds 
17571da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
17581da177e4SLinus Torvalds 
1759138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1760138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
17611da177e4SLinus Torvalds 		/* Connection accepted */
1762c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17631da177e4SLinus Torvalds 		struct hci_conn *conn;
17641da177e4SLinus Torvalds 
17651da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1766b6a0dc82SMarcel Holtmann 
1767cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1768cc11b9c1SAndrei Emeltchenko 		if (ie)
1769c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1770c7bdd502SMarcel Holtmann 
17711da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17721da177e4SLinus Torvalds 		if (!conn) {
1773cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1774cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1775893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17761da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17771da177e4SLinus Torvalds 				return;
17781da177e4SLinus Torvalds 			}
17791da177e4SLinus Torvalds 		}
1780b6a0dc82SMarcel Holtmann 
17811da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
17821da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1783b6a0dc82SMarcel Holtmann 
17841da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17851da177e4SLinus Torvalds 
1786b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1787b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1788b6a0dc82SMarcel Holtmann 
17891da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17901da177e4SLinus Torvalds 
17911da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17921da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17931da177e4SLinus Torvalds 			else
17941da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17951da177e4SLinus Torvalds 
1796b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1797b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1798b6a0dc82SMarcel Holtmann 		} else {
1799b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1800b6a0dc82SMarcel Holtmann 
1801b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1802a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1803b6a0dc82SMarcel Holtmann 
1804b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1805b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1806b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1807b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1808b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1809b6a0dc82SMarcel Holtmann 
1810b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1811b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1812b6a0dc82SMarcel Holtmann 		}
18131da177e4SLinus Torvalds 	} else {
18141da177e4SLinus Torvalds 		/* Connection rejected */
18151da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18161da177e4SLinus Torvalds 
18171da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18189f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1819a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18201da177e4SLinus Torvalds 	}
18211da177e4SLinus Torvalds }
18221da177e4SLinus Torvalds 
18231da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18241da177e4SLinus Torvalds {
1825a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
182604837f64SMarcel Holtmann 	struct hci_conn *conn;
18271da177e4SLinus Torvalds 
18281da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
18291da177e4SLinus Torvalds 
18301da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18311da177e4SLinus Torvalds 
183204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1833f7520543SJohan Hedberg 	if (!conn)
1834f7520543SJohan Hedberg 		goto unlock;
1835f7520543SJohan Hedberg 
183637d9ef76SJohan Hedberg 	if (ev->status == 0)
18371da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18387d0db0a3SMarcel Holtmann 
1839b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1840b644ba33SJohan Hedberg 			(conn->type == ACL_LINK || conn->type == LE_LINK)) {
184137d9ef76SJohan Hedberg 		if (ev->status != 0)
184237d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
184337d9ef76SJohan Hedberg 		else
1844afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
184548264f06SJohan Hedberg 							conn->dst_type);
184637d9ef76SJohan Hedberg 	}
1847f7520543SJohan Hedberg 
184837d9ef76SJohan Hedberg 	if (ev->status == 0) {
18492950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
18501da177e4SLinus Torvalds 		hci_conn_del(conn);
185137d9ef76SJohan Hedberg 	}
18521da177e4SLinus Torvalds 
1853f7520543SJohan Hedberg unlock:
18541da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18551da177e4SLinus Torvalds }
18561da177e4SLinus Torvalds 
1857a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1858a9de9248SMarcel Holtmann {
1859a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1860a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1861a9de9248SMarcel Holtmann 
1862a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1863a9de9248SMarcel Holtmann 
1864a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1865a9de9248SMarcel Holtmann 
1866a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1867d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1868d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1869d7556e20SWaldemar Rymarkiewicz 
1870765c2a96SJohan Hedberg 	if (!ev->status) {
1871aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
187251a8efd7SJohan Hedberg 				test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1873d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
187419f8def0SWaldemar Rymarkiewicz 		} else {
1875a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1876765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
187719f8def0SWaldemar Rymarkiewicz 		}
18782a611692SJohan Hedberg 	} else {
1879744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
18802a611692SJohan Hedberg 	}
1881a9de9248SMarcel Holtmann 
188251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
188351a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1884a9de9248SMarcel Holtmann 
1885f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1886aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1887f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1888f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1889f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1890d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1891d7556e20SWaldemar Rymarkiewicz 									&cp);
1892f8558555SMarcel Holtmann 		} else {
1893f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1894f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1895f8558555SMarcel Holtmann 			hci_conn_put(conn);
1896f8558555SMarcel Holtmann 		}
1897052b30b0SMarcel Holtmann 	} else {
1898a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1899a9de9248SMarcel Holtmann 
1900052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1901052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1902052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1903052b30b0SMarcel Holtmann 	}
1904052b30b0SMarcel Holtmann 
190551a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1906a9de9248SMarcel Holtmann 		if (!ev->status) {
1907a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1908f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1909f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1910d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1911d7556e20SWaldemar Rymarkiewicz 									&cp);
1912a9de9248SMarcel Holtmann 		} else {
191351a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1914a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1915a9de9248SMarcel Holtmann 		}
1916a9de9248SMarcel Holtmann 	}
1917a9de9248SMarcel Holtmann 
1918d7556e20SWaldemar Rymarkiewicz unlock:
1919a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1920a9de9248SMarcel Holtmann }
1921a9de9248SMarcel Holtmann 
1922a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1923a9de9248SMarcel Holtmann {
1924127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1925127178d2SJohan Hedberg 	struct hci_conn *conn;
1926127178d2SJohan Hedberg 
1927a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1928a9de9248SMarcel Holtmann 
1929a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1930127178d2SJohan Hedberg 
1931127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1932127178d2SJohan Hedberg 
1933127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1934b644ba33SJohan Hedberg 
1935b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1936b644ba33SJohan Hedberg 		goto check_auth;
1937b644ba33SJohan Hedberg 
1938b644ba33SJohan Hedberg 	if (ev->status == 0)
1939b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1940b644ba33SJohan Hedberg 					strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1941b644ba33SJohan Hedberg 	else
1942b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1943b644ba33SJohan Hedberg 
1944b644ba33SJohan Hedberg check_auth:
194579c6c70cSJohan Hedberg 	if (!conn)
194679c6c70cSJohan Hedberg 		goto unlock;
194779c6c70cSJohan Hedberg 
194879c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
194979c6c70cSJohan Hedberg 		goto unlock;
195079c6c70cSJohan Hedberg 
195151a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1952127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1953127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1954127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1955127178d2SJohan Hedberg 	}
1956127178d2SJohan Hedberg 
195779c6c70cSJohan Hedberg unlock:
1958127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1959a9de9248SMarcel Holtmann }
1960a9de9248SMarcel Holtmann 
1961a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1962a9de9248SMarcel Holtmann {
1963a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1964a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1965a9de9248SMarcel Holtmann 
1966a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1967a9de9248SMarcel Holtmann 
1968a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1969a9de9248SMarcel Holtmann 
1970a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1971a9de9248SMarcel Holtmann 	if (conn) {
1972a9de9248SMarcel Holtmann 		if (!ev->status) {
1973ae293196SMarcel Holtmann 			if (ev->encrypt) {
1974ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1975ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1976a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1977da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1978ae293196SMarcel Holtmann 			} else
1979a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1980a9de9248SMarcel Holtmann 		}
1981a9de9248SMarcel Holtmann 
198251a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1983a9de9248SMarcel Holtmann 
1984f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1985f8558555SMarcel Holtmann 			if (!ev->status)
1986f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1987f8558555SMarcel Holtmann 
1988f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1989f8558555SMarcel Holtmann 			hci_conn_put(conn);
1990f8558555SMarcel Holtmann 		} else
1991a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1992a9de9248SMarcel Holtmann 	}
1993a9de9248SMarcel Holtmann 
1994a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1995a9de9248SMarcel Holtmann }
1996a9de9248SMarcel Holtmann 
1997a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1998a9de9248SMarcel Holtmann {
1999a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2000a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2001a9de9248SMarcel Holtmann 
2002a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2003a9de9248SMarcel Holtmann 
2004a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2005a9de9248SMarcel Holtmann 
2006a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2007a9de9248SMarcel Holtmann 	if (conn) {
2008a9de9248SMarcel Holtmann 		if (!ev->status)
2009a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2010a9de9248SMarcel Holtmann 
201151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2012a9de9248SMarcel Holtmann 
2013a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2014a9de9248SMarcel Holtmann 	}
2015a9de9248SMarcel Holtmann 
2016a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2017a9de9248SMarcel Holtmann }
2018a9de9248SMarcel Holtmann 
2019a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2020a9de9248SMarcel Holtmann {
2021a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2022a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2023a9de9248SMarcel Holtmann 
2024a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2025a9de9248SMarcel Holtmann 
2026a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2027a9de9248SMarcel Holtmann 
2028a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2029ccd556feSJohan Hedberg 	if (!conn)
2030ccd556feSJohan Hedberg 		goto unlock;
2031ccd556feSJohan Hedberg 
2032769be974SMarcel Holtmann 	if (!ev->status)
2033a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2034a9de9248SMarcel Holtmann 
2035ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2036ccd556feSJohan Hedberg 		goto unlock;
2037ccd556feSJohan Hedberg 
2038ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2039769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2040769be974SMarcel Holtmann 		cp.handle = ev->handle;
2041769be974SMarcel Holtmann 		cp.page = 0x01;
2042ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2043769be974SMarcel Holtmann 							sizeof(cp), &cp);
2044392599b9SJohan Hedberg 		goto unlock;
2045392599b9SJohan Hedberg 	}
2046392599b9SJohan Hedberg 
2047127178d2SJohan Hedberg 	if (!ev->status) {
2048127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2049127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2050127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2051127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2052127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2053b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2054b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2055b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2056b644ba33SJohan Hedberg 						conn->dev_class);
2057392599b9SJohan Hedberg 
2058127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2059769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2060769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2061769be974SMarcel Holtmann 		hci_conn_put(conn);
2062769be974SMarcel Holtmann 	}
2063769be974SMarcel Holtmann 
2064ccd556feSJohan Hedberg unlock:
2065a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2066a9de9248SMarcel Holtmann }
2067a9de9248SMarcel Holtmann 
2068a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2069a9de9248SMarcel Holtmann {
2070a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2071a9de9248SMarcel Holtmann }
2072a9de9248SMarcel Holtmann 
2073a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2074a9de9248SMarcel Holtmann {
2075a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2076a9de9248SMarcel Holtmann }
2077a9de9248SMarcel Holtmann 
2078a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2079a9de9248SMarcel Holtmann {
2080a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2081a9de9248SMarcel Holtmann 	__u16 opcode;
2082a9de9248SMarcel Holtmann 
2083a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2084a9de9248SMarcel Holtmann 
2085a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2086a9de9248SMarcel Holtmann 
2087a9de9248SMarcel Holtmann 	switch (opcode) {
2088a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2089a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2090a9de9248SMarcel Holtmann 		break;
2091a9de9248SMarcel Holtmann 
2092a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2093a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2094a9de9248SMarcel Holtmann 		break;
2095a9de9248SMarcel Holtmann 
2096a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2097a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2098a9de9248SMarcel Holtmann 		break;
2099a9de9248SMarcel Holtmann 
2100a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2101a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2102a9de9248SMarcel Holtmann 		break;
2103a9de9248SMarcel Holtmann 
2104e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2105e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2106e4e8e37cSMarcel Holtmann 		break;
2107e4e8e37cSMarcel Holtmann 
2108a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2109a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2110a9de9248SMarcel Holtmann 		break;
2111a9de9248SMarcel Holtmann 
2112e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2113e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2114e4e8e37cSMarcel Holtmann 		break;
2115e4e8e37cSMarcel Holtmann 
2116e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2117e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2118e4e8e37cSMarcel Holtmann 		break;
2119e4e8e37cSMarcel Holtmann 
2120a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2121a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2122a9de9248SMarcel Holtmann 		break;
2123a9de9248SMarcel Holtmann 
2124a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2125a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2126a9de9248SMarcel Holtmann 		break;
2127a9de9248SMarcel Holtmann 
2128a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2129a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2130a9de9248SMarcel Holtmann 		break;
2131a9de9248SMarcel Holtmann 
2132a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2133a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2134a9de9248SMarcel Holtmann 		break;
2135a9de9248SMarcel Holtmann 
2136a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2137a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2138a9de9248SMarcel Holtmann 		break;
2139a9de9248SMarcel Holtmann 
2140a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2141a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2142a9de9248SMarcel Holtmann 		break;
2143a9de9248SMarcel Holtmann 
2144a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2145a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2146a9de9248SMarcel Holtmann 		break;
2147a9de9248SMarcel Holtmann 
2148a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2149a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2150a9de9248SMarcel Holtmann 		break;
2151a9de9248SMarcel Holtmann 
2152a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2153a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2154a9de9248SMarcel Holtmann 		break;
2155a9de9248SMarcel Holtmann 
2156a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2157a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2158a9de9248SMarcel Holtmann 		break;
2159a9de9248SMarcel Holtmann 
2160a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2161a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2162a9de9248SMarcel Holtmann 		break;
2163a9de9248SMarcel Holtmann 
2164333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
2165333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
2166333140b5SMarcel Holtmann 		break;
2167333140b5SMarcel Holtmann 
2168333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2169333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2170333140b5SMarcel Holtmann 		break;
2171333140b5SMarcel Holtmann 
2172a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2173a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2174a9de9248SMarcel Holtmann 		break;
2175a9de9248SMarcel Holtmann 
2176a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2177a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2178a9de9248SMarcel Holtmann 		break;
2179a9de9248SMarcel Holtmann 
2180a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2181a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2182a9de9248SMarcel Holtmann 		break;
2183a9de9248SMarcel Holtmann 
2184971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2185971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2186971e3a4bSAndre Guedes 		break;
2187971e3a4bSAndre Guedes 
2188a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2189a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2190a9de9248SMarcel Holtmann 		break;
2191a9de9248SMarcel Holtmann 
2192a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2193a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2194a9de9248SMarcel Holtmann 		break;
2195a9de9248SMarcel Holtmann 
2196350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2197350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2198350ee4cfSAndrei Emeltchenko 		break;
2199350ee4cfSAndrei Emeltchenko 
220023bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
220123bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
220223bb5763SJohan Hedberg 		break;
220323bb5763SJohan Hedberg 
22041e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22051e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22061e89cffbSAndrei Emeltchenko 		break;
22071e89cffbSAndrei Emeltchenko 
2208928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2209928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2210928abaa7SAndrei Emeltchenko 		break;
2211928abaa7SAndrei Emeltchenko 
2212b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2213b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2214b0916ea0SJohan Hedberg 		break;
2215b0916ea0SJohan Hedberg 
2216d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2217d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2218d5859e22SJohan Hedberg 		break;
2219d5859e22SJohan Hedberg 
2220d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2221d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2222d5859e22SJohan Hedberg 		break;
2223d5859e22SJohan Hedberg 
2224d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2225d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2226d5859e22SJohan Hedberg 		break;
2227d5859e22SJohan Hedberg 
2228d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2229d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2230d5859e22SJohan Hedberg 		break;
2231d5859e22SJohan Hedberg 
2232980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2233980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2234980e1a53SJohan Hedberg 		break;
2235980e1a53SJohan Hedberg 
2236980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2237980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2238980e1a53SJohan Hedberg 		break;
2239980e1a53SJohan Hedberg 
2240c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2241c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2242c35938b2SSzymon Janc 		break;
2243c35938b2SSzymon Janc 
22446ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22456ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22466ed58ec5SVille Tervo 		break;
22476ed58ec5SVille Tervo 
2248a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2249a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2250a5c29683SJohan Hedberg 		break;
2251a5c29683SJohan Hedberg 
2252a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2253a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2254a5c29683SJohan Hedberg 		break;
2255a5c29683SJohan Hedberg 
22561143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
22571143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
22581143d458SBrian Gix 		break;
22591143d458SBrian Gix 
22601143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
22611143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
226207f7fa5dSAndre Guedes 
226307f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
226407f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
22651143d458SBrian Gix 		break;
22661143d458SBrian Gix 
2267eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2268eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2269eb9d91f5SAndre Guedes 		break;
2270eb9d91f5SAndre Guedes 
2271a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2272a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2273a7a595f6SVinicius Costa Gomes 		break;
2274a7a595f6SVinicius Costa Gomes 
2275a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2276a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2277a7a595f6SVinicius Costa Gomes 		break;
2278a7a595f6SVinicius Costa Gomes 
2279f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2280f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2281f9b49306SAndre Guedes 		break;
2282f9b49306SAndre Guedes 
2283a9de9248SMarcel Holtmann 	default:
2284a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2285a9de9248SMarcel Holtmann 		break;
2286a9de9248SMarcel Holtmann 	}
2287a9de9248SMarcel Holtmann 
22886bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
22896bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
22906bd32326SVille Tervo 
2291a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2292a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2293a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2294c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2295a9de9248SMarcel Holtmann 	}
2296a9de9248SMarcel Holtmann }
2297a9de9248SMarcel Holtmann 
2298a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2299a9de9248SMarcel Holtmann {
2300a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2301a9de9248SMarcel Holtmann 	__u16 opcode;
2302a9de9248SMarcel Holtmann 
2303a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2304a9de9248SMarcel Holtmann 
2305a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2306a9de9248SMarcel Holtmann 
2307a9de9248SMarcel Holtmann 	switch (opcode) {
2308a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2309a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2310a9de9248SMarcel Holtmann 		break;
2311a9de9248SMarcel Holtmann 
2312a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2313a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2314a9de9248SMarcel Holtmann 		break;
2315a9de9248SMarcel Holtmann 
2316a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2317a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2318a9de9248SMarcel Holtmann 		break;
2319a9de9248SMarcel Holtmann 
2320f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2321f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2322f8558555SMarcel Holtmann 		break;
2323f8558555SMarcel Holtmann 
2324f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2325f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2326f8558555SMarcel Holtmann 		break;
2327f8558555SMarcel Holtmann 
2328a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2329a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2330a9de9248SMarcel Holtmann 		break;
2331a9de9248SMarcel Holtmann 
2332769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2333769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2334769be974SMarcel Holtmann 		break;
2335769be974SMarcel Holtmann 
2336769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2337769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2338769be974SMarcel Holtmann 		break;
2339769be974SMarcel Holtmann 
2340a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2341a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2342a9de9248SMarcel Holtmann 		break;
2343a9de9248SMarcel Holtmann 
2344a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2345a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2346a9de9248SMarcel Holtmann 		break;
2347a9de9248SMarcel Holtmann 
2348a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2349a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2350a9de9248SMarcel Holtmann 		break;
2351a9de9248SMarcel Holtmann 
23528962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
23538962ee74SJohan Hedberg 		if (ev->status != 0)
235437d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
23558962ee74SJohan Hedberg 		break;
23568962ee74SJohan Hedberg 
2357fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2358fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2359fcd89c09SVille Tervo 		break;
2360fcd89c09SVille Tervo 
2361a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2362a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2363a7a595f6SVinicius Costa Gomes 		break;
2364a7a595f6SVinicius Costa Gomes 
2365a9de9248SMarcel Holtmann 	default:
2366a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2367a9de9248SMarcel Holtmann 		break;
2368a9de9248SMarcel Holtmann 	}
2369a9de9248SMarcel Holtmann 
23706bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23716bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23726bd32326SVille Tervo 
237310572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2374a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2375a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2376c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2377a9de9248SMarcel Holtmann 	}
2378a9de9248SMarcel Holtmann }
2379a9de9248SMarcel Holtmann 
2380a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2381a9de9248SMarcel Holtmann {
2382a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2383a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2384a9de9248SMarcel Holtmann 
2385a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2386a9de9248SMarcel Holtmann 
2387a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2388a9de9248SMarcel Holtmann 
2389a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2390a9de9248SMarcel Holtmann 	if (conn) {
2391a9de9248SMarcel Holtmann 		if (!ev->status) {
2392a9de9248SMarcel Holtmann 			if (ev->role)
2393a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2394a9de9248SMarcel Holtmann 			else
2395a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2396a9de9248SMarcel Holtmann 		}
2397a9de9248SMarcel Holtmann 
239851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2399a9de9248SMarcel Holtmann 
2400a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2401a9de9248SMarcel Holtmann 	}
2402a9de9248SMarcel Holtmann 
2403a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2404a9de9248SMarcel Holtmann }
2405a9de9248SMarcel Holtmann 
24061da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24071da177e4SLinus Torvalds {
2408a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24091da177e4SLinus Torvalds 	int i;
24101da177e4SLinus Torvalds 
241132ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
241232ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
241332ac5b9bSAndrei Emeltchenko 		return;
241432ac5b9bSAndrei Emeltchenko 	}
241532ac5b9bSAndrei Emeltchenko 
2416c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2417c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24181da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24191da177e4SLinus Torvalds 		return;
24201da177e4SLinus Torvalds 	}
24211da177e4SLinus Torvalds 
2422c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2423c5993de8SAndrei Emeltchenko 
2424613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2425613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24261da177e4SLinus Torvalds 		struct hci_conn *conn;
24271da177e4SLinus Torvalds 		__u16  handle, count;
24281da177e4SLinus Torvalds 
2429613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2430613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24311da177e4SLinus Torvalds 
24321da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2433f4280918SAndrei Emeltchenko 		if (!conn)
2434f4280918SAndrei Emeltchenko 			continue;
2435f4280918SAndrei Emeltchenko 
24361da177e4SLinus Torvalds 		conn->sent -= count;
24371da177e4SLinus Torvalds 
2438f4280918SAndrei Emeltchenko 		switch (conn->type) {
2439f4280918SAndrei Emeltchenko 		case ACL_LINK:
244070f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
244170f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24421da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2443f4280918SAndrei Emeltchenko 			break;
2444f4280918SAndrei Emeltchenko 
2445f4280918SAndrei Emeltchenko 		case LE_LINK:
24466ed58ec5SVille Tervo 			if (hdev->le_pkts) {
24476ed58ec5SVille Tervo 				hdev->le_cnt += count;
24486ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
24496ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
24506ed58ec5SVille Tervo 			} else {
24516ed58ec5SVille Tervo 				hdev->acl_cnt += count;
24526ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
24536ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
24546ed58ec5SVille Tervo 			}
2455f4280918SAndrei Emeltchenko 			break;
2456f4280918SAndrei Emeltchenko 
2457f4280918SAndrei Emeltchenko 		case SCO_LINK:
245870f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
245970f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
24605b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2461f4280918SAndrei Emeltchenko 			break;
2462f4280918SAndrei Emeltchenko 
2463f4280918SAndrei Emeltchenko 		default:
2464f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2465f4280918SAndrei Emeltchenko 			break;
24661da177e4SLinus Torvalds 		}
24671da177e4SLinus Torvalds 	}
2468a9de9248SMarcel Holtmann 
24693eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
24701da177e4SLinus Torvalds }
24711da177e4SLinus Torvalds 
247225e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
247325e89e99SAndrei Emeltchenko 							struct sk_buff *skb)
247425e89e99SAndrei Emeltchenko {
247525e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
247625e89e99SAndrei Emeltchenko 	int i;
247725e89e99SAndrei Emeltchenko 
247825e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
247925e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
248025e89e99SAndrei Emeltchenko 		return;
248125e89e99SAndrei Emeltchenko 	}
248225e89e99SAndrei Emeltchenko 
248325e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
248425e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
248525e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
248625e89e99SAndrei Emeltchenko 		return;
248725e89e99SAndrei Emeltchenko 	}
248825e89e99SAndrei Emeltchenko 
248925e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
249025e89e99SAndrei Emeltchenko 								ev->num_hndl);
249125e89e99SAndrei Emeltchenko 
249225e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
249325e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
249425e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
249525e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
249625e89e99SAndrei Emeltchenko 
249725e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
249825e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
249925e89e99SAndrei Emeltchenko 
250025e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
250125e89e99SAndrei Emeltchenko 		if (!conn)
250225e89e99SAndrei Emeltchenko 			continue;
250325e89e99SAndrei Emeltchenko 
250425e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
250525e89e99SAndrei Emeltchenko 
250625e89e99SAndrei Emeltchenko 		switch (conn->type) {
250725e89e99SAndrei Emeltchenko 		case ACL_LINK:
250825e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
250925e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
251025e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
251125e89e99SAndrei Emeltchenko 			break;
251225e89e99SAndrei Emeltchenko 
251325e89e99SAndrei Emeltchenko 		default:
251425e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
251525e89e99SAndrei Emeltchenko 			break;
251625e89e99SAndrei Emeltchenko 		}
251725e89e99SAndrei Emeltchenko 	}
251825e89e99SAndrei Emeltchenko 
251925e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
252025e89e99SAndrei Emeltchenko }
252125e89e99SAndrei Emeltchenko 
252204837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25231da177e4SLinus Torvalds {
2524a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
252504837f64SMarcel Holtmann 	struct hci_conn *conn;
25261da177e4SLinus Torvalds 
25271da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
25281da177e4SLinus Torvalds 
25291da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25301da177e4SLinus Torvalds 
253104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
253204837f64SMarcel Holtmann 	if (conn) {
253304837f64SMarcel Holtmann 		conn->mode = ev->mode;
253404837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
253504837f64SMarcel Holtmann 
253651a8efd7SJohan Hedberg 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
253704837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
253858a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
253904837f64SMarcel Holtmann 			else
254058a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
254104837f64SMarcel Holtmann 		}
2542e73439d8SMarcel Holtmann 
254351a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2544e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
254504837f64SMarcel Holtmann 	}
254604837f64SMarcel Holtmann 
254704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
254804837f64SMarcel Holtmann }
254904837f64SMarcel Holtmann 
25501da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25511da177e4SLinus Torvalds {
2552052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2553052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2554052b30b0SMarcel Holtmann 
2555a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2556052b30b0SMarcel Holtmann 
2557052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2558052b30b0SMarcel Holtmann 
2559052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2560b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2561b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2562b6f98044SWaldemar Rymarkiewicz 
2563b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2564052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2565052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2566052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2567052b30b0SMarcel Holtmann 	}
2568052b30b0SMarcel Holtmann 
2569a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
257003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
257103b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2572a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2573a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2574a770bb5aSWaldemar Rymarkiewicz 
2575a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2576a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2577a770bb5aSWaldemar Rymarkiewicz 		else
2578a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2579a770bb5aSWaldemar Rymarkiewicz 
2580744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2581a770bb5aSWaldemar Rymarkiewicz 	}
2582980e1a53SJohan Hedberg 
2583b6f98044SWaldemar Rymarkiewicz unlock:
2584052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
25851da177e4SLinus Torvalds }
25861da177e4SLinus Torvalds 
25871da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25881da177e4SLinus Torvalds {
258955ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
259055ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
259155ed8ca1SJohan Hedberg 	struct hci_conn *conn;
259255ed8ca1SJohan Hedberg 	struct link_key *key;
259355ed8ca1SJohan Hedberg 
2594a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
259555ed8ca1SJohan Hedberg 
2596a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
259755ed8ca1SJohan Hedberg 		return;
259855ed8ca1SJohan Hedberg 
259955ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
260055ed8ca1SJohan Hedberg 
260155ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
260255ed8ca1SJohan Hedberg 	if (!key) {
260355ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
260455ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
260555ed8ca1SJohan Hedberg 		goto not_found;
260655ed8ca1SJohan Hedberg 	}
260755ed8ca1SJohan Hedberg 
260855ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
260955ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
261055ed8ca1SJohan Hedberg 
2611a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2612b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
261355ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
261455ed8ca1SJohan Hedberg 		goto not_found;
261555ed8ca1SJohan Hedberg 	}
261655ed8ca1SJohan Hedberg 
261755ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
261860b83f57SWaldemar Rymarkiewicz 	if (conn) {
261960b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
262060b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
262160b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
262255ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
262355ed8ca1SJohan Hedberg 			goto not_found;
262455ed8ca1SJohan Hedberg 		}
262555ed8ca1SJohan Hedberg 
262660b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
262760b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
262860b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
262960b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
263060b83f57SWaldemar Rymarkiewicz 			goto not_found;
263160b83f57SWaldemar Rymarkiewicz 		}
263260b83f57SWaldemar Rymarkiewicz 
263360b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
263460b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
263560b83f57SWaldemar Rymarkiewicz 	}
263660b83f57SWaldemar Rymarkiewicz 
263755ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
263855ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
263955ed8ca1SJohan Hedberg 
264055ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
264155ed8ca1SJohan Hedberg 
264255ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
264355ed8ca1SJohan Hedberg 
264455ed8ca1SJohan Hedberg 	return;
264555ed8ca1SJohan Hedberg 
264655ed8ca1SJohan Hedberg not_found:
264755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
264855ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
26491da177e4SLinus Torvalds }
26501da177e4SLinus Torvalds 
26511da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
26521da177e4SLinus Torvalds {
2653052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2654052b30b0SMarcel Holtmann 	struct hci_conn *conn;
265555ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2656052b30b0SMarcel Holtmann 
2657a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2658052b30b0SMarcel Holtmann 
2659052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2660052b30b0SMarcel Holtmann 
2661052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2662052b30b0SMarcel Holtmann 	if (conn) {
2663052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2664052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2665980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
266613d39315SWaldemar Rymarkiewicz 
266713d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
266813d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
266913d39315SWaldemar Rymarkiewicz 
2670052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2671052b30b0SMarcel Holtmann 	}
2672052b30b0SMarcel Holtmann 
2673a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2674d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
267555ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
267655ed8ca1SJohan Hedberg 
2677052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26781da177e4SLinus Torvalds }
26791da177e4SLinus Torvalds 
268004837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
268104837f64SMarcel Holtmann {
2682a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
268304837f64SMarcel Holtmann 	struct hci_conn *conn;
268404837f64SMarcel Holtmann 
268504837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
268604837f64SMarcel Holtmann 
268704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
268804837f64SMarcel Holtmann 
268904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
26901da177e4SLinus Torvalds 	if (conn && !ev->status) {
26911da177e4SLinus Torvalds 		struct inquiry_entry *ie;
26921da177e4SLinus Torvalds 
2693cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2694cc11b9c1SAndrei Emeltchenko 		if (ie) {
26951da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
26961da177e4SLinus Torvalds 			ie->timestamp = jiffies;
26971da177e4SLinus Torvalds 		}
26981da177e4SLinus Torvalds 	}
26991da177e4SLinus Torvalds 
27001da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27011da177e4SLinus Torvalds }
27021da177e4SLinus Torvalds 
2703a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2704a8746417SMarcel Holtmann {
2705a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2706a8746417SMarcel Holtmann 	struct hci_conn *conn;
2707a8746417SMarcel Holtmann 
2708a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2709a8746417SMarcel Holtmann 
2710a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2711a8746417SMarcel Holtmann 
2712a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2713a8746417SMarcel Holtmann 	if (conn && !ev->status)
2714a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2715a8746417SMarcel Holtmann 
2716a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2717a8746417SMarcel Holtmann }
2718a8746417SMarcel Holtmann 
271985a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
272085a1e930SMarcel Holtmann {
2721a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
272285a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
272385a1e930SMarcel Holtmann 
272485a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
272585a1e930SMarcel Holtmann 
272685a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
272785a1e930SMarcel Holtmann 
2728cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2729cc11b9c1SAndrei Emeltchenko 	if (ie) {
273085a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
273185a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
273285a1e930SMarcel Holtmann 	}
273385a1e930SMarcel Holtmann 
273485a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
273585a1e930SMarcel Holtmann }
273685a1e930SMarcel Holtmann 
2737a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2738a9de9248SMarcel Holtmann {
2739a9de9248SMarcel Holtmann 	struct inquiry_data data;
2740a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
27413175405bSJohan Hedberg 	bool name_known;
2742a9de9248SMarcel Holtmann 
2743a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2744a9de9248SMarcel Holtmann 
2745a9de9248SMarcel Holtmann 	if (!num_rsp)
2746a9de9248SMarcel Holtmann 		return;
2747a9de9248SMarcel Holtmann 
2748a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2749a9de9248SMarcel Holtmann 
2750a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2751138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2752138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2753a9de9248SMarcel Holtmann 
2754e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2755a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2756a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2757a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2758a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2759a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2760a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2761a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
276241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27633175405bSJohan Hedberg 
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 	} else {
2771a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2772a9de9248SMarcel Holtmann 
2773e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2774a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2775a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2776a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2777a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2778a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2779a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2780a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
278141a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27823175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27833175405bSJohan Hedberg 								false);
278448264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2785e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27867d262f86SAndre Guedes 						!name_known, NULL, 0);
2787a9de9248SMarcel Holtmann 		}
2788a9de9248SMarcel Holtmann 	}
2789a9de9248SMarcel Holtmann 
2790a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2791a9de9248SMarcel Holtmann }
2792a9de9248SMarcel Holtmann 
2793a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2794a9de9248SMarcel Holtmann {
279541a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
279641a96212SMarcel Holtmann 	struct hci_conn *conn;
279741a96212SMarcel Holtmann 
2798a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
279941a96212SMarcel Holtmann 
280041a96212SMarcel Holtmann 	hci_dev_lock(hdev);
280141a96212SMarcel Holtmann 
280241a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2803ccd556feSJohan Hedberg 	if (!conn)
2804ccd556feSJohan Hedberg 		goto unlock;
2805ccd556feSJohan Hedberg 
2806769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
280741a96212SMarcel Holtmann 		struct inquiry_entry *ie;
280841a96212SMarcel Holtmann 
2809cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2810cc11b9c1SAndrei Emeltchenko 		if (ie)
281141a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
281241a96212SMarcel Holtmann 
281358a681efSJohan Hedberg 		if (ev->features[0] & 0x01)
281458a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
281541a96212SMarcel Holtmann 	}
281641a96212SMarcel Holtmann 
2817ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2818ccd556feSJohan Hedberg 		goto unlock;
2819ccd556feSJohan Hedberg 
2820127178d2SJohan Hedberg 	if (!ev->status) {
2821127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2822127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2823127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2824127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2825127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2826b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2827b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2828b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2829b644ba33SJohan Hedberg 						conn->dev_class);
2830392599b9SJohan Hedberg 
2831127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2832769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2833769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2834769be974SMarcel Holtmann 		hci_conn_put(conn);
2835769be974SMarcel Holtmann 	}
2836769be974SMarcel Holtmann 
2837ccd556feSJohan Hedberg unlock:
283841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2839a9de9248SMarcel Holtmann }
2840a9de9248SMarcel Holtmann 
2841a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2842a9de9248SMarcel Holtmann {
2843b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2844b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2845b6a0dc82SMarcel Holtmann 
2846b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2847b6a0dc82SMarcel Holtmann 
2848b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2849b6a0dc82SMarcel Holtmann 
2850b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
28519dc0a3afSMarcel Holtmann 	if (!conn) {
28529dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
28539dc0a3afSMarcel Holtmann 			goto unlock;
28549dc0a3afSMarcel Holtmann 
28559dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2856b6a0dc82SMarcel Holtmann 		if (!conn)
2857b6a0dc82SMarcel Holtmann 			goto unlock;
2858b6a0dc82SMarcel Holtmann 
28599dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
28609dc0a3afSMarcel Holtmann 	}
28619dc0a3afSMarcel Holtmann 
2862732547f9SMarcel Holtmann 	switch (ev->status) {
2863732547f9SMarcel Holtmann 	case 0x00:
2864732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2865732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2866732547f9SMarcel Holtmann 
28679eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2868732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2869732547f9SMarcel Holtmann 		break;
2870732547f9SMarcel Holtmann 
2871705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2872732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
28731038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2874732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2875732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2876efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2877efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2878efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2879efc7688bSMarcel Holtmann 			goto unlock;
2880efc7688bSMarcel Holtmann 		}
2881732547f9SMarcel Holtmann 		/* fall through */
2882efc7688bSMarcel Holtmann 
2883732547f9SMarcel Holtmann 	default:
2884b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2885732547f9SMarcel Holtmann 		break;
2886732547f9SMarcel Holtmann 	}
2887b6a0dc82SMarcel Holtmann 
2888b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2889b6a0dc82SMarcel Holtmann 	if (ev->status)
2890b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2891b6a0dc82SMarcel Holtmann 
2892b6a0dc82SMarcel Holtmann unlock:
2893b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2894a9de9248SMarcel Holtmann }
2895a9de9248SMarcel Holtmann 
2896a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2897a9de9248SMarcel Holtmann {
2898a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2899a9de9248SMarcel Holtmann }
2900a9de9248SMarcel Holtmann 
290104837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
290204837f64SMarcel Holtmann {
2903a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
290404837f64SMarcel Holtmann 
290504837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
290604837f64SMarcel Holtmann }
290704837f64SMarcel Holtmann 
2908a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2909a9de9248SMarcel Holtmann {
2910a9de9248SMarcel Holtmann 	struct inquiry_data data;
2911a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2912a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2913a9de9248SMarcel Holtmann 
2914a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2915a9de9248SMarcel Holtmann 
2916a9de9248SMarcel Holtmann 	if (!num_rsp)
2917a9de9248SMarcel Holtmann 		return;
2918a9de9248SMarcel Holtmann 
2919a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2920a9de9248SMarcel Holtmann 
2921e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2922561aafbcSJohan Hedberg 		bool name_known;
2923561aafbcSJohan Hedberg 
2924a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2925a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2926a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2927a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2928a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2929a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2930a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
293141a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2932561aafbcSJohan Hedberg 
2933a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29344ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29354ddb1930SJohan Hedberg 							sizeof(info->data),
29364ddb1930SJohan Hedberg 							EIR_NAME_COMPLETE);
2937561aafbcSJohan Hedberg 		else
2938561aafbcSJohan Hedberg 			name_known = true;
2939561aafbcSJohan Hedberg 
29403175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known);
294148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2942561aafbcSJohan Hedberg 						info->dev_class, info->rssi,
29437d262f86SAndre Guedes 						!name_known, info->data,
29447d262f86SAndre Guedes 						sizeof(info->data));
2945a9de9248SMarcel Holtmann 	}
2946a9de9248SMarcel Holtmann 
2947a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2948a9de9248SMarcel Holtmann }
2949a9de9248SMarcel Holtmann 
295017fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
295117fa4b9dSJohan Hedberg {
295217fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
295317fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
295417fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
295517fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
295617fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
295717fa4b9dSJohan Hedberg 			return 0x02;
295817fa4b9dSJohan Hedberg 		else
295917fa4b9dSJohan Hedberg 			return 0x03;
296017fa4b9dSJohan Hedberg 	}
296117fa4b9dSJohan Hedberg 
296217fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
296317fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
296458797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
296517fa4b9dSJohan Hedberg 
296617fa4b9dSJohan Hedberg 	return conn->auth_type;
296717fa4b9dSJohan Hedberg }
296817fa4b9dSJohan Hedberg 
29690493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29700493684eSMarcel Holtmann {
29710493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
29720493684eSMarcel Holtmann 	struct hci_conn *conn;
29730493684eSMarcel Holtmann 
29740493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
29750493684eSMarcel Holtmann 
29760493684eSMarcel Holtmann 	hci_dev_lock(hdev);
29770493684eSMarcel Holtmann 
29780493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
297903b555e1SJohan Hedberg 	if (!conn)
298003b555e1SJohan Hedberg 		goto unlock;
298103b555e1SJohan Hedberg 
29820493684eSMarcel Holtmann 	hci_conn_hold(conn);
29830493684eSMarcel Holtmann 
2984a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
298503b555e1SJohan Hedberg 		goto unlock;
298603b555e1SJohan Hedberg 
2987a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
298803b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
298917fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
299017fa4b9dSJohan Hedberg 
299117fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
29927a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
29937a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
29947a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
29957a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
29967cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
29977cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
299817fa4b9dSJohan Hedberg 
299958a681efSJohan Hedberg 		if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
3000ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
3001ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3002ce85ee13SSzymon Janc 		else
3003ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3004ce85ee13SSzymon Janc 
300517fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
300617fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
300703b555e1SJohan Hedberg 	} else {
300803b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
300903b555e1SJohan Hedberg 
301003b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30119f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
301203b555e1SJohan Hedberg 
301303b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
301403b555e1SJohan Hedberg 							sizeof(cp), &cp);
301503b555e1SJohan Hedberg 	}
301603b555e1SJohan Hedberg 
301703b555e1SJohan Hedberg unlock:
301803b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
301903b555e1SJohan Hedberg }
302003b555e1SJohan Hedberg 
302103b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
302203b555e1SJohan Hedberg {
302303b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
302403b555e1SJohan Hedberg 	struct hci_conn *conn;
302503b555e1SJohan Hedberg 
302603b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
302703b555e1SJohan Hedberg 
302803b555e1SJohan Hedberg 	hci_dev_lock(hdev);
302903b555e1SJohan Hedberg 
303003b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
303103b555e1SJohan Hedberg 	if (!conn)
303203b555e1SJohan Hedberg 		goto unlock;
303303b555e1SJohan Hedberg 
303403b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
303503b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
303658a681efSJohan Hedberg 	if (ev->oob_data)
303758a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
303803b555e1SJohan Hedberg 
303903b555e1SJohan Hedberg unlock:
30400493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
30410493684eSMarcel Holtmann }
30420493684eSMarcel Holtmann 
3043a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3044a5c29683SJohan Hedberg 							struct sk_buff *skb)
3045a5c29683SJohan Hedberg {
3046a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
304755bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
30487a828908SJohan Hedberg 	struct hci_conn *conn;
3049a5c29683SJohan Hedberg 
3050a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3051a5c29683SJohan Hedberg 
3052a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3053a5c29683SJohan Hedberg 
3054a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
30557a828908SJohan Hedberg 		goto unlock;
30567a828908SJohan Hedberg 
30577a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
30587a828908SJohan Hedberg 	if (!conn)
30597a828908SJohan Hedberg 		goto unlock;
30607a828908SJohan Hedberg 
30617a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
30627a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
30637a828908SJohan Hedberg 
30647a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
30657a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
30667a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
30677a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
30687a828908SJohan Hedberg 	 * bit set. */
30697a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
30707a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
30717a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
30727a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
30737a828908SJohan Hedberg 		goto unlock;
30747a828908SJohan Hedberg 	}
30757a828908SJohan Hedberg 
30767a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
30777a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
30787a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
307955bc1a37SJohan Hedberg 
308055bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
308155bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
308255bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
308351a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
308455bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
308555bc1a37SJohan Hedberg 			confirm_hint = 1;
308655bc1a37SJohan Hedberg 			goto confirm;
308755bc1a37SJohan Hedberg 		}
308855bc1a37SJohan Hedberg 
30899f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
30909f61656aSJohan Hedberg 						hdev->auto_accept_delay);
30919f61656aSJohan Hedberg 
30929f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
30939f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
30949f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
30959f61656aSJohan Hedberg 			goto unlock;
30969f61656aSJohan Hedberg 		}
30979f61656aSJohan Hedberg 
30987a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
30997a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
31007a828908SJohan Hedberg 		goto unlock;
31017a828908SJohan Hedberg 	}
31027a828908SJohan Hedberg 
310355bc1a37SJohan Hedberg confirm:
3104744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
310555bc1a37SJohan Hedberg 								confirm_hint);
3106a5c29683SJohan Hedberg 
31077a828908SJohan Hedberg unlock:
3108a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3109a5c29683SJohan Hedberg }
3110a5c29683SJohan Hedberg 
31111143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
31121143d458SBrian Gix 							struct sk_buff *skb)
31131143d458SBrian Gix {
31141143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
31151143d458SBrian Gix 
31161143d458SBrian Gix 	BT_DBG("%s", hdev->name);
31171143d458SBrian Gix 
31181143d458SBrian Gix 	hci_dev_lock(hdev);
31191143d458SBrian Gix 
3120a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
31211143d458SBrian Gix 		mgmt_user_passkey_request(hdev, &ev->bdaddr);
31221143d458SBrian Gix 
31231143d458SBrian Gix 	hci_dev_unlock(hdev);
31241143d458SBrian Gix }
31251143d458SBrian Gix 
31260493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
31270493684eSMarcel Holtmann {
31280493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
31290493684eSMarcel Holtmann 	struct hci_conn *conn;
31300493684eSMarcel Holtmann 
31310493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31320493684eSMarcel Holtmann 
31330493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31340493684eSMarcel Holtmann 
31350493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31362a611692SJohan Hedberg 	if (!conn)
31372a611692SJohan Hedberg 		goto unlock;
31382a611692SJohan Hedberg 
31392a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
31402a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
31412a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
31422a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
31432a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
314451a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3145744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
31462a611692SJohan Hedberg 
31470493684eSMarcel Holtmann 	hci_conn_put(conn);
31480493684eSMarcel Holtmann 
31492a611692SJohan Hedberg unlock:
31500493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31510493684eSMarcel Holtmann }
31520493684eSMarcel Holtmann 
315341a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
315441a96212SMarcel Holtmann {
315541a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
315641a96212SMarcel Holtmann 	struct inquiry_entry *ie;
315741a96212SMarcel Holtmann 
315841a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
315941a96212SMarcel Holtmann 
316041a96212SMarcel Holtmann 	hci_dev_lock(hdev);
316141a96212SMarcel Holtmann 
3162cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3163cc11b9c1SAndrei Emeltchenko 	if (ie)
316441a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
316541a96212SMarcel Holtmann 
316641a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
316741a96212SMarcel Holtmann }
316841a96212SMarcel Holtmann 
31692763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
31702763eda6SSzymon Janc 							struct sk_buff *skb)
31712763eda6SSzymon Janc {
31722763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
31732763eda6SSzymon Janc 	struct oob_data *data;
31742763eda6SSzymon Janc 
31752763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
31762763eda6SSzymon Janc 
31772763eda6SSzymon Janc 	hci_dev_lock(hdev);
31782763eda6SSzymon Janc 
3179a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3180e1ba1f15SSzymon Janc 		goto unlock;
3181e1ba1f15SSzymon Janc 
31822763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
31832763eda6SSzymon Janc 	if (data) {
31842763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
31852763eda6SSzymon Janc 
31862763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31872763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
31882763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
31892763eda6SSzymon Janc 
31902763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
31912763eda6SSzymon Janc 									&cp);
31922763eda6SSzymon Janc 	} else {
31932763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
31942763eda6SSzymon Janc 
31952763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31962763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
31972763eda6SSzymon Janc 									&cp);
31982763eda6SSzymon Janc 	}
31992763eda6SSzymon Janc 
3200e1ba1f15SSzymon Janc unlock:
32012763eda6SSzymon Janc 	hci_dev_unlock(hdev);
32022763eda6SSzymon Janc }
32032763eda6SSzymon Janc 
3204fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3205fcd89c09SVille Tervo {
3206fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3207fcd89c09SVille Tervo 	struct hci_conn *conn;
3208fcd89c09SVille Tervo 
3209fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3210fcd89c09SVille Tervo 
3211fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3212fcd89c09SVille Tervo 
3213fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3214b62f328bSVille Tervo 	if (!conn) {
3215b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3216b62f328bSVille Tervo 		if (!conn) {
3217b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3218b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3219b62f328bSVille Tervo 			return;
3220b62f328bSVille Tervo 		}
322129b7988aSAndre Guedes 
322229b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3223b62f328bSVille Tervo 	}
3224fcd89c09SVille Tervo 
3225fcd89c09SVille Tervo 	if (ev->status) {
322648264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
322748264f06SJohan Hedberg 						conn->dst_type, ev->status);
3228fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3229fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3230fcd89c09SVille Tervo 		hci_conn_del(conn);
3231fcd89c09SVille Tervo 		goto unlock;
3232fcd89c09SVille Tervo 	}
3233fcd89c09SVille Tervo 
3234b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3235b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
3236b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0, 0);
323783bc71b4SVinicius Costa Gomes 
32387b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3239fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3240fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3241fcd89c09SVille Tervo 
3242fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3243fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3244fcd89c09SVille Tervo 
3245fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3246fcd89c09SVille Tervo 
3247fcd89c09SVille Tervo unlock:
3248fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3249fcd89c09SVille Tervo }
3250fcd89c09SVille Tervo 
32519aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
32529aa04c91SAndre Guedes 						struct sk_buff *skb)
32539aa04c91SAndre Guedes {
3254e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3255e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
32563c9e9195SAndre Guedes 	s8 rssi;
32579aa04c91SAndre Guedes 
32589aa04c91SAndre Guedes 	hci_dev_lock(hdev);
32599aa04c91SAndre Guedes 
3260e95beb41SAndre Guedes 	while (num_reports--) {
3261e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3262e95beb41SAndre Guedes 
32639aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
32649aa04c91SAndre Guedes 
32653c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
32663c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
32673c9e9195SAndre Guedes 					NULL, rssi, 0, ev->data, ev->length);
32683c9e9195SAndre Guedes 
3269e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
32709aa04c91SAndre Guedes 	}
32719aa04c91SAndre Guedes 
32729aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
32739aa04c91SAndre Guedes }
32749aa04c91SAndre Guedes 
3275a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3276a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3277a7a595f6SVinicius Costa Gomes {
3278a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3279a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3280bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3281a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3282c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3283a7a595f6SVinicius Costa Gomes 
3284a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3285a7a595f6SVinicius Costa Gomes 
3286a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3287a7a595f6SVinicius Costa Gomes 
3288a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3289bea710feSVinicius Costa Gomes 	if (conn == NULL)
3290bea710feSVinicius Costa Gomes 		goto not_found;
3291a7a595f6SVinicius Costa Gomes 
3292bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3293bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3294bea710feSVinicius Costa Gomes 		goto not_found;
3295bea710feSVinicius Costa Gomes 
3296bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3297a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3298c9839a11SVinicius Costa Gomes 
3299c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3300c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3301a7a595f6SVinicius Costa Gomes 
3302a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3303a7a595f6SVinicius Costa Gomes 
3304c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3305c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3306c9839a11SVinicius Costa Gomes 		kfree(ltk);
3307c9839a11SVinicius Costa Gomes 	}
3308c9839a11SVinicius Costa Gomes 
3309a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3310bea710feSVinicius Costa Gomes 
3311bea710feSVinicius Costa Gomes 	return;
3312bea710feSVinicius Costa Gomes 
3313bea710feSVinicius Costa Gomes not_found:
3314bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3315bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3316bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3317a7a595f6SVinicius Costa Gomes }
3318a7a595f6SVinicius Costa Gomes 
3319fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3320fcd89c09SVille Tervo {
3321fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3322fcd89c09SVille Tervo 
3323fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3324fcd89c09SVille Tervo 
3325fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3326fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3327fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3328fcd89c09SVille Tervo 		break;
3329fcd89c09SVille Tervo 
33309aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
33319aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
33329aa04c91SAndre Guedes 		break;
33339aa04c91SAndre Guedes 
3334a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3335a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3336a7a595f6SVinicius Costa Gomes 		break;
3337a7a595f6SVinicius Costa Gomes 
3338fcd89c09SVille Tervo 	default:
3339fcd89c09SVille Tervo 		break;
3340fcd89c09SVille Tervo 	}
3341fcd89c09SVille Tervo }
3342fcd89c09SVille Tervo 
33431da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
33441da177e4SLinus Torvalds {
3345a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3346a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
33471da177e4SLinus Torvalds 
33481da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
33491da177e4SLinus Torvalds 
3350a9de9248SMarcel Holtmann 	switch (event) {
33511da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
33521da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
33531da177e4SLinus Torvalds 		break;
33541da177e4SLinus Torvalds 
33551da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
33561da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
33571da177e4SLinus Torvalds 		break;
33581da177e4SLinus Torvalds 
3359a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3360a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
336121d9e30eSMarcel Holtmann 		break;
336221d9e30eSMarcel Holtmann 
33631da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
33641da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
33651da177e4SLinus Torvalds 		break;
33661da177e4SLinus Torvalds 
33671da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
33681da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
33691da177e4SLinus Torvalds 		break;
33701da177e4SLinus Torvalds 
33711da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
33721da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
33731da177e4SLinus Torvalds 		break;
33741da177e4SLinus Torvalds 
3375a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3376a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3377a9de9248SMarcel Holtmann 		break;
3378a9de9248SMarcel Holtmann 
33791da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
33801da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
33811da177e4SLinus Torvalds 		break;
33821da177e4SLinus Torvalds 
3383a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3384a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3385a9de9248SMarcel Holtmann 		break;
3386a9de9248SMarcel Holtmann 
3387a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3388a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3389a9de9248SMarcel Holtmann 		break;
3390a9de9248SMarcel Holtmann 
3391a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3392a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3393a9de9248SMarcel Holtmann 		break;
3394a9de9248SMarcel Holtmann 
3395a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3396a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3397a9de9248SMarcel Holtmann 		break;
3398a9de9248SMarcel Holtmann 
3399a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3400a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3401a9de9248SMarcel Holtmann 		break;
3402a9de9248SMarcel Holtmann 
3403a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3404a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3405a9de9248SMarcel Holtmann 		break;
3406a9de9248SMarcel Holtmann 
3407a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3408a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3409a9de9248SMarcel Holtmann 		break;
3410a9de9248SMarcel Holtmann 
3411a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3412a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3413a9de9248SMarcel Holtmann 		break;
3414a9de9248SMarcel Holtmann 
3415a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3416a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
34171da177e4SLinus Torvalds 		break;
34181da177e4SLinus Torvalds 
34191da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
34201da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
34211da177e4SLinus Torvalds 		break;
34221da177e4SLinus Torvalds 
34231da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
34241da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
34251da177e4SLinus Torvalds 		break;
34261da177e4SLinus Torvalds 
34271da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
34281da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
34291da177e4SLinus Torvalds 		break;
34301da177e4SLinus Torvalds 
34311da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
34321da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
34331da177e4SLinus Torvalds 		break;
34341da177e4SLinus Torvalds 
3435a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3436a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3437a8746417SMarcel Holtmann 		break;
3438a8746417SMarcel Holtmann 
343985a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
344085a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
344185a1e930SMarcel Holtmann 		break;
344285a1e930SMarcel Holtmann 
3443a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3444a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3445a9de9248SMarcel Holtmann 		break;
3446a9de9248SMarcel Holtmann 
3447a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3448a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3449a9de9248SMarcel Holtmann 		break;
3450a9de9248SMarcel Holtmann 
3451a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3452a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3453a9de9248SMarcel Holtmann 		break;
3454a9de9248SMarcel Holtmann 
3455a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3456a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3457a9de9248SMarcel Holtmann 		break;
3458a9de9248SMarcel Holtmann 
345904837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
346004837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
346104837f64SMarcel Holtmann 		break;
346204837f64SMarcel Holtmann 
3463a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3464a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
34651da177e4SLinus Torvalds 		break;
34661da177e4SLinus Torvalds 
34670493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
34680493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
34690493684eSMarcel Holtmann 		break;
34700493684eSMarcel Holtmann 
347103b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
347203b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
347303b555e1SJohan Hedberg 		break;
347403b555e1SJohan Hedberg 
3475a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3476a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3477a5c29683SJohan Hedberg 		break;
3478a5c29683SJohan Hedberg 
34791143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
34801143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
34811143d458SBrian Gix 		break;
34821143d458SBrian Gix 
34830493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
34840493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
34850493684eSMarcel Holtmann 		break;
34860493684eSMarcel Holtmann 
348741a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
348841a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
348941a96212SMarcel Holtmann 		break;
349041a96212SMarcel Holtmann 
3491fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3492fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3493fcd89c09SVille Tervo 		break;
3494fcd89c09SVille Tervo 
34952763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
34962763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
34972763eda6SSzymon Janc 		break;
34982763eda6SSzymon Janc 
349925e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
350025e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
350125e89e99SAndrei Emeltchenko 		break;
350225e89e99SAndrei Emeltchenko 
35031da177e4SLinus Torvalds 	default:
3504a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
35051da177e4SLinus Torvalds 		break;
35061da177e4SLinus Torvalds 	}
35071da177e4SLinus Torvalds 
35081da177e4SLinus Torvalds 	kfree_skb(skb);
35091da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
35101da177e4SLinus Torvalds }
35111da177e4SLinus Torvalds 
35121da177e4SLinus Torvalds /* Generate internal stack event */
35131da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
35141da177e4SLinus Torvalds {
35151da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
35161da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
35171da177e4SLinus Torvalds 	struct sk_buff *skb;
35181da177e4SLinus Torvalds 
35191da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
35201da177e4SLinus Torvalds 	if (!skb)
35211da177e4SLinus Torvalds 		return;
35221da177e4SLinus Torvalds 
35231da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
35241da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
35251da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
35261da177e4SLinus Torvalds 
35271da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
35281da177e4SLinus Torvalds 	ev->type = type;
35291da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
35301da177e4SLinus Torvalds 
3531576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3532a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3533576c7d85SMarcel Holtmann 
35340d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
35351da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3536eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
35371da177e4SLinus Torvalds 	kfree_skb(skb);
35381da177e4SLinus Torvalds }
3539e6100a25SAndre Guedes 
3540669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3541e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3542