xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 95947a39)
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 */
199*95947a39SHemant Gupta 	hdev->dev_flags &= BIT(HCI_MGMT) | BIT(HCI_SETUP) | BIT(HCI_AUTO_OFF) |
200*95947a39SHemant Gupta 				BIT(HCI_LINK_KEYS) | BIT(HCI_DEBUG_KEYS);
201a9de9248SMarcel Holtmann }
202a9de9248SMarcel Holtmann 
203a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
204a9de9248SMarcel Holtmann {
205a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2061da177e4SLinus Torvalds 	void *sent;
2071da177e4SLinus Torvalds 
208a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2091da177e4SLinus Torvalds 
210a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2111da177e4SLinus Torvalds 	if (!sent)
212a9de9248SMarcel Holtmann 		return;
2131da177e4SLinus Torvalds 
21456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21556e5cb86SJohan Hedberg 
216a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
217744cf19eSJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
218b312b161SJohan Hedberg 
21956e5cb86SJohan Hedberg 	if (status == 0)
2201f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
22156e5cb86SJohan Hedberg 
22256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
223a9de9248SMarcel Holtmann }
224a9de9248SMarcel Holtmann 
225a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
226a9de9248SMarcel Holtmann {
227a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
228a9de9248SMarcel Holtmann 
229a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
230a9de9248SMarcel Holtmann 
231a9de9248SMarcel Holtmann 	if (rp->status)
232a9de9248SMarcel Holtmann 		return;
233a9de9248SMarcel Holtmann 
2341f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
235a9de9248SMarcel Holtmann }
236a9de9248SMarcel Holtmann 
237a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
238a9de9248SMarcel Holtmann {
239a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
240a9de9248SMarcel Holtmann 	void *sent;
241a9de9248SMarcel Holtmann 
242a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
243a9de9248SMarcel Holtmann 
244a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
245a9de9248SMarcel Holtmann 	if (!sent)
246a9de9248SMarcel Holtmann 		return;
2471da177e4SLinus Torvalds 
2481da177e4SLinus Torvalds 	if (!status) {
249a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
250a9de9248SMarcel Holtmann 
2511da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2521da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2531da177e4SLinus Torvalds 		else
2541da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2551da177e4SLinus Torvalds 	}
256a9de9248SMarcel Holtmann 
25723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
258a9de9248SMarcel Holtmann }
2591da177e4SLinus Torvalds 
260a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
261a9de9248SMarcel Holtmann {
262a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
263a9de9248SMarcel Holtmann 	void *sent;
264a9de9248SMarcel Holtmann 
265a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
266a9de9248SMarcel Holtmann 
267a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2681da177e4SLinus Torvalds 	if (!sent)
269a9de9248SMarcel Holtmann 		return;
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds 	if (!status) {
272a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
273a9de9248SMarcel Holtmann 
2741da177e4SLinus Torvalds 		if (param)
2751da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2761da177e4SLinus Torvalds 		else
2771da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2781da177e4SLinus Torvalds 	}
279a9de9248SMarcel Holtmann 
28023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2811da177e4SLinus Torvalds }
2821da177e4SLinus Torvalds 
283a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
284a9de9248SMarcel Holtmann {
28536f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28636f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
287a9de9248SMarcel Holtmann 	void *sent;
2881da177e4SLinus Torvalds 
289a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
290a9de9248SMarcel Holtmann 
291a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2921da177e4SLinus Torvalds 	if (!sent)
293a9de9248SMarcel Holtmann 		return;
2941da177e4SLinus Torvalds 
29536f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
296a9de9248SMarcel Holtmann 
29756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29856e5cb86SJohan Hedberg 
2992d7cee58SJohan Hedberg 	if (status != 0) {
300744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3012d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3022d7cee58SJohan Hedberg 		goto done;
3032d7cee58SJohan Hedberg 	}
3042d7cee58SJohan Hedberg 
3059fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3069fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
307a9de9248SMarcel Holtmann 
30873f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3091da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3109fbcbb45SJohan Hedberg 		if (!old_iscan)
311744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31216ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
31316ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31416ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31516ab91abSJohan Hedberg 									to);
31616ab91abSJohan Hedberg 		}
3179fbcbb45SJohan Hedberg 	} else if (old_iscan)
318744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3191da177e4SLinus Torvalds 
3209fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3211da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3229fbcbb45SJohan Hedberg 		if (!old_pscan)
323744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3249fbcbb45SJohan Hedberg 	} else if (old_pscan)
325744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
326a9de9248SMarcel Holtmann 
32736f7fc7eSJohan Hedberg done:
32856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
32923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
332a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
333a9de9248SMarcel Holtmann {
334a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
335a9de9248SMarcel Holtmann 
336a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
337a9de9248SMarcel Holtmann 
338a9de9248SMarcel Holtmann 	if (rp->status)
339a9de9248SMarcel Holtmann 		return;
340a9de9248SMarcel Holtmann 
341a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
344a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
345a9de9248SMarcel Holtmann }
346a9de9248SMarcel Holtmann 
347a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
348a9de9248SMarcel Holtmann {
349a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
350a9de9248SMarcel Holtmann 	void *sent;
351a9de9248SMarcel Holtmann 
352a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
353a9de9248SMarcel Holtmann 
354f383f275SMarcel Holtmann 	if (status)
355f383f275SMarcel Holtmann 		return;
356f383f275SMarcel Holtmann 
357a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
358a9de9248SMarcel Holtmann 	if (!sent)
359a9de9248SMarcel Holtmann 		return;
360a9de9248SMarcel Holtmann 
361a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
362a9de9248SMarcel Holtmann }
363a9de9248SMarcel Holtmann 
364a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
365a9de9248SMarcel Holtmann {
366a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
367a9de9248SMarcel Holtmann 	__u16 setting;
368a9de9248SMarcel Holtmann 
369a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
370a9de9248SMarcel Holtmann 
371a9de9248SMarcel Holtmann 	if (rp->status)
372a9de9248SMarcel Holtmann 		return;
373a9de9248SMarcel Holtmann 
374a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
375a9de9248SMarcel Holtmann 
376a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
377a9de9248SMarcel Holtmann 		return;
378a9de9248SMarcel Holtmann 
379a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
380a9de9248SMarcel Holtmann 
381a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
382a9de9248SMarcel Holtmann 
3833c54711cSGustavo F. Padovan 	if (hdev->notify)
384a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
385a9de9248SMarcel Holtmann }
386a9de9248SMarcel Holtmann 
387a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
388a9de9248SMarcel Holtmann {
389a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
390f383f275SMarcel Holtmann 	__u16 setting;
391a9de9248SMarcel Holtmann 	void *sent;
392a9de9248SMarcel Holtmann 
393a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
394a9de9248SMarcel Holtmann 
395f383f275SMarcel Holtmann 	if (status)
396f383f275SMarcel Holtmann 		return;
397f383f275SMarcel Holtmann 
398a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
399a9de9248SMarcel Holtmann 	if (!sent)
400a9de9248SMarcel Holtmann 		return;
401a9de9248SMarcel Holtmann 
402f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4031da177e4SLinus Torvalds 
404f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
405f383f275SMarcel Holtmann 		return;
406f383f275SMarcel Holtmann 
4071da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4081da177e4SLinus Torvalds 
409a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4101da177e4SLinus Torvalds 
4113c54711cSGustavo F. Padovan 	if (hdev->notify)
4121da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4131da177e4SLinus Torvalds }
4141da177e4SLinus Torvalds 
415a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4161da177e4SLinus Torvalds {
417a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4181da177e4SLinus Torvalds 
419a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4201da177e4SLinus Torvalds 
42123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4221143e5a6SMarcel Holtmann }
4231143e5a6SMarcel Holtmann 
424333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
425333140b5SMarcel Holtmann {
426333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
427333140b5SMarcel Holtmann 
428333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
429333140b5SMarcel Holtmann 
430333140b5SMarcel Holtmann 	if (rp->status)
431333140b5SMarcel Holtmann 		return;
432333140b5SMarcel Holtmann 
43384bde9d6SJohan Hedberg 	if (rp->mode)
43484bde9d6SJohan Hedberg 		set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
43584bde9d6SJohan Hedberg 	else
43684bde9d6SJohan Hedberg 		clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
437333140b5SMarcel Holtmann }
438333140b5SMarcel Holtmann 
439333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
440333140b5SMarcel Holtmann {
441333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
442333140b5SMarcel Holtmann 	void *sent;
443333140b5SMarcel Holtmann 
444333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
445333140b5SMarcel Holtmann 
446333140b5SMarcel Holtmann 	if (status)
447333140b5SMarcel Holtmann 		return;
448333140b5SMarcel Holtmann 
449333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
450333140b5SMarcel Holtmann 	if (!sent)
451333140b5SMarcel Holtmann 		return;
452333140b5SMarcel Holtmann 
45384bde9d6SJohan Hedberg 	if (*((u8 *) sent))
45484bde9d6SJohan Hedberg 		set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
45584bde9d6SJohan Hedberg 	else
45684bde9d6SJohan Hedberg 		clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
457333140b5SMarcel Holtmann }
458333140b5SMarcel Holtmann 
459d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
460d5859e22SJohan Hedberg {
461d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
462d5859e22SJohan Hedberg 		return 2;
463d5859e22SJohan Hedberg 
464d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
465d5859e22SJohan Hedberg 		return 1;
466d5859e22SJohan Hedberg 
467d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
468d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
469d5859e22SJohan Hedberg 		return 1;
470d5859e22SJohan Hedberg 
471d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
472d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
473d5859e22SJohan Hedberg 			return 1;
474d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
475d5859e22SJohan Hedberg 			return 1;
476d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
477d5859e22SJohan Hedberg 			return 1;
478d5859e22SJohan Hedberg 	}
479d5859e22SJohan Hedberg 
480d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
481d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
482d5859e22SJohan Hedberg 		return 1;
483d5859e22SJohan Hedberg 
484d5859e22SJohan Hedberg 	return 0;
485d5859e22SJohan Hedberg }
486d5859e22SJohan Hedberg 
487d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
488d5859e22SJohan Hedberg {
489d5859e22SJohan Hedberg 	u8 mode;
490d5859e22SJohan Hedberg 
491d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
492d5859e22SJohan Hedberg 
493d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
494d5859e22SJohan Hedberg }
495d5859e22SJohan Hedberg 
496d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
497d5859e22SJohan Hedberg {
498d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
499d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
500d5859e22SJohan Hedberg 	 * command otherwise */
501d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
502d5859e22SJohan Hedberg 
5036de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5046de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5055a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
5066de6c18dSVille Tervo 		return;
5076de6c18dSVille Tervo 
508d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
509d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
510d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
511d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
512d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
513d5859e22SJohan Hedberg 
514d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
515d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
516d5859e22SJohan Hedberg 
517d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
518d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
519d5859e22SJohan Hedberg 
520d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
521d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
522d5859e22SJohan Hedberg 
523d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
524d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
525d5859e22SJohan Hedberg 
526d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
527d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
528d5859e22SJohan Hedberg 
529d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
530d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
531d5859e22SJohan Hedberg 
532d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
533d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
534d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
535d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
536d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
537d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
538d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
539d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
540d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
541d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
542d5859e22SJohan Hedberg 					 * Features Notification */
543d5859e22SJohan Hedberg 	}
544d5859e22SJohan Hedberg 
545d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
546d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
547d5859e22SJohan Hedberg 
548d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
549d5859e22SJohan Hedberg }
550d5859e22SJohan Hedberg 
551e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
552e6100a25SAndre Guedes {
553e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
554e6100a25SAndre Guedes 
555e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
556e6100a25SAndre Guedes 
557e6100a25SAndre Guedes 	if (enable_le) {
558e6100a25SAndre Guedes 		cp.le = 1;
559e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
560e6100a25SAndre Guedes 	}
561e6100a25SAndre Guedes 
562e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
563e6100a25SAndre Guedes }
564e6100a25SAndre Guedes 
565d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
566d5859e22SJohan Hedberg {
567e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
568e61ef499SAndrei Emeltchenko 		return;
569e61ef499SAndrei Emeltchenko 
570d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
571d5859e22SJohan Hedberg 
572d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
573d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
574d5859e22SJohan Hedberg 
575d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
576d5859e22SJohan Hedberg 		u8 mode = 0x01;
577d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
578d5859e22SJohan Hedberg 	}
579d5859e22SJohan Hedberg 
580d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
581d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
582d5859e22SJohan Hedberg 
583d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
584d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
585971e3a4bSAndre Guedes 
586971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
587971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
588971e3a4bSAndre Guedes 
589971e3a4bSAndre Guedes 		cp.page = 0x01;
590971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
591971e3a4bSAndre Guedes 							sizeof(cp), &cp);
592971e3a4bSAndre Guedes 	}
593e6100a25SAndre Guedes 
594e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
595e6100a25SAndre Guedes 		hci_set_le_support(hdev);
596d5859e22SJohan Hedberg }
597d5859e22SJohan Hedberg 
598a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
599a9de9248SMarcel Holtmann {
600a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6011143e5a6SMarcel Holtmann 
602a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
6031143e5a6SMarcel Holtmann 
604a9de9248SMarcel Holtmann 	if (rp->status)
605a9de9248SMarcel Holtmann 		return;
6061143e5a6SMarcel Holtmann 
607a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
608e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
609d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
610e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
611d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6121da177e4SLinus Torvalds 
613a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
614a9de9248SMarcel Holtmann 					hdev->manufacturer,
615a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
616d5859e22SJohan Hedberg 
617d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
618d5859e22SJohan Hedberg 		hci_setup(hdev);
619d5859e22SJohan Hedberg }
620d5859e22SJohan Hedberg 
621d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
622d5859e22SJohan Hedberg {
623d5859e22SJohan Hedberg 	u16 link_policy = 0;
624d5859e22SJohan Hedberg 
625d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
626d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
627d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
628d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
629d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
630d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
631d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
632d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
633d5859e22SJohan Hedberg 
634d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
635d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
636d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6371da177e4SLinus Torvalds }
6381da177e4SLinus Torvalds 
639a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
640a9de9248SMarcel Holtmann {
641a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
642a9de9248SMarcel Holtmann 
643a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
644a9de9248SMarcel Holtmann 
645a9de9248SMarcel Holtmann 	if (rp->status)
646d5859e22SJohan Hedberg 		goto done;
647a9de9248SMarcel Holtmann 
648a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
649d5859e22SJohan Hedberg 
650d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
651d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
652d5859e22SJohan Hedberg 
653d5859e22SJohan Hedberg done:
654d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
655a9de9248SMarcel Holtmann }
656a9de9248SMarcel Holtmann 
657a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
658a9de9248SMarcel Holtmann {
659a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
660a9de9248SMarcel Holtmann 
661a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
662a9de9248SMarcel Holtmann 
663a9de9248SMarcel Holtmann 	if (rp->status)
664a9de9248SMarcel Holtmann 		return;
665a9de9248SMarcel Holtmann 
666a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6671da177e4SLinus Torvalds 
6681da177e4SLinus Torvalds 	/* Adjust default settings according to features
6691da177e4SLinus Torvalds 	 * supported by device. */
670a9de9248SMarcel Holtmann 
6711da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6721da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6731da177e4SLinus Torvalds 
6741da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6751da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6761da177e4SLinus Torvalds 
6775b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6781da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6795b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6805b7f9909SMarcel Holtmann 	}
6811da177e4SLinus Torvalds 
6825b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6831da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6845b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6855b7f9909SMarcel Holtmann 	}
6865b7f9909SMarcel Holtmann 
6875b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6885b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6895b7f9909SMarcel Holtmann 
6905b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6915b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6925b7f9909SMarcel Holtmann 
6935b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6945b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6951da177e4SLinus Torvalds 
696efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
697efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
698efc7688bSMarcel Holtmann 
699efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
700efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
701efc7688bSMarcel Holtmann 
702efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
703efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
704efc7688bSMarcel Holtmann 
705a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
706a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
707a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
708a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
709a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7101da177e4SLinus Torvalds }
7111da177e4SLinus Torvalds 
712971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
713971e3a4bSAndre Guedes 							struct sk_buff *skb)
714971e3a4bSAndre Guedes {
715971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
716971e3a4bSAndre Guedes 
717971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
718971e3a4bSAndre Guedes 
719971e3a4bSAndre Guedes 	if (rp->status)
720971e3a4bSAndre Guedes 		return;
721971e3a4bSAndre Guedes 
722b5b32b65SAndre Guedes 	switch (rp->page) {
723b5b32b65SAndre Guedes 	case 0:
724b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
725b5b32b65SAndre Guedes 		break;
726b5b32b65SAndre Guedes 	case 1:
72759e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
728b5b32b65SAndre Guedes 		break;
729b5b32b65SAndre Guedes 	}
730971e3a4bSAndre Guedes 
731971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
732971e3a4bSAndre Guedes }
733971e3a4bSAndre Guedes 
7341e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7351e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7361e89cffbSAndrei Emeltchenko {
7371e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7381e89cffbSAndrei Emeltchenko 
7391e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7401e89cffbSAndrei Emeltchenko 
7411e89cffbSAndrei Emeltchenko 	if (rp->status)
7421e89cffbSAndrei Emeltchenko 		return;
7431e89cffbSAndrei Emeltchenko 
7441e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7451e89cffbSAndrei Emeltchenko 
7461e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7471e89cffbSAndrei Emeltchenko }
7481e89cffbSAndrei Emeltchenko 
749a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
750a9de9248SMarcel Holtmann {
751a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
752a9de9248SMarcel Holtmann 
753a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
754a9de9248SMarcel Holtmann 
755a9de9248SMarcel Holtmann 	if (rp->status)
756a9de9248SMarcel Holtmann 		return;
757a9de9248SMarcel Holtmann 
758a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
759a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
760a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
761a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
762da1f5198SMarcel Holtmann 
763da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
764da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
765da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
766da1f5198SMarcel Holtmann 	}
767da1f5198SMarcel Holtmann 
768da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
769da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7701da177e4SLinus Torvalds 
771a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
772a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
773a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7741da177e4SLinus Torvalds }
7751da177e4SLinus Torvalds 
776a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
777a9de9248SMarcel Holtmann {
778a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7791da177e4SLinus Torvalds 
780a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
781a9de9248SMarcel Holtmann 
782a9de9248SMarcel Holtmann 	if (!rp->status)
783a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
784a9de9248SMarcel Holtmann 
78523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
78623bb5763SJohan Hedberg }
78723bb5763SJohan Hedberg 
788350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
789350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
790350ee4cfSAndrei Emeltchenko {
791350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
792350ee4cfSAndrei Emeltchenko 
793350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
794350ee4cfSAndrei Emeltchenko 
795350ee4cfSAndrei Emeltchenko 	if (rp->status)
796350ee4cfSAndrei Emeltchenko 		return;
797350ee4cfSAndrei Emeltchenko 
798350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
799350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
800350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
801350ee4cfSAndrei Emeltchenko 
802350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
803350ee4cfSAndrei Emeltchenko 
804350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
805350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
806350ee4cfSAndrei Emeltchenko 
807350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
808350ee4cfSAndrei Emeltchenko }
809350ee4cfSAndrei Emeltchenko 
81023bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
81123bb5763SJohan Hedberg {
81223bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
81323bb5763SJohan Hedberg 
81423bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
81523bb5763SJohan Hedberg 
81623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8171da177e4SLinus Torvalds }
8181da177e4SLinus Torvalds 
819928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
820928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
821928abaa7SAndrei Emeltchenko {
822928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
823928abaa7SAndrei Emeltchenko 
824928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
825928abaa7SAndrei Emeltchenko 
826928abaa7SAndrei Emeltchenko 	if (rp->status)
827928abaa7SAndrei Emeltchenko 		return;
828928abaa7SAndrei Emeltchenko 
829928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
830928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
831928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
832928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
833928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
834928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
835928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
836928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
837928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
838928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
839928abaa7SAndrei Emeltchenko 
840928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
841928abaa7SAndrei Emeltchenko }
842928abaa7SAndrei Emeltchenko 
843b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
844b0916ea0SJohan Hedberg 							struct sk_buff *skb)
845b0916ea0SJohan Hedberg {
846b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
847b0916ea0SJohan Hedberg 
848b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
849b0916ea0SJohan Hedberg 
850b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
851b0916ea0SJohan Hedberg }
852b0916ea0SJohan Hedberg 
853d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
854d5859e22SJohan Hedberg {
855d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
856d5859e22SJohan Hedberg 
857d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
858d5859e22SJohan Hedberg 
859d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
860d5859e22SJohan Hedberg }
861d5859e22SJohan Hedberg 
862d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
863d5859e22SJohan Hedberg 							struct sk_buff *skb)
864d5859e22SJohan Hedberg {
865d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
866d5859e22SJohan Hedberg 
867d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
868d5859e22SJohan Hedberg 
869d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
870d5859e22SJohan Hedberg }
871d5859e22SJohan Hedberg 
872d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
873d5859e22SJohan Hedberg 							struct sk_buff *skb)
874d5859e22SJohan Hedberg {
875d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
876d5859e22SJohan Hedberg 
877d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
878d5859e22SJohan Hedberg 
879d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
880d5859e22SJohan Hedberg }
881d5859e22SJohan Hedberg 
882d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
883d5859e22SJohan Hedberg {
884d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
885d5859e22SJohan Hedberg 
886d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
887d5859e22SJohan Hedberg 
888d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
889d5859e22SJohan Hedberg }
890d5859e22SJohan Hedberg 
891980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
892980e1a53SJohan Hedberg {
893980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
894980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
895980e1a53SJohan Hedberg 	struct hci_conn *conn;
896980e1a53SJohan Hedberg 
897980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
898980e1a53SJohan Hedberg 
89956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
90056e5cb86SJohan Hedberg 
901a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
902744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
903980e1a53SJohan Hedberg 
904980e1a53SJohan Hedberg 	if (rp->status != 0)
90556e5cb86SJohan Hedberg 		goto unlock;
906980e1a53SJohan Hedberg 
907980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
908980e1a53SJohan Hedberg 	if (!cp)
90956e5cb86SJohan Hedberg 		goto unlock;
910980e1a53SJohan Hedberg 
911980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
912980e1a53SJohan Hedberg 	if (conn)
913980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
91456e5cb86SJohan Hedberg 
91556e5cb86SJohan Hedberg unlock:
91656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
917980e1a53SJohan Hedberg }
918980e1a53SJohan Hedberg 
919980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
920980e1a53SJohan Hedberg {
921980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
922980e1a53SJohan Hedberg 
923980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
924980e1a53SJohan Hedberg 
92556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92656e5cb86SJohan Hedberg 
927a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
928744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
929980e1a53SJohan Hedberg 								rp->status);
93056e5cb86SJohan Hedberg 
93156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
932980e1a53SJohan Hedberg }
93356e5cb86SJohan Hedberg 
9346ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9356ed58ec5SVille Tervo 				       struct sk_buff *skb)
9366ed58ec5SVille Tervo {
9376ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9386ed58ec5SVille Tervo 
9396ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9406ed58ec5SVille Tervo 
9416ed58ec5SVille Tervo 	if (rp->status)
9426ed58ec5SVille Tervo 		return;
9436ed58ec5SVille Tervo 
9446ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9456ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9466ed58ec5SVille Tervo 
9476ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9486ed58ec5SVille Tervo 
9496ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9506ed58ec5SVille Tervo 
9516ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9526ed58ec5SVille Tervo }
953980e1a53SJohan Hedberg 
954a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
955a5c29683SJohan Hedberg {
956a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
957a5c29683SJohan Hedberg 
958a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
959a5c29683SJohan Hedberg 
96056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96156e5cb86SJohan Hedberg 
962a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
963744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
964a5c29683SJohan Hedberg 								rp->status);
96556e5cb86SJohan Hedberg 
96656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
967a5c29683SJohan Hedberg }
968a5c29683SJohan Hedberg 
969a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
970a5c29683SJohan Hedberg 							struct sk_buff *skb)
971a5c29683SJohan Hedberg {
972a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
973a5c29683SJohan Hedberg 
974a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
975a5c29683SJohan Hedberg 
97656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
97756e5cb86SJohan Hedberg 
978a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
979744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
980a5c29683SJohan Hedberg 								rp->status);
98156e5cb86SJohan Hedberg 
98256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
983a5c29683SJohan Hedberg }
984a5c29683SJohan Hedberg 
9851143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9861143d458SBrian Gix {
9871143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9881143d458SBrian Gix 
9891143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9901143d458SBrian Gix 
9911143d458SBrian Gix 	hci_dev_lock(hdev);
9921143d458SBrian Gix 
993a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9941143d458SBrian Gix 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
9951143d458SBrian Gix 								rp->status);
9961143d458SBrian Gix 
9971143d458SBrian Gix 	hci_dev_unlock(hdev);
9981143d458SBrian Gix }
9991143d458SBrian Gix 
10001143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10011143d458SBrian Gix 							struct sk_buff *skb)
10021143d458SBrian Gix {
10031143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10041143d458SBrian Gix 
10051143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10061143d458SBrian Gix 
10071143d458SBrian Gix 	hci_dev_lock(hdev);
10081143d458SBrian Gix 
1009a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10101143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
10111143d458SBrian Gix 								rp->status);
10121143d458SBrian Gix 
10131143d458SBrian Gix 	hci_dev_unlock(hdev);
10141143d458SBrian Gix }
10151143d458SBrian Gix 
1016c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1017c35938b2SSzymon Janc 							struct sk_buff *skb)
1018c35938b2SSzymon Janc {
1019c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1020c35938b2SSzymon Janc 
1021c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1022c35938b2SSzymon Janc 
102356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1024744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1025c35938b2SSzymon Janc 						rp->randomizer, rp->status);
102656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1027c35938b2SSzymon Janc }
1028c35938b2SSzymon Janc 
102907f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
103007f7fa5dSAndre Guedes {
103107f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
103207f7fa5dSAndre Guedes 
103307f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
103407f7fa5dSAndre Guedes }
103507f7fa5dSAndre Guedes 
1036eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1037eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1038eb9d91f5SAndre Guedes {
1039eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1040eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1041eb9d91f5SAndre Guedes 
1042eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1043eb9d91f5SAndre Guedes 
1044eb9d91f5SAndre Guedes 	if (status)
1045eb9d91f5SAndre Guedes 		return;
1046eb9d91f5SAndre Guedes 
1047eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1048eb9d91f5SAndre Guedes 	if (!cp)
1049eb9d91f5SAndre Guedes 		return;
1050eb9d91f5SAndre Guedes 
105168a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
105268a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
1053d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1054d23264a8SAndre Guedes 
1055db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1056a8f13c8cSAndre Guedes 
1057a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1058eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1059a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
106068a8aea4SAndrei Emeltchenko 		break;
106168a8aea4SAndrei Emeltchenko 
106268a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1063d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1064d23264a8SAndre Guedes 
1065d084329eSAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
106668a8aea4SAndrei Emeltchenko 		break;
106768a8aea4SAndrei Emeltchenko 
106868a8aea4SAndrei Emeltchenko 	default:
106968a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
107068a8aea4SAndrei Emeltchenko 		break;
107135815085SAndre Guedes 	}
1072eb9d91f5SAndre Guedes }
1073eb9d91f5SAndre Guedes 
1074a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1075a7a595f6SVinicius Costa Gomes {
1076a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1077a7a595f6SVinicius Costa Gomes 
1078a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1079a7a595f6SVinicius Costa Gomes 
1080a7a595f6SVinicius Costa Gomes 	if (rp->status)
1081a7a595f6SVinicius Costa Gomes 		return;
1082a7a595f6SVinicius Costa Gomes 
1083a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1084a7a595f6SVinicius Costa Gomes }
1085a7a595f6SVinicius Costa Gomes 
1086a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1087a7a595f6SVinicius Costa Gomes {
1088a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1089a7a595f6SVinicius Costa Gomes 
1090a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1091a7a595f6SVinicius Costa Gomes 
1092a7a595f6SVinicius Costa Gomes 	if (rp->status)
1093a7a595f6SVinicius Costa Gomes 		return;
1094a7a595f6SVinicius Costa Gomes 
1095a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1096a7a595f6SVinicius Costa Gomes }
1097a7a595f6SVinicius Costa Gomes 
1098f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1099f9b49306SAndre Guedes 							struct sk_buff *skb)
1100f9b49306SAndre Guedes {
1101f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1102f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1103f9b49306SAndre Guedes 
1104f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1105f9b49306SAndre Guedes 
1106f9b49306SAndre Guedes 	if (status)
1107f9b49306SAndre Guedes 		return;
1108f9b49306SAndre Guedes 
1109f9b49306SAndre Guedes 	cp.page = 0x01;
1110f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1111f9b49306SAndre Guedes }
1112f9b49306SAndre Guedes 
1113a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1114a9de9248SMarcel Holtmann {
1115a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1116a9de9248SMarcel Holtmann 
1117a9de9248SMarcel Holtmann 	if (status) {
111823bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1119a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
112056e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1121a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11227a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
112356e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1124314b2381SJohan Hedberg 		return;
1125314b2381SJohan Hedberg 	}
1126314b2381SJohan Hedberg 
112789352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
112889352e7dSAndre Guedes 
112956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
113030dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_INQUIRY);
113156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1132a9de9248SMarcel Holtmann }
1133a9de9248SMarcel Holtmann 
11341da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11351da177e4SLinus Torvalds {
1136a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11371da177e4SLinus Torvalds 	struct hci_conn *conn;
11381da177e4SLinus Torvalds 
1139a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1140a9de9248SMarcel Holtmann 
1141a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11421da177e4SLinus Torvalds 	if (!cp)
11431da177e4SLinus Torvalds 		return;
11441da177e4SLinus Torvalds 
11451da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11461da177e4SLinus Torvalds 
11471da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11481da177e4SLinus Torvalds 
1149a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11501da177e4SLinus Torvalds 
11511da177e4SLinus Torvalds 	if (status) {
11521da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11534c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11541da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11551da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11561da177e4SLinus Torvalds 				hci_conn_del(conn);
11574c67bc74SMarcel Holtmann 			} else
11584c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11591da177e4SLinus Torvalds 		}
11601da177e4SLinus Torvalds 	} else {
11611da177e4SLinus Torvalds 		if (!conn) {
11621da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11631da177e4SLinus Torvalds 			if (conn) {
1164a0c808b3SJohan Hedberg 				conn->out = true;
11651da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11661da177e4SLinus Torvalds 			} else
1167893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11681da177e4SLinus Torvalds 		}
11691da177e4SLinus Torvalds 	}
11701da177e4SLinus Torvalds 
11711da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11721da177e4SLinus Torvalds }
11731da177e4SLinus Torvalds 
1174a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11751da177e4SLinus Torvalds {
1176a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11771da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11781da177e4SLinus Torvalds 	__u16 handle;
11791da177e4SLinus Torvalds 
1180b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1181b6a0dc82SMarcel Holtmann 
1182a9de9248SMarcel Holtmann 	if (!status)
1183a9de9248SMarcel Holtmann 		return;
1184a9de9248SMarcel Holtmann 
1185a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11861da177e4SLinus Torvalds 	if (!cp)
1187a9de9248SMarcel Holtmann 		return;
11881da177e4SLinus Torvalds 
11891da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11901da177e4SLinus Torvalds 
1191a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11941da177e4SLinus Torvalds 
11951da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11965a08ecceSAndrei Emeltchenko 	if (acl) {
11975a08ecceSAndrei Emeltchenko 		sco = acl->link;
11985a08ecceSAndrei Emeltchenko 		if (sco) {
11991da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12001da177e4SLinus Torvalds 
12011da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12021da177e4SLinus Torvalds 			hci_conn_del(sco);
12031da177e4SLinus Torvalds 		}
12045a08ecceSAndrei Emeltchenko 	}
12051da177e4SLinus Torvalds 
12061da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12071da177e4SLinus Torvalds }
12081da177e4SLinus Torvalds 
1209f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1210f8558555SMarcel Holtmann {
1211f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1212f8558555SMarcel Holtmann 	struct hci_conn *conn;
1213f8558555SMarcel Holtmann 
1214f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1215f8558555SMarcel Holtmann 
1216f8558555SMarcel Holtmann 	if (!status)
1217f8558555SMarcel Holtmann 		return;
1218f8558555SMarcel Holtmann 
1219f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1220f8558555SMarcel Holtmann 	if (!cp)
1221f8558555SMarcel Holtmann 		return;
1222f8558555SMarcel Holtmann 
1223f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1224f8558555SMarcel Holtmann 
1225f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1226f8558555SMarcel Holtmann 	if (conn) {
1227f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1228f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1229f8558555SMarcel Holtmann 			hci_conn_put(conn);
1230f8558555SMarcel Holtmann 		}
1231f8558555SMarcel Holtmann 	}
1232f8558555SMarcel Holtmann 
1233f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1234f8558555SMarcel Holtmann }
1235f8558555SMarcel Holtmann 
1236f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1237f8558555SMarcel Holtmann {
1238f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1239f8558555SMarcel Holtmann 	struct hci_conn *conn;
1240f8558555SMarcel Holtmann 
1241f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1242f8558555SMarcel Holtmann 
1243f8558555SMarcel Holtmann 	if (!status)
1244f8558555SMarcel Holtmann 		return;
1245f8558555SMarcel Holtmann 
1246f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1247f8558555SMarcel Holtmann 	if (!cp)
1248f8558555SMarcel Holtmann 		return;
1249f8558555SMarcel Holtmann 
1250f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1251f8558555SMarcel Holtmann 
1252f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1253f8558555SMarcel Holtmann 	if (conn) {
1254f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1255f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1256f8558555SMarcel Holtmann 			hci_conn_put(conn);
1257f8558555SMarcel Holtmann 		}
1258f8558555SMarcel Holtmann 	}
1259f8558555SMarcel Holtmann 
1260f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1261f8558555SMarcel Holtmann }
1262f8558555SMarcel Holtmann 
1263127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1264392599b9SJohan Hedberg 							struct hci_conn *conn)
1265392599b9SJohan Hedberg {
1266392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1267392599b9SJohan Hedberg 		return 0;
1268392599b9SJohan Hedberg 
1269765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1270392599b9SJohan Hedberg 		return 0;
1271392599b9SJohan Hedberg 
1272392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1273e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1274aa64a8b5SJohan Hedberg 	if (!hci_conn_ssp_enabled(conn) &&
1275e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1276e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1277392599b9SJohan Hedberg 		return 0;
1278392599b9SJohan Hedberg 
1279392599b9SJohan Hedberg 	return 1;
1280392599b9SJohan Hedberg }
1281392599b9SJohan Hedberg 
128230dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
128330dc78e1SJohan Hedberg {
128430dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
128530dc78e1SJohan Hedberg 
128630dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
128730dc78e1SJohan Hedberg 
128830dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
128930dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
129030dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
129130dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
129230dc78e1SJohan Hedberg 
129330dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
129430dc78e1SJohan Hedberg }
129530dc78e1SJohan Hedberg 
1296b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
129730dc78e1SJohan Hedberg {
129830dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
129930dc78e1SJohan Hedberg 	struct inquiry_entry *e;
130030dc78e1SJohan Hedberg 
1301b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1302b644ba33SJohan Hedberg 		return false;
1303b644ba33SJohan Hedberg 
1304b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1305b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1306b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1307b644ba33SJohan Hedberg 		return true;
1308b644ba33SJohan Hedberg 	}
1309b644ba33SJohan Hedberg 
1310b644ba33SJohan Hedberg 	return false;
1311b644ba33SJohan Hedberg }
1312b644ba33SJohan Hedberg 
1313b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1314b644ba33SJohan Hedberg 					bdaddr_t *bdaddr, u8 *name, u8 name_len)
1315b644ba33SJohan Hedberg {
1316b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1317b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1318b644ba33SJohan Hedberg 
1319b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
1320b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00,
1321b644ba33SJohan Hedberg 					name, name_len, conn->dev_class);
1322b644ba33SJohan Hedberg 
1323b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1324b644ba33SJohan Hedberg 		return;
1325b644ba33SJohan Hedberg 
132630dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
132730dc78e1SJohan Hedberg 		goto discov_complete;
132830dc78e1SJohan Hedberg 
132930dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
133030dc78e1SJohan Hedberg 		return;
133130dc78e1SJohan Hedberg 
133230dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
133330dc78e1SJohan Hedberg 	if (e) {
133430dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
133530dc78e1SJohan Hedberg 		list_del(&e->list);
1336b644ba33SJohan Hedberg 		if (name)
1337b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1338b644ba33SJohan Hedberg 					e->data.rssi, name, name_len);
133930dc78e1SJohan Hedberg 	}
134030dc78e1SJohan Hedberg 
1341b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
134230dc78e1SJohan Hedberg 		return;
134330dc78e1SJohan Hedberg 
134430dc78e1SJohan Hedberg discov_complete:
134530dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
134630dc78e1SJohan Hedberg }
134730dc78e1SJohan Hedberg 
1348a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13491da177e4SLinus Torvalds {
1350127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1351127178d2SJohan Hedberg 	struct hci_conn *conn;
1352127178d2SJohan Hedberg 
1353a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1354127178d2SJohan Hedberg 
1355127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1356127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1357127178d2SJohan Hedberg 	if (!status)
1358127178d2SJohan Hedberg 		return;
1359127178d2SJohan Hedberg 
1360127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1361127178d2SJohan Hedberg 	if (!cp)
1362127178d2SJohan Hedberg 		return;
1363127178d2SJohan Hedberg 
1364127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1365127178d2SJohan Hedberg 
1366127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1367b644ba33SJohan Hedberg 
1368b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1369b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1370b644ba33SJohan Hedberg 
137179c6c70cSJohan Hedberg 	if (!conn)
137279c6c70cSJohan Hedberg 		goto unlock;
137379c6c70cSJohan Hedberg 
137479c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
137579c6c70cSJohan Hedberg 		goto unlock;
137679c6c70cSJohan Hedberg 
137751a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1378127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1379127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1380127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1381127178d2SJohan Hedberg 	}
1382127178d2SJohan Hedberg 
138379c6c70cSJohan Hedberg unlock:
1384127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1385a9de9248SMarcel Holtmann }
13861da177e4SLinus Torvalds 
1387769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1388769be974SMarcel Holtmann {
1389769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1390769be974SMarcel Holtmann 	struct hci_conn *conn;
1391769be974SMarcel Holtmann 
1392769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1393769be974SMarcel Holtmann 
1394769be974SMarcel Holtmann 	if (!status)
1395769be974SMarcel Holtmann 		return;
1396769be974SMarcel Holtmann 
1397769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1398769be974SMarcel Holtmann 	if (!cp)
1399769be974SMarcel Holtmann 		return;
1400769be974SMarcel Holtmann 
1401769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1402769be974SMarcel Holtmann 
1403769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1404769be974SMarcel Holtmann 	if (conn) {
1405769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1406769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1407769be974SMarcel Holtmann 			hci_conn_put(conn);
1408769be974SMarcel Holtmann 		}
1409769be974SMarcel Holtmann 	}
1410769be974SMarcel Holtmann 
1411769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1412769be974SMarcel Holtmann }
1413769be974SMarcel Holtmann 
1414769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1415769be974SMarcel Holtmann {
1416769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1417769be974SMarcel Holtmann 	struct hci_conn *conn;
1418769be974SMarcel Holtmann 
1419769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1420769be974SMarcel Holtmann 
1421769be974SMarcel Holtmann 	if (!status)
1422769be974SMarcel Holtmann 		return;
1423769be974SMarcel Holtmann 
1424769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1425769be974SMarcel Holtmann 	if (!cp)
1426769be974SMarcel Holtmann 		return;
1427769be974SMarcel Holtmann 
1428769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1429769be974SMarcel Holtmann 
1430769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1431769be974SMarcel Holtmann 	if (conn) {
1432769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1433769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1434769be974SMarcel Holtmann 			hci_conn_put(conn);
1435769be974SMarcel Holtmann 		}
1436769be974SMarcel Holtmann 	}
1437769be974SMarcel Holtmann 
1438769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1439769be974SMarcel Holtmann }
1440769be974SMarcel Holtmann 
1441a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1442a9de9248SMarcel Holtmann {
1443b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1444b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1445b6a0dc82SMarcel Holtmann 	__u16 handle;
1446b6a0dc82SMarcel Holtmann 
1447a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1448b6a0dc82SMarcel Holtmann 
1449b6a0dc82SMarcel Holtmann 	if (!status)
1450b6a0dc82SMarcel Holtmann 		return;
1451b6a0dc82SMarcel Holtmann 
1452b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1453b6a0dc82SMarcel Holtmann 	if (!cp)
1454b6a0dc82SMarcel Holtmann 		return;
1455b6a0dc82SMarcel Holtmann 
1456b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1457b6a0dc82SMarcel Holtmann 
1458b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1459b6a0dc82SMarcel Holtmann 
1460b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1461b6a0dc82SMarcel Holtmann 
1462b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14635a08ecceSAndrei Emeltchenko 	if (acl) {
14645a08ecceSAndrei Emeltchenko 		sco = acl->link;
14655a08ecceSAndrei Emeltchenko 		if (sco) {
1466b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1467b6a0dc82SMarcel Holtmann 
1468b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1469b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1470b6a0dc82SMarcel Holtmann 		}
14715a08ecceSAndrei Emeltchenko 	}
1472b6a0dc82SMarcel Holtmann 
1473b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1474a9de9248SMarcel Holtmann }
1475a9de9248SMarcel Holtmann 
1476a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1477a9de9248SMarcel Holtmann {
1478a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
147904837f64SMarcel Holtmann 	struct hci_conn *conn;
148004837f64SMarcel Holtmann 
1481a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1482a9de9248SMarcel Holtmann 
1483a9de9248SMarcel Holtmann 	if (!status)
1484a9de9248SMarcel Holtmann 		return;
1485a9de9248SMarcel Holtmann 
1486a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
148704837f64SMarcel Holtmann 	if (!cp)
1488a9de9248SMarcel Holtmann 		return;
148904837f64SMarcel Holtmann 
149004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
149104837f64SMarcel Holtmann 
149204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1493e73439d8SMarcel Holtmann 	if (conn) {
149451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
149504837f64SMarcel Holtmann 
149651a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1497e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1498e73439d8SMarcel Holtmann 	}
1499e73439d8SMarcel Holtmann 
150004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
150104837f64SMarcel Holtmann }
150204837f64SMarcel Holtmann 
1503a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1504a9de9248SMarcel Holtmann {
1505a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
150604837f64SMarcel Holtmann 	struct hci_conn *conn;
150704837f64SMarcel Holtmann 
1508a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1509a9de9248SMarcel Holtmann 
1510a9de9248SMarcel Holtmann 	if (!status)
1511a9de9248SMarcel Holtmann 		return;
1512a9de9248SMarcel Holtmann 
1513a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
151404837f64SMarcel Holtmann 	if (!cp)
1515a9de9248SMarcel Holtmann 		return;
151604837f64SMarcel Holtmann 
151704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
151804837f64SMarcel Holtmann 
151904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1520e73439d8SMarcel Holtmann 	if (conn) {
152151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
152204837f64SMarcel Holtmann 
152351a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1524e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1525e73439d8SMarcel Holtmann 	}
1526e73439d8SMarcel Holtmann 
152704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
152804837f64SMarcel Holtmann }
152904837f64SMarcel Holtmann 
1530fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1531fcd89c09SVille Tervo {
1532fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1533fcd89c09SVille Tervo 	struct hci_conn *conn;
1534fcd89c09SVille Tervo 
1535fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1536fcd89c09SVille Tervo 
1537fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1538fcd89c09SVille Tervo 	if (!cp)
1539fcd89c09SVille Tervo 		return;
1540fcd89c09SVille Tervo 
1541fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1542fcd89c09SVille Tervo 
1543fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1544fcd89c09SVille Tervo 
1545fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1546fcd89c09SVille Tervo 		conn);
1547fcd89c09SVille Tervo 
1548fcd89c09SVille Tervo 	if (status) {
1549fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1550fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1551fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1552fcd89c09SVille Tervo 			hci_conn_del(conn);
1553fcd89c09SVille Tervo 		}
1554fcd89c09SVille Tervo 	} else {
1555fcd89c09SVille Tervo 		if (!conn) {
1556fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
155729b7988aSAndre Guedes 			if (conn) {
155829b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1559a0c808b3SJohan Hedberg 				conn->out = true;
156029b7988aSAndre Guedes 			} else {
1561fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1562fcd89c09SVille Tervo 			}
1563fcd89c09SVille Tervo 		}
156429b7988aSAndre Guedes 	}
1565fcd89c09SVille Tervo 
1566fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1567fcd89c09SVille Tervo }
1568fcd89c09SVille Tervo 
1569a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1570a7a595f6SVinicius Costa Gomes {
1571a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1572a7a595f6SVinicius Costa Gomes }
1573a7a595f6SVinicius Costa Gomes 
15741da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15751da177e4SLinus Torvalds {
15761da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
157730dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
157830dc78e1SJohan Hedberg 	struct inquiry_entry *e;
15791da177e4SLinus Torvalds 
15801da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
15811da177e4SLinus Torvalds 
158223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
15836bd57416SMarcel Holtmann 
1584a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
158589352e7dSAndre Guedes 
158689352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
158789352e7dSAndre Guedes 		return;
158889352e7dSAndre Guedes 
1589a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
159030dc78e1SJohan Hedberg 		return;
159130dc78e1SJohan Hedberg 
159256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
159330dc78e1SJohan Hedberg 
159430dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_INQUIRY)
159530dc78e1SJohan Hedberg 		goto unlock;
159630dc78e1SJohan Hedberg 
159730dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1598ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
159930dc78e1SJohan Hedberg 		goto unlock;
160030dc78e1SJohan Hedberg 	}
160130dc78e1SJohan Hedberg 
160230dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
160330dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
160430dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
160530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
160630dc78e1SJohan Hedberg 	} else {
160730dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
160830dc78e1SJohan Hedberg 	}
160930dc78e1SJohan Hedberg 
161030dc78e1SJohan Hedberg unlock:
161156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16121da177e4SLinus Torvalds }
16131da177e4SLinus Torvalds 
16141da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16151da177e4SLinus Torvalds {
161645bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1617a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16181da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16191da177e4SLinus Torvalds 
16201da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16211da177e4SLinus Torvalds 
162245bb4bf0SMarcel Holtmann 	if (!num_rsp)
162345bb4bf0SMarcel Holtmann 		return;
162445bb4bf0SMarcel Holtmann 
16251da177e4SLinus Torvalds 	hci_dev_lock(hdev);
162645bb4bf0SMarcel Holtmann 
1627e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
16283175405bSJohan Hedberg 		bool name_known;
16293175405bSJohan Hedberg 
16301da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16311da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16321da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16331da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16341da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16351da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16361da177e4SLinus Torvalds 		data.rssi		= 0x00;
163741a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16383175405bSJohan Hedberg 
16393175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false);
164048264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
16417d262f86SAndre Guedes 					info->dev_class, 0, !name_known,
16427d262f86SAndre Guedes 					NULL, 0);
16431da177e4SLinus Torvalds 	}
164445bb4bf0SMarcel Holtmann 
16451da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16461da177e4SLinus Torvalds }
16471da177e4SLinus Torvalds 
1648a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16491da177e4SLinus Torvalds {
1650a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1651a9de9248SMarcel Holtmann 	struct hci_conn *conn;
16521da177e4SLinus Torvalds 
1653a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
165445bb4bf0SMarcel Holtmann 
16551da177e4SLinus Torvalds 	hci_dev_lock(hdev);
165645bb4bf0SMarcel Holtmann 
1657a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16589499237aSMarcel Holtmann 	if (!conn) {
16599499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16609499237aSMarcel Holtmann 			goto unlock;
16619499237aSMarcel Holtmann 
16629499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1663a9de9248SMarcel Holtmann 		if (!conn)
1664a9de9248SMarcel Holtmann 			goto unlock;
166545bb4bf0SMarcel Holtmann 
16669499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16679499237aSMarcel Holtmann 	}
16689499237aSMarcel Holtmann 
1669a9de9248SMarcel Holtmann 	if (!ev->status) {
1670a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1671769be974SMarcel Holtmann 
1672769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1673769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1674769be974SMarcel Holtmann 			hci_conn_hold(conn);
1675052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1676769be974SMarcel Holtmann 		} else
1677a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1678a9de9248SMarcel Holtmann 
16799eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
16807d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
16817d0db0a3SMarcel Holtmann 
1682a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1683a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1684a9de9248SMarcel Holtmann 
1685a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1686a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1687a9de9248SMarcel Holtmann 
1688a9de9248SMarcel Holtmann 		/* Get remote features */
1689a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1690a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1691a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1692769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1693769be974SMarcel Holtmann 							sizeof(cp), &cp);
169445bb4bf0SMarcel Holtmann 		}
1695a9de9248SMarcel Holtmann 
1696a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1697d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1698a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1699a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1700a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1701a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1702a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1703a9de9248SMarcel Holtmann 		}
170417d5c04cSJohan Hedberg 	} else {
1705a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
170617d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1707744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
170848264f06SJohan Hedberg 						conn->dst_type, ev->status);
170917d5c04cSJohan Hedberg 	}
171045bb4bf0SMarcel Holtmann 
1711e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1712e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
171345bb4bf0SMarcel Holtmann 
1714769be974SMarcel Holtmann 	if (ev->status) {
1715a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1716a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1717c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1718c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1719a9de9248SMarcel Holtmann 
1720a9de9248SMarcel Holtmann unlock:
17211da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1722a9de9248SMarcel Holtmann 
1723a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
17241da177e4SLinus Torvalds }
17251da177e4SLinus Torvalds 
17261da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17271da177e4SLinus Torvalds {
1728a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17291da177e4SLinus Torvalds 	int mask = hdev->link_mode;
17301da177e4SLinus Torvalds 
1731a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
17321da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
17331da177e4SLinus Torvalds 
17341da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
17351da177e4SLinus Torvalds 
1736138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1737138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
17381da177e4SLinus Torvalds 		/* Connection accepted */
1739c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17401da177e4SLinus Torvalds 		struct hci_conn *conn;
17411da177e4SLinus Torvalds 
17421da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1743b6a0dc82SMarcel Holtmann 
1744cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1745cc11b9c1SAndrei Emeltchenko 		if (ie)
1746c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1747c7bdd502SMarcel Holtmann 
17481da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17491da177e4SLinus Torvalds 		if (!conn) {
1750cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1751cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1752893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17531da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17541da177e4SLinus Torvalds 				return;
17551da177e4SLinus Torvalds 			}
17561da177e4SLinus Torvalds 		}
1757b6a0dc82SMarcel Holtmann 
17581da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
17591da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1760b6a0dc82SMarcel Holtmann 
17611da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17621da177e4SLinus Torvalds 
1763b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1764b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1765b6a0dc82SMarcel Holtmann 
17661da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17671da177e4SLinus Torvalds 
17681da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17691da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17701da177e4SLinus Torvalds 			else
17711da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17721da177e4SLinus Torvalds 
1773b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1774b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1775b6a0dc82SMarcel Holtmann 		} else {
1776b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1777b6a0dc82SMarcel Holtmann 
1778b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1779a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1780b6a0dc82SMarcel Holtmann 
1781b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1782b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1783b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1784b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1785b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1786b6a0dc82SMarcel Holtmann 
1787b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1788b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1789b6a0dc82SMarcel Holtmann 		}
17901da177e4SLinus Torvalds 	} else {
17911da177e4SLinus Torvalds 		/* Connection rejected */
17921da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
17931da177e4SLinus Torvalds 
17941da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
17959f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1796a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
17971da177e4SLinus Torvalds 	}
17981da177e4SLinus Torvalds }
17991da177e4SLinus Torvalds 
18001da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18011da177e4SLinus Torvalds {
1802a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
180304837f64SMarcel Holtmann 	struct hci_conn *conn;
18041da177e4SLinus Torvalds 
18051da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
18061da177e4SLinus Torvalds 
18071da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18081da177e4SLinus Torvalds 
180904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1810f7520543SJohan Hedberg 	if (!conn)
1811f7520543SJohan Hedberg 		goto unlock;
1812f7520543SJohan Hedberg 
181337d9ef76SJohan Hedberg 	if (ev->status == 0)
18141da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18157d0db0a3SMarcel Holtmann 
1816b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1817b644ba33SJohan Hedberg 			(conn->type == ACL_LINK || conn->type == LE_LINK)) {
181837d9ef76SJohan Hedberg 		if (ev->status != 0)
181937d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
182037d9ef76SJohan Hedberg 		else
1821afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
182248264f06SJohan Hedberg 							conn->dst_type);
182337d9ef76SJohan Hedberg 	}
1824f7520543SJohan Hedberg 
182537d9ef76SJohan Hedberg 	if (ev->status == 0) {
18262950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
18271da177e4SLinus Torvalds 		hci_conn_del(conn);
182837d9ef76SJohan Hedberg 	}
18291da177e4SLinus Torvalds 
1830f7520543SJohan Hedberg unlock:
18311da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18321da177e4SLinus Torvalds }
18331da177e4SLinus Torvalds 
1834a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1835a9de9248SMarcel Holtmann {
1836a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1837a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1838a9de9248SMarcel Holtmann 
1839a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1840a9de9248SMarcel Holtmann 
1841a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1842a9de9248SMarcel Holtmann 
1843a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1844d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1845d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1846d7556e20SWaldemar Rymarkiewicz 
1847765c2a96SJohan Hedberg 	if (!ev->status) {
1848aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
184951a8efd7SJohan Hedberg 				test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1850d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
185119f8def0SWaldemar Rymarkiewicz 		} else {
1852a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1853765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
185419f8def0SWaldemar Rymarkiewicz 		}
18552a611692SJohan Hedberg 	} else {
1856744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
18572a611692SJohan Hedberg 	}
1858a9de9248SMarcel Holtmann 
185951a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
186051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1861a9de9248SMarcel Holtmann 
1862f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1863aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1864f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1865f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1866f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1867d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1868d7556e20SWaldemar Rymarkiewicz 									&cp);
1869f8558555SMarcel Holtmann 		} else {
1870f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1871f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1872f8558555SMarcel Holtmann 			hci_conn_put(conn);
1873f8558555SMarcel Holtmann 		}
1874052b30b0SMarcel Holtmann 	} else {
1875a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1876a9de9248SMarcel Holtmann 
1877052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1878052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1879052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1880052b30b0SMarcel Holtmann 	}
1881052b30b0SMarcel Holtmann 
188251a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1883a9de9248SMarcel Holtmann 		if (!ev->status) {
1884a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1885f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1886f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1887d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1888d7556e20SWaldemar Rymarkiewicz 									&cp);
1889a9de9248SMarcel Holtmann 		} else {
189051a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1891a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1892a9de9248SMarcel Holtmann 		}
1893a9de9248SMarcel Holtmann 	}
1894a9de9248SMarcel Holtmann 
1895d7556e20SWaldemar Rymarkiewicz unlock:
1896a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1897a9de9248SMarcel Holtmann }
1898a9de9248SMarcel Holtmann 
1899a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1900a9de9248SMarcel Holtmann {
1901127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1902127178d2SJohan Hedberg 	struct hci_conn *conn;
1903127178d2SJohan Hedberg 
1904a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1905a9de9248SMarcel Holtmann 
1906a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1907127178d2SJohan Hedberg 
1908127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1909127178d2SJohan Hedberg 
1910127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1911b644ba33SJohan Hedberg 
1912b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1913b644ba33SJohan Hedberg 		goto check_auth;
1914b644ba33SJohan Hedberg 
1915b644ba33SJohan Hedberg 	if (ev->status == 0)
1916b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1917b644ba33SJohan Hedberg 					strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1918b644ba33SJohan Hedberg 	else
1919b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1920b644ba33SJohan Hedberg 
1921b644ba33SJohan Hedberg check_auth:
192279c6c70cSJohan Hedberg 	if (!conn)
192379c6c70cSJohan Hedberg 		goto unlock;
192479c6c70cSJohan Hedberg 
192579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
192679c6c70cSJohan Hedberg 		goto unlock;
192779c6c70cSJohan Hedberg 
192851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1929127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1930127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1931127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1932127178d2SJohan Hedberg 	}
1933127178d2SJohan Hedberg 
193479c6c70cSJohan Hedberg unlock:
1935127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1936a9de9248SMarcel Holtmann }
1937a9de9248SMarcel Holtmann 
1938a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1939a9de9248SMarcel Holtmann {
1940a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1941a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1942a9de9248SMarcel Holtmann 
1943a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1944a9de9248SMarcel Holtmann 
1945a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1946a9de9248SMarcel Holtmann 
1947a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1948a9de9248SMarcel Holtmann 	if (conn) {
1949a9de9248SMarcel Holtmann 		if (!ev->status) {
1950ae293196SMarcel Holtmann 			if (ev->encrypt) {
1951ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1952ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1953a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1954da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1955ae293196SMarcel Holtmann 			} else
1956a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1957a9de9248SMarcel Holtmann 		}
1958a9de9248SMarcel Holtmann 
195951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1960a9de9248SMarcel Holtmann 
1961f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1962f8558555SMarcel Holtmann 			if (!ev->status)
1963f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1964f8558555SMarcel Holtmann 
1965f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1966f8558555SMarcel Holtmann 			hci_conn_put(conn);
1967f8558555SMarcel Holtmann 		} else
1968a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1969a9de9248SMarcel Holtmann 	}
1970a9de9248SMarcel Holtmann 
1971a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1972a9de9248SMarcel Holtmann }
1973a9de9248SMarcel Holtmann 
1974a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1975a9de9248SMarcel Holtmann {
1976a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1977a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1978a9de9248SMarcel Holtmann 
1979a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1980a9de9248SMarcel Holtmann 
1981a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1982a9de9248SMarcel Holtmann 
1983a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1984a9de9248SMarcel Holtmann 	if (conn) {
1985a9de9248SMarcel Holtmann 		if (!ev->status)
1986a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1987a9de9248SMarcel Holtmann 
198851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1989a9de9248SMarcel Holtmann 
1990a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1991a9de9248SMarcel Holtmann 	}
1992a9de9248SMarcel Holtmann 
1993a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1994a9de9248SMarcel Holtmann }
1995a9de9248SMarcel Holtmann 
1996a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1997a9de9248SMarcel Holtmann {
1998a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1999a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2000a9de9248SMarcel Holtmann 
2001a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2002a9de9248SMarcel Holtmann 
2003a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2004a9de9248SMarcel Holtmann 
2005a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2006ccd556feSJohan Hedberg 	if (!conn)
2007ccd556feSJohan Hedberg 		goto unlock;
2008ccd556feSJohan Hedberg 
2009769be974SMarcel Holtmann 	if (!ev->status)
2010a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2011a9de9248SMarcel Holtmann 
2012ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2013ccd556feSJohan Hedberg 		goto unlock;
2014ccd556feSJohan Hedberg 
2015ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2016769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2017769be974SMarcel Holtmann 		cp.handle = ev->handle;
2018769be974SMarcel Holtmann 		cp.page = 0x01;
2019ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2020769be974SMarcel Holtmann 							sizeof(cp), &cp);
2021392599b9SJohan Hedberg 		goto unlock;
2022392599b9SJohan Hedberg 	}
2023392599b9SJohan Hedberg 
2024127178d2SJohan Hedberg 	if (!ev->status) {
2025127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2026127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2027127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2028127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2029127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2030b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2031b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2032b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2033b644ba33SJohan Hedberg 						conn->dev_class);
2034392599b9SJohan Hedberg 
2035127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2036769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2037769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2038769be974SMarcel Holtmann 		hci_conn_put(conn);
2039769be974SMarcel Holtmann 	}
2040769be974SMarcel Holtmann 
2041ccd556feSJohan Hedberg unlock:
2042a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2043a9de9248SMarcel Holtmann }
2044a9de9248SMarcel Holtmann 
2045a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2046a9de9248SMarcel Holtmann {
2047a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2048a9de9248SMarcel Holtmann }
2049a9de9248SMarcel Holtmann 
2050a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2051a9de9248SMarcel Holtmann {
2052a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2053a9de9248SMarcel Holtmann }
2054a9de9248SMarcel Holtmann 
2055a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2056a9de9248SMarcel Holtmann {
2057a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2058a9de9248SMarcel Holtmann 	__u16 opcode;
2059a9de9248SMarcel Holtmann 
2060a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2061a9de9248SMarcel Holtmann 
2062a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2063a9de9248SMarcel Holtmann 
2064a9de9248SMarcel Holtmann 	switch (opcode) {
2065a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2066a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2067a9de9248SMarcel Holtmann 		break;
2068a9de9248SMarcel Holtmann 
2069a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2070a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2071a9de9248SMarcel Holtmann 		break;
2072a9de9248SMarcel Holtmann 
2073a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2074a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2075a9de9248SMarcel Holtmann 		break;
2076a9de9248SMarcel Holtmann 
2077a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2078a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2079a9de9248SMarcel Holtmann 		break;
2080a9de9248SMarcel Holtmann 
2081e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2082e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2083e4e8e37cSMarcel Holtmann 		break;
2084e4e8e37cSMarcel Holtmann 
2085a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2086a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2087a9de9248SMarcel Holtmann 		break;
2088a9de9248SMarcel Holtmann 
2089e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2090e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2091e4e8e37cSMarcel Holtmann 		break;
2092e4e8e37cSMarcel Holtmann 
2093e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2094e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2095e4e8e37cSMarcel Holtmann 		break;
2096e4e8e37cSMarcel Holtmann 
2097a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2098a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2099a9de9248SMarcel Holtmann 		break;
2100a9de9248SMarcel Holtmann 
2101a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2102a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2103a9de9248SMarcel Holtmann 		break;
2104a9de9248SMarcel Holtmann 
2105a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2106a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2107a9de9248SMarcel Holtmann 		break;
2108a9de9248SMarcel Holtmann 
2109a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2110a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2111a9de9248SMarcel Holtmann 		break;
2112a9de9248SMarcel Holtmann 
2113a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2114a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2115a9de9248SMarcel Holtmann 		break;
2116a9de9248SMarcel Holtmann 
2117a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2118a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2119a9de9248SMarcel Holtmann 		break;
2120a9de9248SMarcel Holtmann 
2121a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2122a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2123a9de9248SMarcel Holtmann 		break;
2124a9de9248SMarcel Holtmann 
2125a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2126a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2127a9de9248SMarcel Holtmann 		break;
2128a9de9248SMarcel Holtmann 
2129a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2130a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2131a9de9248SMarcel Holtmann 		break;
2132a9de9248SMarcel Holtmann 
2133a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2134a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2135a9de9248SMarcel Holtmann 		break;
2136a9de9248SMarcel Holtmann 
2137a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2138a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2139a9de9248SMarcel Holtmann 		break;
2140a9de9248SMarcel Holtmann 
2141333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
2142333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
2143333140b5SMarcel Holtmann 		break;
2144333140b5SMarcel Holtmann 
2145333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2146333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2147333140b5SMarcel Holtmann 		break;
2148333140b5SMarcel Holtmann 
2149a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2150a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2151a9de9248SMarcel Holtmann 		break;
2152a9de9248SMarcel Holtmann 
2153a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2154a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2155a9de9248SMarcel Holtmann 		break;
2156a9de9248SMarcel Holtmann 
2157a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2158a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2159a9de9248SMarcel Holtmann 		break;
2160a9de9248SMarcel Holtmann 
2161971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2162971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2163971e3a4bSAndre Guedes 		break;
2164971e3a4bSAndre Guedes 
2165a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2166a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2167a9de9248SMarcel Holtmann 		break;
2168a9de9248SMarcel Holtmann 
2169a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2170a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2171a9de9248SMarcel Holtmann 		break;
2172a9de9248SMarcel Holtmann 
2173350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2174350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2175350ee4cfSAndrei Emeltchenko 		break;
2176350ee4cfSAndrei Emeltchenko 
217723bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
217823bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
217923bb5763SJohan Hedberg 		break;
218023bb5763SJohan Hedberg 
21811e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
21821e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
21831e89cffbSAndrei Emeltchenko 		break;
21841e89cffbSAndrei Emeltchenko 
2185928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2186928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2187928abaa7SAndrei Emeltchenko 		break;
2188928abaa7SAndrei Emeltchenko 
2189b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2190b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2191b0916ea0SJohan Hedberg 		break;
2192b0916ea0SJohan Hedberg 
2193d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2194d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2195d5859e22SJohan Hedberg 		break;
2196d5859e22SJohan Hedberg 
2197d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2198d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2199d5859e22SJohan Hedberg 		break;
2200d5859e22SJohan Hedberg 
2201d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2202d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2203d5859e22SJohan Hedberg 		break;
2204d5859e22SJohan Hedberg 
2205d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2206d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2207d5859e22SJohan Hedberg 		break;
2208d5859e22SJohan Hedberg 
2209980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2210980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2211980e1a53SJohan Hedberg 		break;
2212980e1a53SJohan Hedberg 
2213980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2214980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2215980e1a53SJohan Hedberg 		break;
2216980e1a53SJohan Hedberg 
2217c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2218c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2219c35938b2SSzymon Janc 		break;
2220c35938b2SSzymon Janc 
22216ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22226ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22236ed58ec5SVille Tervo 		break;
22246ed58ec5SVille Tervo 
2225a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2226a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2227a5c29683SJohan Hedberg 		break;
2228a5c29683SJohan Hedberg 
2229a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2230a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2231a5c29683SJohan Hedberg 		break;
2232a5c29683SJohan Hedberg 
22331143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
22341143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
22351143d458SBrian Gix 		break;
22361143d458SBrian Gix 
22371143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
22381143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
223907f7fa5dSAndre Guedes 
224007f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
224107f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
22421143d458SBrian Gix 		break;
22431143d458SBrian Gix 
2244eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2245eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2246eb9d91f5SAndre Guedes 		break;
2247eb9d91f5SAndre Guedes 
2248a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2249a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2250a7a595f6SVinicius Costa Gomes 		break;
2251a7a595f6SVinicius Costa Gomes 
2252a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2253a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2254a7a595f6SVinicius Costa Gomes 		break;
2255a7a595f6SVinicius Costa Gomes 
2256f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2257f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2258f9b49306SAndre Guedes 		break;
2259f9b49306SAndre Guedes 
2260a9de9248SMarcel Holtmann 	default:
2261a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2262a9de9248SMarcel Holtmann 		break;
2263a9de9248SMarcel Holtmann 	}
2264a9de9248SMarcel Holtmann 
22656bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
22666bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
22676bd32326SVille Tervo 
2268a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2269a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2270a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2271c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2272a9de9248SMarcel Holtmann 	}
2273a9de9248SMarcel Holtmann }
2274a9de9248SMarcel Holtmann 
2275a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2276a9de9248SMarcel Holtmann {
2277a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2278a9de9248SMarcel Holtmann 	__u16 opcode;
2279a9de9248SMarcel Holtmann 
2280a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2281a9de9248SMarcel Holtmann 
2282a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2283a9de9248SMarcel Holtmann 
2284a9de9248SMarcel Holtmann 	switch (opcode) {
2285a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2286a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2287a9de9248SMarcel Holtmann 		break;
2288a9de9248SMarcel Holtmann 
2289a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2290a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2291a9de9248SMarcel Holtmann 		break;
2292a9de9248SMarcel Holtmann 
2293a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2294a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2295a9de9248SMarcel Holtmann 		break;
2296a9de9248SMarcel Holtmann 
2297f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2298f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2299f8558555SMarcel Holtmann 		break;
2300f8558555SMarcel Holtmann 
2301f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2302f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2303f8558555SMarcel Holtmann 		break;
2304f8558555SMarcel Holtmann 
2305a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2306a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2307a9de9248SMarcel Holtmann 		break;
2308a9de9248SMarcel Holtmann 
2309769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2310769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2311769be974SMarcel Holtmann 		break;
2312769be974SMarcel Holtmann 
2313769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2314769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2315769be974SMarcel Holtmann 		break;
2316769be974SMarcel Holtmann 
2317a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2318a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2319a9de9248SMarcel Holtmann 		break;
2320a9de9248SMarcel Holtmann 
2321a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2322a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2323a9de9248SMarcel Holtmann 		break;
2324a9de9248SMarcel Holtmann 
2325a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2326a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2327a9de9248SMarcel Holtmann 		break;
2328a9de9248SMarcel Holtmann 
23298962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
23308962ee74SJohan Hedberg 		if (ev->status != 0)
233137d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
23328962ee74SJohan Hedberg 		break;
23338962ee74SJohan Hedberg 
2334fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2335fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2336fcd89c09SVille Tervo 		break;
2337fcd89c09SVille Tervo 
2338a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2339a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2340a7a595f6SVinicius Costa Gomes 		break;
2341a7a595f6SVinicius Costa Gomes 
2342a9de9248SMarcel Holtmann 	default:
2343a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2344a9de9248SMarcel Holtmann 		break;
2345a9de9248SMarcel Holtmann 	}
2346a9de9248SMarcel Holtmann 
23476bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23486bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23496bd32326SVille Tervo 
235010572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2351a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2352a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2353c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2354a9de9248SMarcel Holtmann 	}
2355a9de9248SMarcel Holtmann }
2356a9de9248SMarcel Holtmann 
2357a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2358a9de9248SMarcel Holtmann {
2359a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2360a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2361a9de9248SMarcel Holtmann 
2362a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2363a9de9248SMarcel Holtmann 
2364a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2365a9de9248SMarcel Holtmann 
2366a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2367a9de9248SMarcel Holtmann 	if (conn) {
2368a9de9248SMarcel Holtmann 		if (!ev->status) {
2369a9de9248SMarcel Holtmann 			if (ev->role)
2370a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2371a9de9248SMarcel Holtmann 			else
2372a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2373a9de9248SMarcel Holtmann 		}
2374a9de9248SMarcel Holtmann 
237551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2376a9de9248SMarcel Holtmann 
2377a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2378a9de9248SMarcel Holtmann 	}
2379a9de9248SMarcel Holtmann 
2380a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2381a9de9248SMarcel Holtmann }
2382a9de9248SMarcel Holtmann 
23831da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
23841da177e4SLinus Torvalds {
2385a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
23861da177e4SLinus Torvalds 	int i;
23871da177e4SLinus Torvalds 
238832ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
238932ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
239032ac5b9bSAndrei Emeltchenko 		return;
239132ac5b9bSAndrei Emeltchenko 	}
239232ac5b9bSAndrei Emeltchenko 
2393c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2394c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
23951da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
23961da177e4SLinus Torvalds 		return;
23971da177e4SLinus Torvalds 	}
23981da177e4SLinus Torvalds 
2399c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2400c5993de8SAndrei Emeltchenko 
2401613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2402613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24031da177e4SLinus Torvalds 		struct hci_conn *conn;
24041da177e4SLinus Torvalds 		__u16  handle, count;
24051da177e4SLinus Torvalds 
2406613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2407613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24081da177e4SLinus Torvalds 
24091da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2410f4280918SAndrei Emeltchenko 		if (!conn)
2411f4280918SAndrei Emeltchenko 			continue;
2412f4280918SAndrei Emeltchenko 
24131da177e4SLinus Torvalds 		conn->sent -= count;
24141da177e4SLinus Torvalds 
2415f4280918SAndrei Emeltchenko 		switch (conn->type) {
2416f4280918SAndrei Emeltchenko 		case ACL_LINK:
241770f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
241870f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24191da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2420f4280918SAndrei Emeltchenko 			break;
2421f4280918SAndrei Emeltchenko 
2422f4280918SAndrei Emeltchenko 		case LE_LINK:
24236ed58ec5SVille Tervo 			if (hdev->le_pkts) {
24246ed58ec5SVille Tervo 				hdev->le_cnt += count;
24256ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
24266ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
24276ed58ec5SVille Tervo 			} else {
24286ed58ec5SVille Tervo 				hdev->acl_cnt += count;
24296ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
24306ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
24316ed58ec5SVille Tervo 			}
2432f4280918SAndrei Emeltchenko 			break;
2433f4280918SAndrei Emeltchenko 
2434f4280918SAndrei Emeltchenko 		case SCO_LINK:
243570f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
243670f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
24375b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2438f4280918SAndrei Emeltchenko 			break;
2439f4280918SAndrei Emeltchenko 
2440f4280918SAndrei Emeltchenko 		default:
2441f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2442f4280918SAndrei Emeltchenko 			break;
24431da177e4SLinus Torvalds 		}
24441da177e4SLinus Torvalds 	}
2445a9de9248SMarcel Holtmann 
24463eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
24471da177e4SLinus Torvalds }
24481da177e4SLinus Torvalds 
244925e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
245025e89e99SAndrei Emeltchenko 							struct sk_buff *skb)
245125e89e99SAndrei Emeltchenko {
245225e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
245325e89e99SAndrei Emeltchenko 	int i;
245425e89e99SAndrei Emeltchenko 
245525e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
245625e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
245725e89e99SAndrei Emeltchenko 		return;
245825e89e99SAndrei Emeltchenko 	}
245925e89e99SAndrei Emeltchenko 
246025e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
246125e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
246225e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
246325e89e99SAndrei Emeltchenko 		return;
246425e89e99SAndrei Emeltchenko 	}
246525e89e99SAndrei Emeltchenko 
246625e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
246725e89e99SAndrei Emeltchenko 								ev->num_hndl);
246825e89e99SAndrei Emeltchenko 
246925e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
247025e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
247125e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
247225e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
247325e89e99SAndrei Emeltchenko 
247425e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
247525e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
247625e89e99SAndrei Emeltchenko 
247725e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
247825e89e99SAndrei Emeltchenko 		if (!conn)
247925e89e99SAndrei Emeltchenko 			continue;
248025e89e99SAndrei Emeltchenko 
248125e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
248225e89e99SAndrei Emeltchenko 
248325e89e99SAndrei Emeltchenko 		switch (conn->type) {
248425e89e99SAndrei Emeltchenko 		case ACL_LINK:
248525e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
248625e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
248725e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
248825e89e99SAndrei Emeltchenko 			break;
248925e89e99SAndrei Emeltchenko 
249025e89e99SAndrei Emeltchenko 		default:
249125e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
249225e89e99SAndrei Emeltchenko 			break;
249325e89e99SAndrei Emeltchenko 		}
249425e89e99SAndrei Emeltchenko 	}
249525e89e99SAndrei Emeltchenko 
249625e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
249725e89e99SAndrei Emeltchenko }
249825e89e99SAndrei Emeltchenko 
249904837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25001da177e4SLinus Torvalds {
2501a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
250204837f64SMarcel Holtmann 	struct hci_conn *conn;
25031da177e4SLinus Torvalds 
25041da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
25051da177e4SLinus Torvalds 
25061da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25071da177e4SLinus Torvalds 
250804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
250904837f64SMarcel Holtmann 	if (conn) {
251004837f64SMarcel Holtmann 		conn->mode = ev->mode;
251104837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
251204837f64SMarcel Holtmann 
251351a8efd7SJohan Hedberg 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
251404837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
251558a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
251604837f64SMarcel Holtmann 			else
251758a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
251804837f64SMarcel Holtmann 		}
2519e73439d8SMarcel Holtmann 
252051a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2521e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
252204837f64SMarcel Holtmann 	}
252304837f64SMarcel Holtmann 
252404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
252504837f64SMarcel Holtmann }
252604837f64SMarcel Holtmann 
25271da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25281da177e4SLinus Torvalds {
2529052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2530052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2531052b30b0SMarcel Holtmann 
2532a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2533052b30b0SMarcel Holtmann 
2534052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2535052b30b0SMarcel Holtmann 
2536052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2537b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2538b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2539b6f98044SWaldemar Rymarkiewicz 
2540b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2541052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2542052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2543052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2544052b30b0SMarcel Holtmann 	}
2545052b30b0SMarcel Holtmann 
2546a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
254703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
254803b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2549a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2550a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2551a770bb5aSWaldemar Rymarkiewicz 
2552a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2553a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2554a770bb5aSWaldemar Rymarkiewicz 		else
2555a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2556a770bb5aSWaldemar Rymarkiewicz 
2557744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2558a770bb5aSWaldemar Rymarkiewicz 	}
2559980e1a53SJohan Hedberg 
2560b6f98044SWaldemar Rymarkiewicz unlock:
2561052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
25621da177e4SLinus Torvalds }
25631da177e4SLinus Torvalds 
25641da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25651da177e4SLinus Torvalds {
256655ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
256755ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
256855ed8ca1SJohan Hedberg 	struct hci_conn *conn;
256955ed8ca1SJohan Hedberg 	struct link_key *key;
257055ed8ca1SJohan Hedberg 
2571a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
257255ed8ca1SJohan Hedberg 
2573a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
257455ed8ca1SJohan Hedberg 		return;
257555ed8ca1SJohan Hedberg 
257655ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
257755ed8ca1SJohan Hedberg 
257855ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
257955ed8ca1SJohan Hedberg 	if (!key) {
258055ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
258155ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
258255ed8ca1SJohan Hedberg 		goto not_found;
258355ed8ca1SJohan Hedberg 	}
258455ed8ca1SJohan Hedberg 
258555ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
258655ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
258755ed8ca1SJohan Hedberg 
2588a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2589b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
259055ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
259155ed8ca1SJohan Hedberg 		goto not_found;
259255ed8ca1SJohan Hedberg 	}
259355ed8ca1SJohan Hedberg 
259455ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
259560b83f57SWaldemar Rymarkiewicz 	if (conn) {
259660b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
259760b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
259860b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
259955ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
260055ed8ca1SJohan Hedberg 			goto not_found;
260155ed8ca1SJohan Hedberg 		}
260255ed8ca1SJohan Hedberg 
260360b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
260460b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
260560b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
260660b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
260760b83f57SWaldemar Rymarkiewicz 			goto not_found;
260860b83f57SWaldemar Rymarkiewicz 		}
260960b83f57SWaldemar Rymarkiewicz 
261060b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
261160b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
261260b83f57SWaldemar Rymarkiewicz 	}
261360b83f57SWaldemar Rymarkiewicz 
261455ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
261555ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
261655ed8ca1SJohan Hedberg 
261755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
261855ed8ca1SJohan Hedberg 
261955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
262055ed8ca1SJohan Hedberg 
262155ed8ca1SJohan Hedberg 	return;
262255ed8ca1SJohan Hedberg 
262355ed8ca1SJohan Hedberg not_found:
262455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
262555ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
26261da177e4SLinus Torvalds }
26271da177e4SLinus Torvalds 
26281da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
26291da177e4SLinus Torvalds {
2630052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2631052b30b0SMarcel Holtmann 	struct hci_conn *conn;
263255ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2633052b30b0SMarcel Holtmann 
2634a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2635052b30b0SMarcel Holtmann 
2636052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2637052b30b0SMarcel Holtmann 
2638052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2639052b30b0SMarcel Holtmann 	if (conn) {
2640052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2641052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2642980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
264313d39315SWaldemar Rymarkiewicz 
264413d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
264513d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
264613d39315SWaldemar Rymarkiewicz 
2647052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2648052b30b0SMarcel Holtmann 	}
2649052b30b0SMarcel Holtmann 
2650a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2651d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
265255ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
265355ed8ca1SJohan Hedberg 
2654052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26551da177e4SLinus Torvalds }
26561da177e4SLinus Torvalds 
265704837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
265804837f64SMarcel Holtmann {
2659a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
266004837f64SMarcel Holtmann 	struct hci_conn *conn;
266104837f64SMarcel Holtmann 
266204837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
266304837f64SMarcel Holtmann 
266404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
266504837f64SMarcel Holtmann 
266604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
26671da177e4SLinus Torvalds 	if (conn && !ev->status) {
26681da177e4SLinus Torvalds 		struct inquiry_entry *ie;
26691da177e4SLinus Torvalds 
2670cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2671cc11b9c1SAndrei Emeltchenko 		if (ie) {
26721da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
26731da177e4SLinus Torvalds 			ie->timestamp = jiffies;
26741da177e4SLinus Torvalds 		}
26751da177e4SLinus Torvalds 	}
26761da177e4SLinus Torvalds 
26771da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
26781da177e4SLinus Torvalds }
26791da177e4SLinus Torvalds 
2680a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2681a8746417SMarcel Holtmann {
2682a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2683a8746417SMarcel Holtmann 	struct hci_conn *conn;
2684a8746417SMarcel Holtmann 
2685a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2686a8746417SMarcel Holtmann 
2687a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2688a8746417SMarcel Holtmann 
2689a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2690a8746417SMarcel Holtmann 	if (conn && !ev->status)
2691a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2692a8746417SMarcel Holtmann 
2693a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2694a8746417SMarcel Holtmann }
2695a8746417SMarcel Holtmann 
269685a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
269785a1e930SMarcel Holtmann {
2698a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
269985a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
270085a1e930SMarcel Holtmann 
270185a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
270285a1e930SMarcel Holtmann 
270385a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
270485a1e930SMarcel Holtmann 
2705cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2706cc11b9c1SAndrei Emeltchenko 	if (ie) {
270785a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
270885a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
270985a1e930SMarcel Holtmann 	}
271085a1e930SMarcel Holtmann 
271185a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
271285a1e930SMarcel Holtmann }
271385a1e930SMarcel Holtmann 
2714a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2715a9de9248SMarcel Holtmann {
2716a9de9248SMarcel Holtmann 	struct inquiry_data data;
2717a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
27183175405bSJohan Hedberg 	bool name_known;
2719a9de9248SMarcel Holtmann 
2720a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2721a9de9248SMarcel Holtmann 
2722a9de9248SMarcel Holtmann 	if (!num_rsp)
2723a9de9248SMarcel Holtmann 		return;
2724a9de9248SMarcel Holtmann 
2725a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2726a9de9248SMarcel Holtmann 
2727a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2728138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2729138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2730a9de9248SMarcel Holtmann 
2731e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2732a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2733a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2734a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2735a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2736a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2737a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2738a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
273941a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27403175405bSJohan Hedberg 
27413175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27423175405bSJohan Hedberg 								false);
274348264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2744e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27457d262f86SAndre Guedes 						!name_known, NULL, 0);
2746a9de9248SMarcel Holtmann 		}
2747a9de9248SMarcel Holtmann 	} else {
2748a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2749a9de9248SMarcel Holtmann 
2750e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2751a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2752a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2753a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2754a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2755a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2756a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2757a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
275841a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27593175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27603175405bSJohan Hedberg 								false);
276148264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2762e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27637d262f86SAndre Guedes 						!name_known, NULL, 0);
2764a9de9248SMarcel Holtmann 		}
2765a9de9248SMarcel Holtmann 	}
2766a9de9248SMarcel Holtmann 
2767a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2768a9de9248SMarcel Holtmann }
2769a9de9248SMarcel Holtmann 
2770a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2771a9de9248SMarcel Holtmann {
277241a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
277341a96212SMarcel Holtmann 	struct hci_conn *conn;
277441a96212SMarcel Holtmann 
2775a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
277641a96212SMarcel Holtmann 
277741a96212SMarcel Holtmann 	hci_dev_lock(hdev);
277841a96212SMarcel Holtmann 
277941a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2780ccd556feSJohan Hedberg 	if (!conn)
2781ccd556feSJohan Hedberg 		goto unlock;
2782ccd556feSJohan Hedberg 
2783769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
278441a96212SMarcel Holtmann 		struct inquiry_entry *ie;
278541a96212SMarcel Holtmann 
2786cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2787cc11b9c1SAndrei Emeltchenko 		if (ie)
278841a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
278941a96212SMarcel Holtmann 
279058a681efSJohan Hedberg 		if (ev->features[0] & 0x01)
279158a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
279241a96212SMarcel Holtmann 	}
279341a96212SMarcel Holtmann 
2794ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2795ccd556feSJohan Hedberg 		goto unlock;
2796ccd556feSJohan Hedberg 
2797127178d2SJohan Hedberg 	if (!ev->status) {
2798127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2799127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2800127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2801127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2802127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2803b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2804b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2805b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2806b644ba33SJohan Hedberg 						conn->dev_class);
2807392599b9SJohan Hedberg 
2808127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2809769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2810769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2811769be974SMarcel Holtmann 		hci_conn_put(conn);
2812769be974SMarcel Holtmann 	}
2813769be974SMarcel Holtmann 
2814ccd556feSJohan Hedberg unlock:
281541a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2816a9de9248SMarcel Holtmann }
2817a9de9248SMarcel Holtmann 
2818a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2819a9de9248SMarcel Holtmann {
2820b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2821b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2822b6a0dc82SMarcel Holtmann 
2823b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2824b6a0dc82SMarcel Holtmann 
2825b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2826b6a0dc82SMarcel Holtmann 
2827b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
28289dc0a3afSMarcel Holtmann 	if (!conn) {
28299dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
28309dc0a3afSMarcel Holtmann 			goto unlock;
28319dc0a3afSMarcel Holtmann 
28329dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2833b6a0dc82SMarcel Holtmann 		if (!conn)
2834b6a0dc82SMarcel Holtmann 			goto unlock;
2835b6a0dc82SMarcel Holtmann 
28369dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
28379dc0a3afSMarcel Holtmann 	}
28389dc0a3afSMarcel Holtmann 
2839732547f9SMarcel Holtmann 	switch (ev->status) {
2840732547f9SMarcel Holtmann 	case 0x00:
2841732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2842732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2843732547f9SMarcel Holtmann 
28449eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2845732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2846732547f9SMarcel Holtmann 		break;
2847732547f9SMarcel Holtmann 
2848705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2849732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
28501038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2851732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2852732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2853efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2854efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2855efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2856efc7688bSMarcel Holtmann 			goto unlock;
2857efc7688bSMarcel Holtmann 		}
2858732547f9SMarcel Holtmann 		/* fall through */
2859efc7688bSMarcel Holtmann 
2860732547f9SMarcel Holtmann 	default:
2861b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2862732547f9SMarcel Holtmann 		break;
2863732547f9SMarcel Holtmann 	}
2864b6a0dc82SMarcel Holtmann 
2865b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2866b6a0dc82SMarcel Holtmann 	if (ev->status)
2867b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2868b6a0dc82SMarcel Holtmann 
2869b6a0dc82SMarcel Holtmann unlock:
2870b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2871a9de9248SMarcel Holtmann }
2872a9de9248SMarcel Holtmann 
2873a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2874a9de9248SMarcel Holtmann {
2875a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2876a9de9248SMarcel Holtmann }
2877a9de9248SMarcel Holtmann 
287804837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
287904837f64SMarcel Holtmann {
2880a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
288104837f64SMarcel Holtmann 
288204837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
288304837f64SMarcel Holtmann }
288404837f64SMarcel Holtmann 
2885a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2886a9de9248SMarcel Holtmann {
2887a9de9248SMarcel Holtmann 	struct inquiry_data data;
2888a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2889a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2890a9de9248SMarcel Holtmann 
2891a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2892a9de9248SMarcel Holtmann 
2893a9de9248SMarcel Holtmann 	if (!num_rsp)
2894a9de9248SMarcel Holtmann 		return;
2895a9de9248SMarcel Holtmann 
2896a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2897a9de9248SMarcel Holtmann 
2898e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2899561aafbcSJohan Hedberg 		bool name_known;
2900561aafbcSJohan Hedberg 
2901a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2902a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2903a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2904a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2905a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2906a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2907a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
290841a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2909561aafbcSJohan Hedberg 
2910a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29114ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29124ddb1930SJohan Hedberg 							sizeof(info->data),
29134ddb1930SJohan Hedberg 							EIR_NAME_COMPLETE);
2914561aafbcSJohan Hedberg 		else
2915561aafbcSJohan Hedberg 			name_known = true;
2916561aafbcSJohan Hedberg 
29173175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known);
291848264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2919561aafbcSJohan Hedberg 						info->dev_class, info->rssi,
29207d262f86SAndre Guedes 						!name_known, info->data,
29217d262f86SAndre Guedes 						sizeof(info->data));
2922a9de9248SMarcel Holtmann 	}
2923a9de9248SMarcel Holtmann 
2924a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2925a9de9248SMarcel Holtmann }
2926a9de9248SMarcel Holtmann 
292717fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
292817fa4b9dSJohan Hedberg {
292917fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
293017fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
293117fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
293217fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
293317fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
293417fa4b9dSJohan Hedberg 			return 0x02;
293517fa4b9dSJohan Hedberg 		else
293617fa4b9dSJohan Hedberg 			return 0x03;
293717fa4b9dSJohan Hedberg 	}
293817fa4b9dSJohan Hedberg 
293917fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
294017fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
294158797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
294217fa4b9dSJohan Hedberg 
294317fa4b9dSJohan Hedberg 	return conn->auth_type;
294417fa4b9dSJohan Hedberg }
294517fa4b9dSJohan Hedberg 
29460493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29470493684eSMarcel Holtmann {
29480493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
29490493684eSMarcel Holtmann 	struct hci_conn *conn;
29500493684eSMarcel Holtmann 
29510493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
29520493684eSMarcel Holtmann 
29530493684eSMarcel Holtmann 	hci_dev_lock(hdev);
29540493684eSMarcel Holtmann 
29550493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
295603b555e1SJohan Hedberg 	if (!conn)
295703b555e1SJohan Hedberg 		goto unlock;
295803b555e1SJohan Hedberg 
29590493684eSMarcel Holtmann 	hci_conn_hold(conn);
29600493684eSMarcel Holtmann 
2961a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
296203b555e1SJohan Hedberg 		goto unlock;
296303b555e1SJohan Hedberg 
2964a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
296503b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
296617fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
296717fa4b9dSJohan Hedberg 
296817fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
29697a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
29707a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
29717a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
29727a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
29737cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
29747cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
297517fa4b9dSJohan Hedberg 
297658a681efSJohan Hedberg 		if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
2977ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2978ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2979ce85ee13SSzymon Janc 		else
2980ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2981ce85ee13SSzymon Janc 
298217fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
298317fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
298403b555e1SJohan Hedberg 	} else {
298503b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
298603b555e1SJohan Hedberg 
298703b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
29889f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
298903b555e1SJohan Hedberg 
299003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
299103b555e1SJohan Hedberg 							sizeof(cp), &cp);
299203b555e1SJohan Hedberg 	}
299303b555e1SJohan Hedberg 
299403b555e1SJohan Hedberg unlock:
299503b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
299603b555e1SJohan Hedberg }
299703b555e1SJohan Hedberg 
299803b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
299903b555e1SJohan Hedberg {
300003b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
300103b555e1SJohan Hedberg 	struct hci_conn *conn;
300203b555e1SJohan Hedberg 
300303b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
300403b555e1SJohan Hedberg 
300503b555e1SJohan Hedberg 	hci_dev_lock(hdev);
300603b555e1SJohan Hedberg 
300703b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
300803b555e1SJohan Hedberg 	if (!conn)
300903b555e1SJohan Hedberg 		goto unlock;
301003b555e1SJohan Hedberg 
301103b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
301203b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
301358a681efSJohan Hedberg 	if (ev->oob_data)
301458a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
301503b555e1SJohan Hedberg 
301603b555e1SJohan Hedberg unlock:
30170493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
30180493684eSMarcel Holtmann }
30190493684eSMarcel Holtmann 
3020a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3021a5c29683SJohan Hedberg 							struct sk_buff *skb)
3022a5c29683SJohan Hedberg {
3023a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
302455bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
30257a828908SJohan Hedberg 	struct hci_conn *conn;
3026a5c29683SJohan Hedberg 
3027a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3028a5c29683SJohan Hedberg 
3029a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3030a5c29683SJohan Hedberg 
3031a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
30327a828908SJohan Hedberg 		goto unlock;
30337a828908SJohan Hedberg 
30347a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
30357a828908SJohan Hedberg 	if (!conn)
30367a828908SJohan Hedberg 		goto unlock;
30377a828908SJohan Hedberg 
30387a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
30397a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
30407a828908SJohan Hedberg 
30417a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
30427a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
30437a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
30447a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
30457a828908SJohan Hedberg 	 * bit set. */
30467a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
30477a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
30487a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
30497a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
30507a828908SJohan Hedberg 		goto unlock;
30517a828908SJohan Hedberg 	}
30527a828908SJohan Hedberg 
30537a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
30547a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
30557a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
305655bc1a37SJohan Hedberg 
305755bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
305855bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
305955bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
306051a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
306155bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
306255bc1a37SJohan Hedberg 			confirm_hint = 1;
306355bc1a37SJohan Hedberg 			goto confirm;
306455bc1a37SJohan Hedberg 		}
306555bc1a37SJohan Hedberg 
30669f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
30679f61656aSJohan Hedberg 						hdev->auto_accept_delay);
30689f61656aSJohan Hedberg 
30699f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
30709f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
30719f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
30729f61656aSJohan Hedberg 			goto unlock;
30739f61656aSJohan Hedberg 		}
30749f61656aSJohan Hedberg 
30757a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
30767a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
30777a828908SJohan Hedberg 		goto unlock;
30787a828908SJohan Hedberg 	}
30797a828908SJohan Hedberg 
308055bc1a37SJohan Hedberg confirm:
3081744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
308255bc1a37SJohan Hedberg 								confirm_hint);
3083a5c29683SJohan Hedberg 
30847a828908SJohan Hedberg unlock:
3085a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3086a5c29683SJohan Hedberg }
3087a5c29683SJohan Hedberg 
30881143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
30891143d458SBrian Gix 							struct sk_buff *skb)
30901143d458SBrian Gix {
30911143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
30921143d458SBrian Gix 
30931143d458SBrian Gix 	BT_DBG("%s", hdev->name);
30941143d458SBrian Gix 
30951143d458SBrian Gix 	hci_dev_lock(hdev);
30961143d458SBrian Gix 
3097a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
30981143d458SBrian Gix 		mgmt_user_passkey_request(hdev, &ev->bdaddr);
30991143d458SBrian Gix 
31001143d458SBrian Gix 	hci_dev_unlock(hdev);
31011143d458SBrian Gix }
31021143d458SBrian Gix 
31030493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
31040493684eSMarcel Holtmann {
31050493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
31060493684eSMarcel Holtmann 	struct hci_conn *conn;
31070493684eSMarcel Holtmann 
31080493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31090493684eSMarcel Holtmann 
31100493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31110493684eSMarcel Holtmann 
31120493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31132a611692SJohan Hedberg 	if (!conn)
31142a611692SJohan Hedberg 		goto unlock;
31152a611692SJohan Hedberg 
31162a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
31172a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
31182a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
31192a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
31202a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
312151a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3122744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
31232a611692SJohan Hedberg 
31240493684eSMarcel Holtmann 	hci_conn_put(conn);
31250493684eSMarcel Holtmann 
31262a611692SJohan Hedberg unlock:
31270493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31280493684eSMarcel Holtmann }
31290493684eSMarcel Holtmann 
313041a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
313141a96212SMarcel Holtmann {
313241a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
313341a96212SMarcel Holtmann 	struct inquiry_entry *ie;
313441a96212SMarcel Holtmann 
313541a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
313641a96212SMarcel Holtmann 
313741a96212SMarcel Holtmann 	hci_dev_lock(hdev);
313841a96212SMarcel Holtmann 
3139cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3140cc11b9c1SAndrei Emeltchenko 	if (ie)
314141a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
314241a96212SMarcel Holtmann 
314341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
314441a96212SMarcel Holtmann }
314541a96212SMarcel Holtmann 
31462763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
31472763eda6SSzymon Janc 							struct sk_buff *skb)
31482763eda6SSzymon Janc {
31492763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
31502763eda6SSzymon Janc 	struct oob_data *data;
31512763eda6SSzymon Janc 
31522763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
31532763eda6SSzymon Janc 
31542763eda6SSzymon Janc 	hci_dev_lock(hdev);
31552763eda6SSzymon Janc 
3156a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3157e1ba1f15SSzymon Janc 		goto unlock;
3158e1ba1f15SSzymon Janc 
31592763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
31602763eda6SSzymon Janc 	if (data) {
31612763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
31622763eda6SSzymon Janc 
31632763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31642763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
31652763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
31662763eda6SSzymon Janc 
31672763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
31682763eda6SSzymon Janc 									&cp);
31692763eda6SSzymon Janc 	} else {
31702763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
31712763eda6SSzymon Janc 
31722763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31732763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
31742763eda6SSzymon Janc 									&cp);
31752763eda6SSzymon Janc 	}
31762763eda6SSzymon Janc 
3177e1ba1f15SSzymon Janc unlock:
31782763eda6SSzymon Janc 	hci_dev_unlock(hdev);
31792763eda6SSzymon Janc }
31802763eda6SSzymon Janc 
3181fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3182fcd89c09SVille Tervo {
3183fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3184fcd89c09SVille Tervo 	struct hci_conn *conn;
3185fcd89c09SVille Tervo 
3186fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3187fcd89c09SVille Tervo 
3188fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3189fcd89c09SVille Tervo 
3190fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3191b62f328bSVille Tervo 	if (!conn) {
3192b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3193b62f328bSVille Tervo 		if (!conn) {
3194b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3195b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3196b62f328bSVille Tervo 			return;
3197b62f328bSVille Tervo 		}
319829b7988aSAndre Guedes 
319929b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3200b62f328bSVille Tervo 	}
3201fcd89c09SVille Tervo 
3202fcd89c09SVille Tervo 	if (ev->status) {
320348264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
320448264f06SJohan Hedberg 						conn->dst_type, ev->status);
3205fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3206fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3207fcd89c09SVille Tervo 		hci_conn_del(conn);
3208fcd89c09SVille Tervo 		goto unlock;
3209fcd89c09SVille Tervo 	}
3210fcd89c09SVille Tervo 
3211b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3212b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
3213b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0, 0);
321483bc71b4SVinicius Costa Gomes 
32157b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3216fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3217fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3218fcd89c09SVille Tervo 
3219fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3220fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3221fcd89c09SVille Tervo 
3222fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3223fcd89c09SVille Tervo 
3224fcd89c09SVille Tervo unlock:
3225fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3226fcd89c09SVille Tervo }
3227fcd89c09SVille Tervo 
32289aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
32299aa04c91SAndre Guedes 						struct sk_buff *skb)
32309aa04c91SAndre Guedes {
3231e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3232e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
32333c9e9195SAndre Guedes 	s8 rssi;
32349aa04c91SAndre Guedes 
32359aa04c91SAndre Guedes 	hci_dev_lock(hdev);
32369aa04c91SAndre Guedes 
3237e95beb41SAndre Guedes 	while (num_reports--) {
3238e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3239e95beb41SAndre Guedes 
32409aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
32419aa04c91SAndre Guedes 
32423c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
32433c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
32443c9e9195SAndre Guedes 					NULL, rssi, 0, ev->data, ev->length);
32453c9e9195SAndre Guedes 
3246e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
32479aa04c91SAndre Guedes 	}
32489aa04c91SAndre Guedes 
32499aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
32509aa04c91SAndre Guedes }
32519aa04c91SAndre Guedes 
3252a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3253a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3254a7a595f6SVinicius Costa Gomes {
3255a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3256a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3257bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3258a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3259bea710feSVinicius Costa Gomes 	struct link_key *ltk;
3260a7a595f6SVinicius Costa Gomes 
3261a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3262a7a595f6SVinicius Costa Gomes 
3263a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3264a7a595f6SVinicius Costa Gomes 
3265a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3266bea710feSVinicius Costa Gomes 	if (conn == NULL)
3267bea710feSVinicius Costa Gomes 		goto not_found;
3268a7a595f6SVinicius Costa Gomes 
3269bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3270bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3271bea710feSVinicius Costa Gomes 		goto not_found;
3272bea710feSVinicius Costa Gomes 
3273bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3274a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3275726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
3276a7a595f6SVinicius Costa Gomes 
3277a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3278a7a595f6SVinicius Costa Gomes 
3279a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3280bea710feSVinicius Costa Gomes 
3281bea710feSVinicius Costa Gomes 	return;
3282bea710feSVinicius Costa Gomes 
3283bea710feSVinicius Costa Gomes not_found:
3284bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3285bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3286bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3287a7a595f6SVinicius Costa Gomes }
3288a7a595f6SVinicius Costa Gomes 
3289fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3290fcd89c09SVille Tervo {
3291fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3292fcd89c09SVille Tervo 
3293fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3294fcd89c09SVille Tervo 
3295fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3296fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3297fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3298fcd89c09SVille Tervo 		break;
3299fcd89c09SVille Tervo 
33009aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
33019aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
33029aa04c91SAndre Guedes 		break;
33039aa04c91SAndre Guedes 
3304a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3305a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3306a7a595f6SVinicius Costa Gomes 		break;
3307a7a595f6SVinicius Costa Gomes 
3308fcd89c09SVille Tervo 	default:
3309fcd89c09SVille Tervo 		break;
3310fcd89c09SVille Tervo 	}
3311fcd89c09SVille Tervo }
3312fcd89c09SVille Tervo 
33131da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
33141da177e4SLinus Torvalds {
3315a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3316a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
33171da177e4SLinus Torvalds 
33181da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
33191da177e4SLinus Torvalds 
3320a9de9248SMarcel Holtmann 	switch (event) {
33211da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
33221da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
33231da177e4SLinus Torvalds 		break;
33241da177e4SLinus Torvalds 
33251da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
33261da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
33271da177e4SLinus Torvalds 		break;
33281da177e4SLinus Torvalds 
3329a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3330a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
333121d9e30eSMarcel Holtmann 		break;
333221d9e30eSMarcel Holtmann 
33331da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
33341da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
33351da177e4SLinus Torvalds 		break;
33361da177e4SLinus Torvalds 
33371da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
33381da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
33391da177e4SLinus Torvalds 		break;
33401da177e4SLinus Torvalds 
33411da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
33421da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
33431da177e4SLinus Torvalds 		break;
33441da177e4SLinus Torvalds 
3345a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3346a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3347a9de9248SMarcel Holtmann 		break;
3348a9de9248SMarcel Holtmann 
33491da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
33501da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
33511da177e4SLinus Torvalds 		break;
33521da177e4SLinus Torvalds 
3353a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3354a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3355a9de9248SMarcel Holtmann 		break;
3356a9de9248SMarcel Holtmann 
3357a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3358a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3359a9de9248SMarcel Holtmann 		break;
3360a9de9248SMarcel Holtmann 
3361a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3362a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3363a9de9248SMarcel Holtmann 		break;
3364a9de9248SMarcel Holtmann 
3365a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3366a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3367a9de9248SMarcel Holtmann 		break;
3368a9de9248SMarcel Holtmann 
3369a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3370a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3371a9de9248SMarcel Holtmann 		break;
3372a9de9248SMarcel Holtmann 
3373a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3374a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3375a9de9248SMarcel Holtmann 		break;
3376a9de9248SMarcel Holtmann 
3377a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3378a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3379a9de9248SMarcel Holtmann 		break;
3380a9de9248SMarcel Holtmann 
3381a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3382a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3383a9de9248SMarcel Holtmann 		break;
3384a9de9248SMarcel Holtmann 
3385a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3386a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
33871da177e4SLinus Torvalds 		break;
33881da177e4SLinus Torvalds 
33891da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
33901da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
33911da177e4SLinus Torvalds 		break;
33921da177e4SLinus Torvalds 
33931da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
33941da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
33951da177e4SLinus Torvalds 		break;
33961da177e4SLinus Torvalds 
33971da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
33981da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
33991da177e4SLinus Torvalds 		break;
34001da177e4SLinus Torvalds 
34011da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
34021da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
34031da177e4SLinus Torvalds 		break;
34041da177e4SLinus Torvalds 
3405a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3406a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3407a8746417SMarcel Holtmann 		break;
3408a8746417SMarcel Holtmann 
340985a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
341085a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
341185a1e930SMarcel Holtmann 		break;
341285a1e930SMarcel Holtmann 
3413a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3414a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3415a9de9248SMarcel Holtmann 		break;
3416a9de9248SMarcel Holtmann 
3417a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3418a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3419a9de9248SMarcel Holtmann 		break;
3420a9de9248SMarcel Holtmann 
3421a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3422a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3423a9de9248SMarcel Holtmann 		break;
3424a9de9248SMarcel Holtmann 
3425a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3426a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3427a9de9248SMarcel Holtmann 		break;
3428a9de9248SMarcel Holtmann 
342904837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
343004837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
343104837f64SMarcel Holtmann 		break;
343204837f64SMarcel Holtmann 
3433a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3434a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
34351da177e4SLinus Torvalds 		break;
34361da177e4SLinus Torvalds 
34370493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
34380493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
34390493684eSMarcel Holtmann 		break;
34400493684eSMarcel Holtmann 
344103b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
344203b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
344303b555e1SJohan Hedberg 		break;
344403b555e1SJohan Hedberg 
3445a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3446a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3447a5c29683SJohan Hedberg 		break;
3448a5c29683SJohan Hedberg 
34491143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
34501143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
34511143d458SBrian Gix 		break;
34521143d458SBrian Gix 
34530493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
34540493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
34550493684eSMarcel Holtmann 		break;
34560493684eSMarcel Holtmann 
345741a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
345841a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
345941a96212SMarcel Holtmann 		break;
346041a96212SMarcel Holtmann 
3461fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3462fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3463fcd89c09SVille Tervo 		break;
3464fcd89c09SVille Tervo 
34652763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
34662763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
34672763eda6SSzymon Janc 		break;
34682763eda6SSzymon Janc 
346925e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
347025e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
347125e89e99SAndrei Emeltchenko 		break;
347225e89e99SAndrei Emeltchenko 
34731da177e4SLinus Torvalds 	default:
3474a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
34751da177e4SLinus Torvalds 		break;
34761da177e4SLinus Torvalds 	}
34771da177e4SLinus Torvalds 
34781da177e4SLinus Torvalds 	kfree_skb(skb);
34791da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
34801da177e4SLinus Torvalds }
34811da177e4SLinus Torvalds 
34821da177e4SLinus Torvalds /* Generate internal stack event */
34831da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
34841da177e4SLinus Torvalds {
34851da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
34861da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
34871da177e4SLinus Torvalds 	struct sk_buff *skb;
34881da177e4SLinus Torvalds 
34891da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
34901da177e4SLinus Torvalds 	if (!skb)
34911da177e4SLinus Torvalds 		return;
34921da177e4SLinus Torvalds 
34931da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
34941da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
34951da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
34961da177e4SLinus Torvalds 
34971da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
34981da177e4SLinus Torvalds 	ev->type = type;
34991da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
35001da177e4SLinus Torvalds 
3501576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3502a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3503576c7d85SMarcel Holtmann 
35040d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
35051da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3506eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
35071da177e4SLinus Torvalds 	kfree_skb(skb);
35081da177e4SLinus Torvalds }
3509e6100a25SAndre Guedes 
3510669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3511e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3512