xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 7ba8b4be)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds    BlueZ - Bluetooth protocol stack for Linux
32d0a0346SRon Shaffer    Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds    This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds    it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds    published by the Free Software Foundation;
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
121da177e4SLinus Torvalds    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131da177e4SLinus Torvalds    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
141da177e4SLinus Torvalds    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
151da177e4SLinus Torvalds    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
161da177e4SLinus Torvalds    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
171da177e4SLinus Torvalds    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
181da177e4SLinus Torvalds    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
211da177e4SLinus Torvalds    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
221da177e4SLinus Torvalds    SOFTWARE IS DISCLAIMED.
231da177e4SLinus Torvalds */
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds #include <linux/module.h>
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds #include <linux/types.h>
301da177e4SLinus Torvalds #include <linux/errno.h>
311da177e4SLinus Torvalds #include <linux/kernel.h>
321da177e4SLinus Torvalds #include <linux/slab.h>
331da177e4SLinus Torvalds #include <linux/poll.h>
341da177e4SLinus Torvalds #include <linux/fcntl.h>
351da177e4SLinus Torvalds #include <linux/init.h>
361da177e4SLinus Torvalds #include <linux/skbuff.h>
371da177e4SLinus Torvalds #include <linux/interrupt.h>
381da177e4SLinus Torvalds #include <linux/notifier.h>
391da177e4SLinus Torvalds #include <net/sock.h>
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds #include <asm/system.h>
4270f23020SAndrei Emeltchenko #include <linux/uaccess.h>
431da177e4SLinus Torvalds #include <asm/unaligned.h>
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
461da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
471da177e4SLinus Torvalds 
48eb939922SRusty Russell static bool enable_le;
49e6100a25SAndre Guedes 
501da177e4SLinus Torvalds /* Handle HCI Event packets */
511da177e4SLinus Torvalds 
52a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
531da177e4SLinus Torvalds {
54a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
551da177e4SLinus Torvalds 
56a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
571da177e4SLinus Torvalds 
58e6d465cbSAndre Guedes 	if (status) {
59e6d465cbSAndre Guedes 		hci_dev_lock(hdev);
60e6d465cbSAndre Guedes 		mgmt_stop_discovery_failed(hdev, status);
61e6d465cbSAndre Guedes 		hci_dev_unlock(hdev);
62a9de9248SMarcel Holtmann 		return;
63e6d465cbSAndre Guedes 	}
641da177e4SLinus Torvalds 
6589352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
6689352e7dSAndre Guedes 
6756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
68ff9ef578SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
6956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
70a9de9248SMarcel Holtmann 
7123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
72a9de9248SMarcel Holtmann 
73a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
741da177e4SLinus Torvalds }
756bd57416SMarcel Holtmann 
76a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
771da177e4SLinus Torvalds {
78a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
79a9de9248SMarcel Holtmann 
80a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
81a9de9248SMarcel Holtmann 
82a9de9248SMarcel Holtmann 	if (status)
83a9de9248SMarcel Holtmann 		return;
84a9de9248SMarcel Holtmann 
85a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
86a9de9248SMarcel Holtmann }
87a9de9248SMarcel Holtmann 
88a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
89a9de9248SMarcel Holtmann {
90a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
91a9de9248SMarcel Holtmann }
92a9de9248SMarcel Holtmann 
93a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
94a9de9248SMarcel Holtmann {
95a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
961da177e4SLinus Torvalds 	struct hci_conn *conn;
971da177e4SLinus Torvalds 
98a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
991da177e4SLinus Torvalds 
100a9de9248SMarcel Holtmann 	if (rp->status)
101a9de9248SMarcel Holtmann 		return;
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1041da177e4SLinus Torvalds 
105a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1061da177e4SLinus Torvalds 	if (conn) {
107a9de9248SMarcel Holtmann 		if (rp->role)
1081da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1091da177e4SLinus Torvalds 		else
1101da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1111da177e4SLinus Torvalds 	}
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
114a9de9248SMarcel Holtmann }
1151da177e4SLinus Torvalds 
116e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
117e4e8e37cSMarcel Holtmann {
118e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
119e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
120e4e8e37cSMarcel Holtmann 
121e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
122e4e8e37cSMarcel Holtmann 
123e4e8e37cSMarcel Holtmann 	if (rp->status)
124e4e8e37cSMarcel Holtmann 		return;
125e4e8e37cSMarcel Holtmann 
126e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
127e4e8e37cSMarcel Holtmann 
128e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
129e4e8e37cSMarcel Holtmann 	if (conn)
130e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
131e4e8e37cSMarcel Holtmann 
132e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
133e4e8e37cSMarcel Holtmann }
134e4e8e37cSMarcel Holtmann 
135a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
136a9de9248SMarcel Holtmann {
137a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
138a9de9248SMarcel Holtmann 	struct hci_conn *conn;
139a9de9248SMarcel Holtmann 	void *sent;
140a9de9248SMarcel Holtmann 
141a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
142a9de9248SMarcel Holtmann 
143a9de9248SMarcel Holtmann 	if (rp->status)
144a9de9248SMarcel Holtmann 		return;
145a9de9248SMarcel Holtmann 
146a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14704837f64SMarcel Holtmann 	if (!sent)
148a9de9248SMarcel Holtmann 		return;
14904837f64SMarcel Holtmann 
15004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
15104837f64SMarcel Holtmann 
152a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
153e4e8e37cSMarcel Holtmann 	if (conn)
15483985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15504837f64SMarcel Holtmann 
15604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds 
159e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
160e4e8e37cSMarcel Holtmann {
161e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
162e4e8e37cSMarcel Holtmann 
163e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
164e4e8e37cSMarcel Holtmann 
165e4e8e37cSMarcel Holtmann 	if (rp->status)
166e4e8e37cSMarcel Holtmann 		return;
167e4e8e37cSMarcel Holtmann 
168e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
169e4e8e37cSMarcel Holtmann }
170e4e8e37cSMarcel Holtmann 
171e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
172e4e8e37cSMarcel Holtmann {
173e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
174e4e8e37cSMarcel Holtmann 	void *sent;
175e4e8e37cSMarcel Holtmann 
176e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
177e4e8e37cSMarcel Holtmann 
178e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
179e4e8e37cSMarcel Holtmann 	if (!sent)
180e4e8e37cSMarcel Holtmann 		return;
181e4e8e37cSMarcel Holtmann 
182e4e8e37cSMarcel Holtmann 	if (!status)
183e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
184e4e8e37cSMarcel Holtmann 
18523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
186e4e8e37cSMarcel Holtmann }
187e4e8e37cSMarcel Holtmann 
188a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1891da177e4SLinus Torvalds {
190a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
191a9de9248SMarcel Holtmann 
192a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
193a9de9248SMarcel Holtmann 
19410572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19510572132SGustavo F. Padovan 
19623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
197d23264a8SAndre Guedes 
1987005ff17SJohan Hedberg 	/* Reset all flags, except persistent ones */
19995947a39SHemant Gupta 	hdev->dev_flags &= BIT(HCI_MGMT) | BIT(HCI_SETUP) | BIT(HCI_AUTO_OFF) |
20095947a39SHemant Gupta 				BIT(HCI_LINK_KEYS) | BIT(HCI_DEBUG_KEYS);
201a9de9248SMarcel Holtmann }
202a9de9248SMarcel Holtmann 
203a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
204a9de9248SMarcel Holtmann {
205a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2061da177e4SLinus Torvalds 	void *sent;
2071da177e4SLinus Torvalds 
208a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2091da177e4SLinus Torvalds 
210a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2111da177e4SLinus Torvalds 	if (!sent)
212a9de9248SMarcel Holtmann 		return;
2131da177e4SLinus Torvalds 
21456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21556e5cb86SJohan Hedberg 
216a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
217744cf19eSJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
218b312b161SJohan Hedberg 
21956e5cb86SJohan Hedberg 	if (status == 0)
2201f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
22156e5cb86SJohan Hedberg 
22256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
223a9de9248SMarcel Holtmann }
224a9de9248SMarcel Holtmann 
225a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
226a9de9248SMarcel Holtmann {
227a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
228a9de9248SMarcel Holtmann 
229a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
230a9de9248SMarcel Holtmann 
231a9de9248SMarcel Holtmann 	if (rp->status)
232a9de9248SMarcel Holtmann 		return;
233a9de9248SMarcel Holtmann 
2341f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
235a9de9248SMarcel Holtmann }
236a9de9248SMarcel Holtmann 
237a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
238a9de9248SMarcel Holtmann {
239a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
240a9de9248SMarcel Holtmann 	void *sent;
241a9de9248SMarcel Holtmann 
242a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
243a9de9248SMarcel Holtmann 
244a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
245a9de9248SMarcel Holtmann 	if (!sent)
246a9de9248SMarcel Holtmann 		return;
2471da177e4SLinus Torvalds 
2481da177e4SLinus Torvalds 	if (!status) {
249a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
250a9de9248SMarcel Holtmann 
2511da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2521da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2531da177e4SLinus Torvalds 		else
2541da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2551da177e4SLinus Torvalds 	}
256a9de9248SMarcel Holtmann 
25723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
258a9de9248SMarcel Holtmann }
2591da177e4SLinus Torvalds 
260a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
261a9de9248SMarcel Holtmann {
262a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
263a9de9248SMarcel Holtmann 	void *sent;
264a9de9248SMarcel Holtmann 
265a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
266a9de9248SMarcel Holtmann 
267a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2681da177e4SLinus Torvalds 	if (!sent)
269a9de9248SMarcel Holtmann 		return;
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds 	if (!status) {
272a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
273a9de9248SMarcel Holtmann 
2741da177e4SLinus Torvalds 		if (param)
2751da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2761da177e4SLinus Torvalds 		else
2771da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2781da177e4SLinus Torvalds 	}
279a9de9248SMarcel Holtmann 
28023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2811da177e4SLinus Torvalds }
2821da177e4SLinus Torvalds 
283a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
284a9de9248SMarcel Holtmann {
28536f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28636f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
287a9de9248SMarcel Holtmann 	void *sent;
2881da177e4SLinus Torvalds 
289a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
290a9de9248SMarcel Holtmann 
291a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2921da177e4SLinus Torvalds 	if (!sent)
293a9de9248SMarcel Holtmann 		return;
2941da177e4SLinus Torvalds 
29536f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
296a9de9248SMarcel Holtmann 
29756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29856e5cb86SJohan Hedberg 
2992d7cee58SJohan Hedberg 	if (status != 0) {
300744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3012d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3022d7cee58SJohan Hedberg 		goto done;
3032d7cee58SJohan Hedberg 	}
3042d7cee58SJohan Hedberg 
3059fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3069fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
307a9de9248SMarcel Holtmann 
30873f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3091da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3109fbcbb45SJohan Hedberg 		if (!old_iscan)
311744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31216ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
31316ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31416ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31516ab91abSJohan Hedberg 									to);
31616ab91abSJohan Hedberg 		}
3179fbcbb45SJohan Hedberg 	} else if (old_iscan)
318744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3191da177e4SLinus Torvalds 
3209fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3211da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3229fbcbb45SJohan Hedberg 		if (!old_pscan)
323744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3249fbcbb45SJohan Hedberg 	} else if (old_pscan)
325744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
326a9de9248SMarcel Holtmann 
32736f7fc7eSJohan Hedberg done:
32856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
32923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
332a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
333a9de9248SMarcel Holtmann {
334a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
335a9de9248SMarcel Holtmann 
336a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
337a9de9248SMarcel Holtmann 
338a9de9248SMarcel Holtmann 	if (rp->status)
339a9de9248SMarcel Holtmann 		return;
340a9de9248SMarcel Holtmann 
341a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
344a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
345a9de9248SMarcel Holtmann }
346a9de9248SMarcel Holtmann 
347a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
348a9de9248SMarcel Holtmann {
349a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
350a9de9248SMarcel Holtmann 	void *sent;
351a9de9248SMarcel Holtmann 
352a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
353a9de9248SMarcel Holtmann 
354f383f275SMarcel Holtmann 	if (status)
355f383f275SMarcel Holtmann 		return;
356f383f275SMarcel Holtmann 
357a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
358a9de9248SMarcel Holtmann 	if (!sent)
359a9de9248SMarcel Holtmann 		return;
360a9de9248SMarcel Holtmann 
361a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
362a9de9248SMarcel Holtmann }
363a9de9248SMarcel Holtmann 
364a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
365a9de9248SMarcel Holtmann {
366a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
367a9de9248SMarcel Holtmann 	__u16 setting;
368a9de9248SMarcel Holtmann 
369a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
370a9de9248SMarcel Holtmann 
371a9de9248SMarcel Holtmann 	if (rp->status)
372a9de9248SMarcel Holtmann 		return;
373a9de9248SMarcel Holtmann 
374a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
375a9de9248SMarcel Holtmann 
376a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
377a9de9248SMarcel Holtmann 		return;
378a9de9248SMarcel Holtmann 
379a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
380a9de9248SMarcel Holtmann 
381a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
382a9de9248SMarcel Holtmann 
3833c54711cSGustavo F. Padovan 	if (hdev->notify)
384a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
385a9de9248SMarcel Holtmann }
386a9de9248SMarcel Holtmann 
387a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
388a9de9248SMarcel Holtmann {
389a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
390f383f275SMarcel Holtmann 	__u16 setting;
391a9de9248SMarcel Holtmann 	void *sent;
392a9de9248SMarcel Holtmann 
393a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
394a9de9248SMarcel Holtmann 
395f383f275SMarcel Holtmann 	if (status)
396f383f275SMarcel Holtmann 		return;
397f383f275SMarcel Holtmann 
398a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
399a9de9248SMarcel Holtmann 	if (!sent)
400a9de9248SMarcel Holtmann 		return;
401a9de9248SMarcel Holtmann 
402f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4031da177e4SLinus Torvalds 
404f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
405f383f275SMarcel Holtmann 		return;
406f383f275SMarcel Holtmann 
4071da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4081da177e4SLinus Torvalds 
409a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4101da177e4SLinus Torvalds 
4113c54711cSGustavo F. Padovan 	if (hdev->notify)
4121da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4131da177e4SLinus Torvalds }
4141da177e4SLinus Torvalds 
415a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4161da177e4SLinus Torvalds {
417a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4181da177e4SLinus Torvalds 
419a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4201da177e4SLinus Torvalds 
42123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4221143e5a6SMarcel Holtmann }
4231143e5a6SMarcel Holtmann 
424333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
425333140b5SMarcel Holtmann {
426333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
427333140b5SMarcel Holtmann 
428333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
429333140b5SMarcel Holtmann 
430333140b5SMarcel Holtmann 	if (rp->status)
431333140b5SMarcel Holtmann 		return;
432333140b5SMarcel Holtmann 
43384bde9d6SJohan Hedberg 	if (rp->mode)
43484bde9d6SJohan Hedberg 		set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
43584bde9d6SJohan Hedberg 	else
43684bde9d6SJohan Hedberg 		clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
437333140b5SMarcel Holtmann }
438333140b5SMarcel Holtmann 
439333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
440333140b5SMarcel Holtmann {
441333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
442333140b5SMarcel Holtmann 	void *sent;
443333140b5SMarcel Holtmann 
444333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
445333140b5SMarcel Holtmann 
446333140b5SMarcel Holtmann 	if (status)
447333140b5SMarcel Holtmann 		return;
448333140b5SMarcel Holtmann 
449333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
450333140b5SMarcel Holtmann 	if (!sent)
451333140b5SMarcel Holtmann 		return;
452333140b5SMarcel Holtmann 
45384bde9d6SJohan Hedberg 	if (*((u8 *) sent))
45484bde9d6SJohan Hedberg 		set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
45584bde9d6SJohan Hedberg 	else
45684bde9d6SJohan Hedberg 		clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
457333140b5SMarcel Holtmann }
458333140b5SMarcel Holtmann 
459d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
460d5859e22SJohan Hedberg {
461d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
462d5859e22SJohan Hedberg 		return 2;
463d5859e22SJohan Hedberg 
464d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
465d5859e22SJohan Hedberg 		return 1;
466d5859e22SJohan Hedberg 
467d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
468d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
469d5859e22SJohan Hedberg 		return 1;
470d5859e22SJohan Hedberg 
471d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
472d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
473d5859e22SJohan Hedberg 			return 1;
474d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
475d5859e22SJohan Hedberg 			return 1;
476d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
477d5859e22SJohan Hedberg 			return 1;
478d5859e22SJohan Hedberg 	}
479d5859e22SJohan Hedberg 
480d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
481d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
482d5859e22SJohan Hedberg 		return 1;
483d5859e22SJohan Hedberg 
484d5859e22SJohan Hedberg 	return 0;
485d5859e22SJohan Hedberg }
486d5859e22SJohan Hedberg 
487d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
488d5859e22SJohan Hedberg {
489d5859e22SJohan Hedberg 	u8 mode;
490d5859e22SJohan Hedberg 
491d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
492d5859e22SJohan Hedberg 
493d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
494d5859e22SJohan Hedberg }
495d5859e22SJohan Hedberg 
496d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
497d5859e22SJohan Hedberg {
498d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
499d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
500d5859e22SJohan Hedberg 	 * command otherwise */
501d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
502d5859e22SJohan Hedberg 
5036de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5046de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5055a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
5066de6c18dSVille Tervo 		return;
5076de6c18dSVille Tervo 
508d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
509d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
510d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
511d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
512d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
513d5859e22SJohan Hedberg 
514d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
515d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
516d5859e22SJohan Hedberg 
517d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
518d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
519d5859e22SJohan Hedberg 
520d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
521d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
522d5859e22SJohan Hedberg 
523d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
524d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
525d5859e22SJohan Hedberg 
526d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
527d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
528d5859e22SJohan Hedberg 
529d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
530d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
531d5859e22SJohan Hedberg 
532d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
533d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
534d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
535d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
536d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
537d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
538d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
539d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
540d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
541d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
542d5859e22SJohan Hedberg 					 * Features Notification */
543d5859e22SJohan Hedberg 	}
544d5859e22SJohan Hedberg 
545d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
546d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
547d5859e22SJohan Hedberg 
548d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
549d5859e22SJohan Hedberg }
550d5859e22SJohan Hedberg 
551e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
552e6100a25SAndre Guedes {
553e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
554e6100a25SAndre Guedes 
555e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
556e6100a25SAndre Guedes 
557e6100a25SAndre Guedes 	if (enable_le) {
558e6100a25SAndre Guedes 		cp.le = 1;
559e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
560e6100a25SAndre Guedes 	}
561e6100a25SAndre Guedes 
562e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
563e6100a25SAndre Guedes }
564e6100a25SAndre Guedes 
565d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
566d5859e22SJohan Hedberg {
567e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
568e61ef499SAndrei Emeltchenko 		return;
569e61ef499SAndrei Emeltchenko 
570d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
571d5859e22SJohan Hedberg 
572d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
573d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
574d5859e22SJohan Hedberg 
575d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
576d5859e22SJohan Hedberg 		u8 mode = 0x01;
577d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
578d5859e22SJohan Hedberg 	}
579d5859e22SJohan Hedberg 
580d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
581d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
582d5859e22SJohan Hedberg 
583d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
584d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
585971e3a4bSAndre Guedes 
586971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
587971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
588971e3a4bSAndre Guedes 
589971e3a4bSAndre Guedes 		cp.page = 0x01;
590971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
591971e3a4bSAndre Guedes 							sizeof(cp), &cp);
592971e3a4bSAndre Guedes 	}
593e6100a25SAndre Guedes 
594e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
595e6100a25SAndre Guedes 		hci_set_le_support(hdev);
596d5859e22SJohan Hedberg }
597d5859e22SJohan Hedberg 
598a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
599a9de9248SMarcel Holtmann {
600a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6011143e5a6SMarcel Holtmann 
602a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
6031143e5a6SMarcel Holtmann 
604a9de9248SMarcel Holtmann 	if (rp->status)
605a9de9248SMarcel Holtmann 		return;
6061143e5a6SMarcel Holtmann 
607a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
608e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
609d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
610e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
611d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6121da177e4SLinus Torvalds 
613a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
614a9de9248SMarcel Holtmann 					hdev->manufacturer,
615a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
616d5859e22SJohan Hedberg 
617d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
618d5859e22SJohan Hedberg 		hci_setup(hdev);
619d5859e22SJohan Hedberg }
620d5859e22SJohan Hedberg 
621d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
622d5859e22SJohan Hedberg {
623d5859e22SJohan Hedberg 	u16 link_policy = 0;
624d5859e22SJohan Hedberg 
625d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
626d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
627d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
628d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
629d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
630d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
631d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
632d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
633d5859e22SJohan Hedberg 
634d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
635d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
636d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6371da177e4SLinus Torvalds }
6381da177e4SLinus Torvalds 
639a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
640a9de9248SMarcel Holtmann {
641a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
642a9de9248SMarcel Holtmann 
643a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
644a9de9248SMarcel Holtmann 
645a9de9248SMarcel Holtmann 	if (rp->status)
646d5859e22SJohan Hedberg 		goto done;
647a9de9248SMarcel Holtmann 
648a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
649d5859e22SJohan Hedberg 
650d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
651d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
652d5859e22SJohan Hedberg 
653d5859e22SJohan Hedberg done:
654d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
655a9de9248SMarcel Holtmann }
656a9de9248SMarcel Holtmann 
657a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
658a9de9248SMarcel Holtmann {
659a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
660a9de9248SMarcel Holtmann 
661a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
662a9de9248SMarcel Holtmann 
663a9de9248SMarcel Holtmann 	if (rp->status)
664a9de9248SMarcel Holtmann 		return;
665a9de9248SMarcel Holtmann 
666a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6671da177e4SLinus Torvalds 
6681da177e4SLinus Torvalds 	/* Adjust default settings according to features
6691da177e4SLinus Torvalds 	 * supported by device. */
670a9de9248SMarcel Holtmann 
6711da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6721da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6731da177e4SLinus Torvalds 
6741da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6751da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6761da177e4SLinus Torvalds 
6775b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6781da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6795b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6805b7f9909SMarcel Holtmann 	}
6811da177e4SLinus Torvalds 
6825b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6831da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6845b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6855b7f9909SMarcel Holtmann 	}
6865b7f9909SMarcel Holtmann 
6875b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6885b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6895b7f9909SMarcel Holtmann 
6905b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6915b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6925b7f9909SMarcel Holtmann 
6935b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6945b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6951da177e4SLinus Torvalds 
696efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
697efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
698efc7688bSMarcel Holtmann 
699efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
700efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
701efc7688bSMarcel Holtmann 
702efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
703efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
704efc7688bSMarcel Holtmann 
705a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
706a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
707a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
708a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
709a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7101da177e4SLinus Torvalds }
7111da177e4SLinus Torvalds 
712971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
713971e3a4bSAndre Guedes 							struct sk_buff *skb)
714971e3a4bSAndre Guedes {
715971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
716971e3a4bSAndre Guedes 
717971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
718971e3a4bSAndre Guedes 
719971e3a4bSAndre Guedes 	if (rp->status)
720971e3a4bSAndre Guedes 		return;
721971e3a4bSAndre Guedes 
722b5b32b65SAndre Guedes 	switch (rp->page) {
723b5b32b65SAndre Guedes 	case 0:
724b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
725b5b32b65SAndre Guedes 		break;
726b5b32b65SAndre Guedes 	case 1:
72759e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
728b5b32b65SAndre Guedes 		break;
729b5b32b65SAndre Guedes 	}
730971e3a4bSAndre Guedes 
731971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
732971e3a4bSAndre Guedes }
733971e3a4bSAndre Guedes 
7341e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7351e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7361e89cffbSAndrei Emeltchenko {
7371e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7381e89cffbSAndrei Emeltchenko 
7391e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7401e89cffbSAndrei Emeltchenko 
7411e89cffbSAndrei Emeltchenko 	if (rp->status)
7421e89cffbSAndrei Emeltchenko 		return;
7431e89cffbSAndrei Emeltchenko 
7441e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7451e89cffbSAndrei Emeltchenko 
7461e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7471e89cffbSAndrei Emeltchenko }
7481e89cffbSAndrei Emeltchenko 
749a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
750a9de9248SMarcel Holtmann {
751a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
752a9de9248SMarcel Holtmann 
753a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
754a9de9248SMarcel Holtmann 
755a9de9248SMarcel Holtmann 	if (rp->status)
756a9de9248SMarcel Holtmann 		return;
757a9de9248SMarcel Holtmann 
758a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
759a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
760a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
761a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
762da1f5198SMarcel Holtmann 
763da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
764da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
765da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
766da1f5198SMarcel Holtmann 	}
767da1f5198SMarcel Holtmann 
768da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
769da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7701da177e4SLinus Torvalds 
771a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
772a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
773a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7741da177e4SLinus Torvalds }
7751da177e4SLinus Torvalds 
776a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
777a9de9248SMarcel Holtmann {
778a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7791da177e4SLinus Torvalds 
780a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
781a9de9248SMarcel Holtmann 
782a9de9248SMarcel Holtmann 	if (!rp->status)
783a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
784a9de9248SMarcel Holtmann 
78523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
78623bb5763SJohan Hedberg }
78723bb5763SJohan Hedberg 
788350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
789350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
790350ee4cfSAndrei Emeltchenko {
791350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
792350ee4cfSAndrei Emeltchenko 
793350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
794350ee4cfSAndrei Emeltchenko 
795350ee4cfSAndrei Emeltchenko 	if (rp->status)
796350ee4cfSAndrei Emeltchenko 		return;
797350ee4cfSAndrei Emeltchenko 
798350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
799350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
800350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
801350ee4cfSAndrei Emeltchenko 
802350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
803350ee4cfSAndrei Emeltchenko 
804350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
805350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
806350ee4cfSAndrei Emeltchenko 
807350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
808350ee4cfSAndrei Emeltchenko }
809350ee4cfSAndrei Emeltchenko 
81023bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
81123bb5763SJohan Hedberg {
81223bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
81323bb5763SJohan Hedberg 
81423bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
81523bb5763SJohan Hedberg 
81623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8171da177e4SLinus Torvalds }
8181da177e4SLinus Torvalds 
819928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
820928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
821928abaa7SAndrei Emeltchenko {
822928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
823928abaa7SAndrei Emeltchenko 
824928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
825928abaa7SAndrei Emeltchenko 
826928abaa7SAndrei Emeltchenko 	if (rp->status)
827928abaa7SAndrei Emeltchenko 		return;
828928abaa7SAndrei Emeltchenko 
829928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
830928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
831928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
832928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
833928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
834928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
835928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
836928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
837928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
838928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
839928abaa7SAndrei Emeltchenko 
840928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
841928abaa7SAndrei Emeltchenko }
842928abaa7SAndrei Emeltchenko 
843b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
844b0916ea0SJohan Hedberg 							struct sk_buff *skb)
845b0916ea0SJohan Hedberg {
846b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
847b0916ea0SJohan Hedberg 
848b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
849b0916ea0SJohan Hedberg 
850b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
851b0916ea0SJohan Hedberg }
852b0916ea0SJohan Hedberg 
853d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
854d5859e22SJohan Hedberg {
855d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
856d5859e22SJohan Hedberg 
857d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
858d5859e22SJohan Hedberg 
859d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
860d5859e22SJohan Hedberg }
861d5859e22SJohan Hedberg 
862d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
863d5859e22SJohan Hedberg 							struct sk_buff *skb)
864d5859e22SJohan Hedberg {
865d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
866d5859e22SJohan Hedberg 
867d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
868d5859e22SJohan Hedberg 
869d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
870d5859e22SJohan Hedberg }
871d5859e22SJohan Hedberg 
872d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
873d5859e22SJohan Hedberg 							struct sk_buff *skb)
874d5859e22SJohan Hedberg {
875d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
876d5859e22SJohan Hedberg 
877d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
878d5859e22SJohan Hedberg 
879d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
880d5859e22SJohan Hedberg }
881d5859e22SJohan Hedberg 
882d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
883d5859e22SJohan Hedberg {
884d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
885d5859e22SJohan Hedberg 
886d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
887d5859e22SJohan Hedberg 
888d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
889d5859e22SJohan Hedberg }
890d5859e22SJohan Hedberg 
891980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
892980e1a53SJohan Hedberg {
893980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
894980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
895980e1a53SJohan Hedberg 	struct hci_conn *conn;
896980e1a53SJohan Hedberg 
897980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
898980e1a53SJohan Hedberg 
89956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
90056e5cb86SJohan Hedberg 
901a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
902744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
903980e1a53SJohan Hedberg 
904980e1a53SJohan Hedberg 	if (rp->status != 0)
90556e5cb86SJohan Hedberg 		goto unlock;
906980e1a53SJohan Hedberg 
907980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
908980e1a53SJohan Hedberg 	if (!cp)
90956e5cb86SJohan Hedberg 		goto unlock;
910980e1a53SJohan Hedberg 
911980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
912980e1a53SJohan Hedberg 	if (conn)
913980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
91456e5cb86SJohan Hedberg 
91556e5cb86SJohan Hedberg unlock:
91656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
917980e1a53SJohan Hedberg }
918980e1a53SJohan Hedberg 
919980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
920980e1a53SJohan Hedberg {
921980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
922980e1a53SJohan Hedberg 
923980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
924980e1a53SJohan Hedberg 
92556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92656e5cb86SJohan Hedberg 
927a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
928744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
929980e1a53SJohan Hedberg 								rp->status);
93056e5cb86SJohan Hedberg 
93156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
932980e1a53SJohan Hedberg }
93356e5cb86SJohan Hedberg 
9346ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9356ed58ec5SVille Tervo 				       struct sk_buff *skb)
9366ed58ec5SVille Tervo {
9376ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9386ed58ec5SVille Tervo 
9396ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9406ed58ec5SVille Tervo 
9416ed58ec5SVille Tervo 	if (rp->status)
9426ed58ec5SVille Tervo 		return;
9436ed58ec5SVille Tervo 
9446ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9456ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9466ed58ec5SVille Tervo 
9476ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9486ed58ec5SVille Tervo 
9496ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9506ed58ec5SVille Tervo 
9516ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9526ed58ec5SVille Tervo }
953980e1a53SJohan Hedberg 
954a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
955a5c29683SJohan Hedberg {
956a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
957a5c29683SJohan Hedberg 
958a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
959a5c29683SJohan Hedberg 
96056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96156e5cb86SJohan Hedberg 
962a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
963744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
964a5c29683SJohan Hedberg 								rp->status);
96556e5cb86SJohan Hedberg 
96656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
967a5c29683SJohan Hedberg }
968a5c29683SJohan Hedberg 
969a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
970a5c29683SJohan Hedberg 							struct sk_buff *skb)
971a5c29683SJohan Hedberg {
972a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
973a5c29683SJohan Hedberg 
974a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
975a5c29683SJohan Hedberg 
97656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
97756e5cb86SJohan Hedberg 
978a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
979744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
980a5c29683SJohan Hedberg 								rp->status);
98156e5cb86SJohan Hedberg 
98256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
983a5c29683SJohan Hedberg }
984a5c29683SJohan Hedberg 
9851143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9861143d458SBrian Gix {
9871143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9881143d458SBrian Gix 
9891143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9901143d458SBrian Gix 
9911143d458SBrian Gix 	hci_dev_lock(hdev);
9921143d458SBrian Gix 
993a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9941143d458SBrian Gix 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
9951143d458SBrian Gix 								rp->status);
9961143d458SBrian Gix 
9971143d458SBrian Gix 	hci_dev_unlock(hdev);
9981143d458SBrian Gix }
9991143d458SBrian Gix 
10001143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10011143d458SBrian Gix 							struct sk_buff *skb)
10021143d458SBrian Gix {
10031143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10041143d458SBrian Gix 
10051143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10061143d458SBrian Gix 
10071143d458SBrian Gix 	hci_dev_lock(hdev);
10081143d458SBrian Gix 
1009a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10101143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
10111143d458SBrian Gix 								rp->status);
10121143d458SBrian Gix 
10131143d458SBrian Gix 	hci_dev_unlock(hdev);
10141143d458SBrian Gix }
10151143d458SBrian Gix 
1016c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1017c35938b2SSzymon Janc 							struct sk_buff *skb)
1018c35938b2SSzymon Janc {
1019c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1020c35938b2SSzymon Janc 
1021c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1022c35938b2SSzymon Janc 
102356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1024744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1025c35938b2SSzymon Janc 						rp->randomizer, rp->status);
102656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1027c35938b2SSzymon Janc }
1028c35938b2SSzymon Janc 
102907f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
103007f7fa5dSAndre Guedes {
103107f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
103207f7fa5dSAndre Guedes 
103307f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1034*7ba8b4beSAndre Guedes 
1035*7ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
103607f7fa5dSAndre Guedes }
103707f7fa5dSAndre Guedes 
1038eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1039eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1040eb9d91f5SAndre Guedes {
1041eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1042eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1043eb9d91f5SAndre Guedes 
1044eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1045eb9d91f5SAndre Guedes 
1046eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1047eb9d91f5SAndre Guedes 	if (!cp)
1048eb9d91f5SAndre Guedes 		return;
1049eb9d91f5SAndre Guedes 
105068a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
105168a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
1052*7ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1053*7ba8b4beSAndre Guedes 
1054*7ba8b4beSAndre Guedes 		if (status)
1055*7ba8b4beSAndre Guedes 			return;
1056*7ba8b4beSAndre Guedes 
1057d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1058d23264a8SAndre Guedes 
1059db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1060a8f13c8cSAndre Guedes 
1061a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1062eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1063c599008fSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_LE_SCAN);
1064a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
106568a8aea4SAndrei Emeltchenko 		break;
106668a8aea4SAndrei Emeltchenko 
106768a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1068*7ba8b4beSAndre Guedes 		if (status)
1069*7ba8b4beSAndre Guedes 			return;
1070*7ba8b4beSAndre Guedes 
1071d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1072d23264a8SAndre Guedes 
1073c599008fSAndre Guedes 		hci_dev_lock(hdev);
1074c599008fSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1075c599008fSAndre Guedes 		hci_dev_unlock(hdev);
1076c599008fSAndre Guedes 
1077d084329eSAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
107868a8aea4SAndrei Emeltchenko 		break;
107968a8aea4SAndrei Emeltchenko 
108068a8aea4SAndrei Emeltchenko 	default:
108168a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
108268a8aea4SAndrei Emeltchenko 		break;
108335815085SAndre Guedes 	}
1084eb9d91f5SAndre Guedes }
1085eb9d91f5SAndre Guedes 
1086a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1087a7a595f6SVinicius Costa Gomes {
1088a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_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_REPLY, rp->status);
1096a7a595f6SVinicius Costa Gomes }
1097a7a595f6SVinicius Costa Gomes 
1098a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1099a7a595f6SVinicius Costa Gomes {
1100a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1101a7a595f6SVinicius Costa Gomes 
1102a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1103a7a595f6SVinicius Costa Gomes 
1104a7a595f6SVinicius Costa Gomes 	if (rp->status)
1105a7a595f6SVinicius Costa Gomes 		return;
1106a7a595f6SVinicius Costa Gomes 
1107a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1108a7a595f6SVinicius Costa Gomes }
1109a7a595f6SVinicius Costa Gomes 
1110f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1111f9b49306SAndre Guedes 							struct sk_buff *skb)
1112f9b49306SAndre Guedes {
1113f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1114f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1115f9b49306SAndre Guedes 
1116f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1117f9b49306SAndre Guedes 
1118f9b49306SAndre Guedes 	if (status)
1119f9b49306SAndre Guedes 		return;
1120f9b49306SAndre Guedes 
1121f9b49306SAndre Guedes 	cp.page = 0x01;
1122f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1123f9b49306SAndre Guedes }
1124f9b49306SAndre Guedes 
1125a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1126a9de9248SMarcel Holtmann {
1127a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1128a9de9248SMarcel Holtmann 
1129a9de9248SMarcel Holtmann 	if (status) {
113023bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1131a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
113256e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1133a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11347a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
113556e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1136314b2381SJohan Hedberg 		return;
1137314b2381SJohan Hedberg 	}
1138314b2381SJohan Hedberg 
113989352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
114089352e7dSAndre Guedes 
114156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
114230dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_INQUIRY);
114356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1144a9de9248SMarcel Holtmann }
1145a9de9248SMarcel Holtmann 
11461da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11471da177e4SLinus Torvalds {
1148a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11491da177e4SLinus Torvalds 	struct hci_conn *conn;
11501da177e4SLinus Torvalds 
1151a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1152a9de9248SMarcel Holtmann 
1153a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11541da177e4SLinus Torvalds 	if (!cp)
11551da177e4SLinus Torvalds 		return;
11561da177e4SLinus Torvalds 
11571da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11581da177e4SLinus Torvalds 
11591da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11601da177e4SLinus Torvalds 
1161a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11621da177e4SLinus Torvalds 
11631da177e4SLinus Torvalds 	if (status) {
11641da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11654c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11661da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11671da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11681da177e4SLinus Torvalds 				hci_conn_del(conn);
11694c67bc74SMarcel Holtmann 			} else
11704c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11711da177e4SLinus Torvalds 		}
11721da177e4SLinus Torvalds 	} else {
11731da177e4SLinus Torvalds 		if (!conn) {
11741da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11751da177e4SLinus Torvalds 			if (conn) {
1176a0c808b3SJohan Hedberg 				conn->out = true;
11771da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11781da177e4SLinus Torvalds 			} else
1179893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11801da177e4SLinus Torvalds 		}
11811da177e4SLinus Torvalds 	}
11821da177e4SLinus Torvalds 
11831da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11841da177e4SLinus Torvalds }
11851da177e4SLinus Torvalds 
1186a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11871da177e4SLinus Torvalds {
1188a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11891da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11901da177e4SLinus Torvalds 	__u16 handle;
11911da177e4SLinus Torvalds 
1192b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1193b6a0dc82SMarcel Holtmann 
1194a9de9248SMarcel Holtmann 	if (!status)
1195a9de9248SMarcel Holtmann 		return;
1196a9de9248SMarcel Holtmann 
1197a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11981da177e4SLinus Torvalds 	if (!cp)
1199a9de9248SMarcel Holtmann 		return;
12001da177e4SLinus Torvalds 
12011da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12021da177e4SLinus Torvalds 
1203a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
12041da177e4SLinus Torvalds 
12051da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12061da177e4SLinus Torvalds 
12071da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12085a08ecceSAndrei Emeltchenko 	if (acl) {
12095a08ecceSAndrei Emeltchenko 		sco = acl->link;
12105a08ecceSAndrei Emeltchenko 		if (sco) {
12111da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12121da177e4SLinus Torvalds 
12131da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12141da177e4SLinus Torvalds 			hci_conn_del(sco);
12151da177e4SLinus Torvalds 		}
12165a08ecceSAndrei Emeltchenko 	}
12171da177e4SLinus Torvalds 
12181da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12191da177e4SLinus Torvalds }
12201da177e4SLinus Torvalds 
1221f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1222f8558555SMarcel Holtmann {
1223f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1224f8558555SMarcel Holtmann 	struct hci_conn *conn;
1225f8558555SMarcel Holtmann 
1226f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1227f8558555SMarcel Holtmann 
1228f8558555SMarcel Holtmann 	if (!status)
1229f8558555SMarcel Holtmann 		return;
1230f8558555SMarcel Holtmann 
1231f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1232f8558555SMarcel Holtmann 	if (!cp)
1233f8558555SMarcel Holtmann 		return;
1234f8558555SMarcel Holtmann 
1235f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1236f8558555SMarcel Holtmann 
1237f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1238f8558555SMarcel Holtmann 	if (conn) {
1239f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1240f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1241f8558555SMarcel Holtmann 			hci_conn_put(conn);
1242f8558555SMarcel Holtmann 		}
1243f8558555SMarcel Holtmann 	}
1244f8558555SMarcel Holtmann 
1245f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1246f8558555SMarcel Holtmann }
1247f8558555SMarcel Holtmann 
1248f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1249f8558555SMarcel Holtmann {
1250f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1251f8558555SMarcel Holtmann 	struct hci_conn *conn;
1252f8558555SMarcel Holtmann 
1253f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1254f8558555SMarcel Holtmann 
1255f8558555SMarcel Holtmann 	if (!status)
1256f8558555SMarcel Holtmann 		return;
1257f8558555SMarcel Holtmann 
1258f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1259f8558555SMarcel Holtmann 	if (!cp)
1260f8558555SMarcel Holtmann 		return;
1261f8558555SMarcel Holtmann 
1262f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1263f8558555SMarcel Holtmann 
1264f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1265f8558555SMarcel Holtmann 	if (conn) {
1266f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1267f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1268f8558555SMarcel Holtmann 			hci_conn_put(conn);
1269f8558555SMarcel Holtmann 		}
1270f8558555SMarcel Holtmann 	}
1271f8558555SMarcel Holtmann 
1272f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1273f8558555SMarcel Holtmann }
1274f8558555SMarcel Holtmann 
1275127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1276392599b9SJohan Hedberg 							struct hci_conn *conn)
1277392599b9SJohan Hedberg {
1278392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1279392599b9SJohan Hedberg 		return 0;
1280392599b9SJohan Hedberg 
1281765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1282392599b9SJohan Hedberg 		return 0;
1283392599b9SJohan Hedberg 
1284392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1285e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1286aa64a8b5SJohan Hedberg 	if (!hci_conn_ssp_enabled(conn) &&
1287e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1288e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1289392599b9SJohan Hedberg 		return 0;
1290392599b9SJohan Hedberg 
1291392599b9SJohan Hedberg 	return 1;
1292392599b9SJohan Hedberg }
1293392599b9SJohan Hedberg 
129430dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
129530dc78e1SJohan Hedberg {
129630dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
129730dc78e1SJohan Hedberg 
129830dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
129930dc78e1SJohan Hedberg 
130030dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
130130dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
130230dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
130330dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
130430dc78e1SJohan Hedberg 
130530dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
130630dc78e1SJohan Hedberg }
130730dc78e1SJohan Hedberg 
1308b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
130930dc78e1SJohan Hedberg {
131030dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
131130dc78e1SJohan Hedberg 	struct inquiry_entry *e;
131230dc78e1SJohan Hedberg 
1313b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1314b644ba33SJohan Hedberg 		return false;
1315b644ba33SJohan Hedberg 
1316b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1317b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1318b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1319b644ba33SJohan Hedberg 		return true;
1320b644ba33SJohan Hedberg 	}
1321b644ba33SJohan Hedberg 
1322b644ba33SJohan Hedberg 	return false;
1323b644ba33SJohan Hedberg }
1324b644ba33SJohan Hedberg 
1325b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1326b644ba33SJohan Hedberg 					bdaddr_t *bdaddr, u8 *name, u8 name_len)
1327b644ba33SJohan Hedberg {
1328b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1329b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1330b644ba33SJohan Hedberg 
1331b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
1332b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00,
1333b644ba33SJohan Hedberg 					name, name_len, conn->dev_class);
1334b644ba33SJohan Hedberg 
1335b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1336b644ba33SJohan Hedberg 		return;
1337b644ba33SJohan Hedberg 
133830dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
133930dc78e1SJohan Hedberg 		goto discov_complete;
134030dc78e1SJohan Hedberg 
134130dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
134230dc78e1SJohan Hedberg 		return;
134330dc78e1SJohan Hedberg 
134430dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
134530dc78e1SJohan Hedberg 	if (e) {
134630dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
134730dc78e1SJohan Hedberg 		list_del(&e->list);
1348b644ba33SJohan Hedberg 		if (name)
1349b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1350b644ba33SJohan Hedberg 					e->data.rssi, name, name_len);
135130dc78e1SJohan Hedberg 	}
135230dc78e1SJohan Hedberg 
1353b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
135430dc78e1SJohan Hedberg 		return;
135530dc78e1SJohan Hedberg 
135630dc78e1SJohan Hedberg discov_complete:
135730dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
135830dc78e1SJohan Hedberg }
135930dc78e1SJohan Hedberg 
1360a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13611da177e4SLinus Torvalds {
1362127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1363127178d2SJohan Hedberg 	struct hci_conn *conn;
1364127178d2SJohan Hedberg 
1365a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1366127178d2SJohan Hedberg 
1367127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1368127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1369127178d2SJohan Hedberg 	if (!status)
1370127178d2SJohan Hedberg 		return;
1371127178d2SJohan Hedberg 
1372127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1373127178d2SJohan Hedberg 	if (!cp)
1374127178d2SJohan Hedberg 		return;
1375127178d2SJohan Hedberg 
1376127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1377127178d2SJohan Hedberg 
1378127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1379b644ba33SJohan Hedberg 
1380b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1381b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1382b644ba33SJohan Hedberg 
138379c6c70cSJohan Hedberg 	if (!conn)
138479c6c70cSJohan Hedberg 		goto unlock;
138579c6c70cSJohan Hedberg 
138679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
138779c6c70cSJohan Hedberg 		goto unlock;
138879c6c70cSJohan Hedberg 
138951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1390127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1391127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1392127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1393127178d2SJohan Hedberg 	}
1394127178d2SJohan Hedberg 
139579c6c70cSJohan Hedberg unlock:
1396127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1397a9de9248SMarcel Holtmann }
13981da177e4SLinus Torvalds 
1399769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1400769be974SMarcel Holtmann {
1401769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1402769be974SMarcel Holtmann 	struct hci_conn *conn;
1403769be974SMarcel Holtmann 
1404769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1405769be974SMarcel Holtmann 
1406769be974SMarcel Holtmann 	if (!status)
1407769be974SMarcel Holtmann 		return;
1408769be974SMarcel Holtmann 
1409769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1410769be974SMarcel Holtmann 	if (!cp)
1411769be974SMarcel Holtmann 		return;
1412769be974SMarcel Holtmann 
1413769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1414769be974SMarcel Holtmann 
1415769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1416769be974SMarcel Holtmann 	if (conn) {
1417769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1418769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1419769be974SMarcel Holtmann 			hci_conn_put(conn);
1420769be974SMarcel Holtmann 		}
1421769be974SMarcel Holtmann 	}
1422769be974SMarcel Holtmann 
1423769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1424769be974SMarcel Holtmann }
1425769be974SMarcel Holtmann 
1426769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1427769be974SMarcel Holtmann {
1428769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1429769be974SMarcel Holtmann 	struct hci_conn *conn;
1430769be974SMarcel Holtmann 
1431769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1432769be974SMarcel Holtmann 
1433769be974SMarcel Holtmann 	if (!status)
1434769be974SMarcel Holtmann 		return;
1435769be974SMarcel Holtmann 
1436769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1437769be974SMarcel Holtmann 	if (!cp)
1438769be974SMarcel Holtmann 		return;
1439769be974SMarcel Holtmann 
1440769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1441769be974SMarcel Holtmann 
1442769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1443769be974SMarcel Holtmann 	if (conn) {
1444769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1445769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1446769be974SMarcel Holtmann 			hci_conn_put(conn);
1447769be974SMarcel Holtmann 		}
1448769be974SMarcel Holtmann 	}
1449769be974SMarcel Holtmann 
1450769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1451769be974SMarcel Holtmann }
1452769be974SMarcel Holtmann 
1453a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1454a9de9248SMarcel Holtmann {
1455b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1456b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1457b6a0dc82SMarcel Holtmann 	__u16 handle;
1458b6a0dc82SMarcel Holtmann 
1459a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1460b6a0dc82SMarcel Holtmann 
1461b6a0dc82SMarcel Holtmann 	if (!status)
1462b6a0dc82SMarcel Holtmann 		return;
1463b6a0dc82SMarcel Holtmann 
1464b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1465b6a0dc82SMarcel Holtmann 	if (!cp)
1466b6a0dc82SMarcel Holtmann 		return;
1467b6a0dc82SMarcel Holtmann 
1468b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1469b6a0dc82SMarcel Holtmann 
1470b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1471b6a0dc82SMarcel Holtmann 
1472b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1473b6a0dc82SMarcel Holtmann 
1474b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14755a08ecceSAndrei Emeltchenko 	if (acl) {
14765a08ecceSAndrei Emeltchenko 		sco = acl->link;
14775a08ecceSAndrei Emeltchenko 		if (sco) {
1478b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1479b6a0dc82SMarcel Holtmann 
1480b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1481b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1482b6a0dc82SMarcel Holtmann 		}
14835a08ecceSAndrei Emeltchenko 	}
1484b6a0dc82SMarcel Holtmann 
1485b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1486a9de9248SMarcel Holtmann }
1487a9de9248SMarcel Holtmann 
1488a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1489a9de9248SMarcel Holtmann {
1490a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
149104837f64SMarcel Holtmann 	struct hci_conn *conn;
149204837f64SMarcel Holtmann 
1493a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1494a9de9248SMarcel Holtmann 
1495a9de9248SMarcel Holtmann 	if (!status)
1496a9de9248SMarcel Holtmann 		return;
1497a9de9248SMarcel Holtmann 
1498a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
149904837f64SMarcel Holtmann 	if (!cp)
1500a9de9248SMarcel Holtmann 		return;
150104837f64SMarcel Holtmann 
150204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
150304837f64SMarcel Holtmann 
150404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1505e73439d8SMarcel Holtmann 	if (conn) {
150651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
150704837f64SMarcel Holtmann 
150851a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1509e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1510e73439d8SMarcel Holtmann 	}
1511e73439d8SMarcel Holtmann 
151204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
151304837f64SMarcel Holtmann }
151404837f64SMarcel Holtmann 
1515a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1516a9de9248SMarcel Holtmann {
1517a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
151804837f64SMarcel Holtmann 	struct hci_conn *conn;
151904837f64SMarcel Holtmann 
1520a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1521a9de9248SMarcel Holtmann 
1522a9de9248SMarcel Holtmann 	if (!status)
1523a9de9248SMarcel Holtmann 		return;
1524a9de9248SMarcel Holtmann 
1525a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
152604837f64SMarcel Holtmann 	if (!cp)
1527a9de9248SMarcel Holtmann 		return;
152804837f64SMarcel Holtmann 
152904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
153004837f64SMarcel Holtmann 
153104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1532e73439d8SMarcel Holtmann 	if (conn) {
153351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
153404837f64SMarcel Holtmann 
153551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1536e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1537e73439d8SMarcel Holtmann 	}
1538e73439d8SMarcel Holtmann 
153904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
154004837f64SMarcel Holtmann }
154104837f64SMarcel Holtmann 
1542fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1543fcd89c09SVille Tervo {
1544fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1545fcd89c09SVille Tervo 	struct hci_conn *conn;
1546fcd89c09SVille Tervo 
1547fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1548fcd89c09SVille Tervo 
1549fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1550fcd89c09SVille Tervo 	if (!cp)
1551fcd89c09SVille Tervo 		return;
1552fcd89c09SVille Tervo 
1553fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1554fcd89c09SVille Tervo 
1555fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1556fcd89c09SVille Tervo 
1557fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1558fcd89c09SVille Tervo 		conn);
1559fcd89c09SVille Tervo 
1560fcd89c09SVille Tervo 	if (status) {
1561fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1562fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1563fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1564fcd89c09SVille Tervo 			hci_conn_del(conn);
1565fcd89c09SVille Tervo 		}
1566fcd89c09SVille Tervo 	} else {
1567fcd89c09SVille Tervo 		if (!conn) {
1568fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
156929b7988aSAndre Guedes 			if (conn) {
157029b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1571a0c808b3SJohan Hedberg 				conn->out = true;
157229b7988aSAndre Guedes 			} else {
1573fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1574fcd89c09SVille Tervo 			}
1575fcd89c09SVille Tervo 		}
157629b7988aSAndre Guedes 	}
1577fcd89c09SVille Tervo 
1578fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1579fcd89c09SVille Tervo }
1580fcd89c09SVille Tervo 
1581a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1582a7a595f6SVinicius Costa Gomes {
1583a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1584a7a595f6SVinicius Costa Gomes }
1585a7a595f6SVinicius Costa Gomes 
15861da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15871da177e4SLinus Torvalds {
15881da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
158930dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
159030dc78e1SJohan Hedberg 	struct inquiry_entry *e;
15911da177e4SLinus Torvalds 
15921da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
15931da177e4SLinus Torvalds 
159423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
15956bd57416SMarcel Holtmann 
1596a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
159789352e7dSAndre Guedes 
159889352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
159989352e7dSAndre Guedes 		return;
160089352e7dSAndre Guedes 
1601a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
160230dc78e1SJohan Hedberg 		return;
160330dc78e1SJohan Hedberg 
160456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
160530dc78e1SJohan Hedberg 
160630dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_INQUIRY)
160730dc78e1SJohan Hedberg 		goto unlock;
160830dc78e1SJohan Hedberg 
160930dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1610ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
161130dc78e1SJohan Hedberg 		goto unlock;
161230dc78e1SJohan Hedberg 	}
161330dc78e1SJohan Hedberg 
161430dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
161530dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
161630dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
161730dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
161830dc78e1SJohan Hedberg 	} else {
161930dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
162030dc78e1SJohan Hedberg 	}
162130dc78e1SJohan Hedberg 
162230dc78e1SJohan Hedberg unlock:
162356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16241da177e4SLinus Torvalds }
16251da177e4SLinus Torvalds 
16261da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16271da177e4SLinus Torvalds {
162845bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1629a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16301da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16311da177e4SLinus Torvalds 
16321da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16331da177e4SLinus Torvalds 
163445bb4bf0SMarcel Holtmann 	if (!num_rsp)
163545bb4bf0SMarcel Holtmann 		return;
163645bb4bf0SMarcel Holtmann 
16371da177e4SLinus Torvalds 	hci_dev_lock(hdev);
163845bb4bf0SMarcel Holtmann 
1639e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
16403175405bSJohan Hedberg 		bool name_known;
16413175405bSJohan Hedberg 
16421da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16431da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16441da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16451da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16461da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16471da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16481da177e4SLinus Torvalds 		data.rssi		= 0x00;
164941a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16503175405bSJohan Hedberg 
16513175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false);
165248264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
16537d262f86SAndre Guedes 					info->dev_class, 0, !name_known,
16547d262f86SAndre Guedes 					NULL, 0);
16551da177e4SLinus Torvalds 	}
165645bb4bf0SMarcel Holtmann 
16571da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16581da177e4SLinus Torvalds }
16591da177e4SLinus Torvalds 
1660a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16611da177e4SLinus Torvalds {
1662a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1663a9de9248SMarcel Holtmann 	struct hci_conn *conn;
16641da177e4SLinus Torvalds 
1665a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
166645bb4bf0SMarcel Holtmann 
16671da177e4SLinus Torvalds 	hci_dev_lock(hdev);
166845bb4bf0SMarcel Holtmann 
1669a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16709499237aSMarcel Holtmann 	if (!conn) {
16719499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16729499237aSMarcel Holtmann 			goto unlock;
16739499237aSMarcel Holtmann 
16749499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1675a9de9248SMarcel Holtmann 		if (!conn)
1676a9de9248SMarcel Holtmann 			goto unlock;
167745bb4bf0SMarcel Holtmann 
16789499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16799499237aSMarcel Holtmann 	}
16809499237aSMarcel Holtmann 
1681a9de9248SMarcel Holtmann 	if (!ev->status) {
1682a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1683769be974SMarcel Holtmann 
1684769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1685769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1686769be974SMarcel Holtmann 			hci_conn_hold(conn);
1687052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1688769be974SMarcel Holtmann 		} else
1689a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1690a9de9248SMarcel Holtmann 
16919eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
16927d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
16937d0db0a3SMarcel Holtmann 
1694a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1695a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1696a9de9248SMarcel Holtmann 
1697a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1698a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1699a9de9248SMarcel Holtmann 
1700a9de9248SMarcel Holtmann 		/* Get remote features */
1701a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1702a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1703a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1704769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1705769be974SMarcel Holtmann 							sizeof(cp), &cp);
170645bb4bf0SMarcel Holtmann 		}
1707a9de9248SMarcel Holtmann 
1708a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1709d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1710a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1711a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1712a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1713a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1714a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1715a9de9248SMarcel Holtmann 		}
171617d5c04cSJohan Hedberg 	} else {
1717a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
171817d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1719744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
172048264f06SJohan Hedberg 						conn->dst_type, ev->status);
172117d5c04cSJohan Hedberg 	}
172245bb4bf0SMarcel Holtmann 
1723e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1724e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
172545bb4bf0SMarcel Holtmann 
1726769be974SMarcel Holtmann 	if (ev->status) {
1727a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1728a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1729c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1730c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1731a9de9248SMarcel Holtmann 
1732a9de9248SMarcel Holtmann unlock:
17331da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1734a9de9248SMarcel Holtmann 
1735a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
17361da177e4SLinus Torvalds }
17371da177e4SLinus Torvalds 
17381da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17391da177e4SLinus Torvalds {
1740a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17411da177e4SLinus Torvalds 	int mask = hdev->link_mode;
17421da177e4SLinus Torvalds 
1743a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
17441da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
17451da177e4SLinus Torvalds 
17461da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
17471da177e4SLinus Torvalds 
1748138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1749138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
17501da177e4SLinus Torvalds 		/* Connection accepted */
1751c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17521da177e4SLinus Torvalds 		struct hci_conn *conn;
17531da177e4SLinus Torvalds 
17541da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1755b6a0dc82SMarcel Holtmann 
1756cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1757cc11b9c1SAndrei Emeltchenko 		if (ie)
1758c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1759c7bdd502SMarcel Holtmann 
17601da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17611da177e4SLinus Torvalds 		if (!conn) {
1762cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1763cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1764893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17651da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17661da177e4SLinus Torvalds 				return;
17671da177e4SLinus Torvalds 			}
17681da177e4SLinus Torvalds 		}
1769b6a0dc82SMarcel Holtmann 
17701da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
17711da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1772b6a0dc82SMarcel Holtmann 
17731da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17741da177e4SLinus Torvalds 
1775b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1776b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1777b6a0dc82SMarcel Holtmann 
17781da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17791da177e4SLinus Torvalds 
17801da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17811da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17821da177e4SLinus Torvalds 			else
17831da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17841da177e4SLinus Torvalds 
1785b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1786b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1787b6a0dc82SMarcel Holtmann 		} else {
1788b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1789b6a0dc82SMarcel Holtmann 
1790b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1791a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1792b6a0dc82SMarcel Holtmann 
1793b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1794b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1795b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1796b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1797b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1798b6a0dc82SMarcel Holtmann 
1799b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1800b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1801b6a0dc82SMarcel Holtmann 		}
18021da177e4SLinus Torvalds 	} else {
18031da177e4SLinus Torvalds 		/* Connection rejected */
18041da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18051da177e4SLinus Torvalds 
18061da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18079f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1808a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18091da177e4SLinus Torvalds 	}
18101da177e4SLinus Torvalds }
18111da177e4SLinus Torvalds 
18121da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18131da177e4SLinus Torvalds {
1814a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
181504837f64SMarcel Holtmann 	struct hci_conn *conn;
18161da177e4SLinus Torvalds 
18171da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
18181da177e4SLinus Torvalds 
18191da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18201da177e4SLinus Torvalds 
182104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1822f7520543SJohan Hedberg 	if (!conn)
1823f7520543SJohan Hedberg 		goto unlock;
1824f7520543SJohan Hedberg 
182537d9ef76SJohan Hedberg 	if (ev->status == 0)
18261da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18277d0db0a3SMarcel Holtmann 
1828b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1829b644ba33SJohan Hedberg 			(conn->type == ACL_LINK || conn->type == LE_LINK)) {
183037d9ef76SJohan Hedberg 		if (ev->status != 0)
183137d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
183237d9ef76SJohan Hedberg 		else
1833afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
183448264f06SJohan Hedberg 							conn->dst_type);
183537d9ef76SJohan Hedberg 	}
1836f7520543SJohan Hedberg 
183737d9ef76SJohan Hedberg 	if (ev->status == 0) {
18382950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
18391da177e4SLinus Torvalds 		hci_conn_del(conn);
184037d9ef76SJohan Hedberg 	}
18411da177e4SLinus Torvalds 
1842f7520543SJohan Hedberg unlock:
18431da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18441da177e4SLinus Torvalds }
18451da177e4SLinus Torvalds 
1846a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1847a9de9248SMarcel Holtmann {
1848a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1849a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1850a9de9248SMarcel Holtmann 
1851a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1852a9de9248SMarcel Holtmann 
1853a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1854a9de9248SMarcel Holtmann 
1855a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1856d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1857d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1858d7556e20SWaldemar Rymarkiewicz 
1859765c2a96SJohan Hedberg 	if (!ev->status) {
1860aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
186151a8efd7SJohan Hedberg 				test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1862d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
186319f8def0SWaldemar Rymarkiewicz 		} else {
1864a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1865765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
186619f8def0SWaldemar Rymarkiewicz 		}
18672a611692SJohan Hedberg 	} else {
1868744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
18692a611692SJohan Hedberg 	}
1870a9de9248SMarcel Holtmann 
187151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
187251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1873a9de9248SMarcel Holtmann 
1874f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1875aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1876f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1877f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1878f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1879d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1880d7556e20SWaldemar Rymarkiewicz 									&cp);
1881f8558555SMarcel Holtmann 		} else {
1882f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1883f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1884f8558555SMarcel Holtmann 			hci_conn_put(conn);
1885f8558555SMarcel Holtmann 		}
1886052b30b0SMarcel Holtmann 	} else {
1887a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1888a9de9248SMarcel Holtmann 
1889052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1890052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1891052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1892052b30b0SMarcel Holtmann 	}
1893052b30b0SMarcel Holtmann 
189451a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1895a9de9248SMarcel Holtmann 		if (!ev->status) {
1896a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1897f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1898f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1899d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1900d7556e20SWaldemar Rymarkiewicz 									&cp);
1901a9de9248SMarcel Holtmann 		} else {
190251a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1903a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1904a9de9248SMarcel Holtmann 		}
1905a9de9248SMarcel Holtmann 	}
1906a9de9248SMarcel Holtmann 
1907d7556e20SWaldemar Rymarkiewicz unlock:
1908a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1909a9de9248SMarcel Holtmann }
1910a9de9248SMarcel Holtmann 
1911a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1912a9de9248SMarcel Holtmann {
1913127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1914127178d2SJohan Hedberg 	struct hci_conn *conn;
1915127178d2SJohan Hedberg 
1916a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1917a9de9248SMarcel Holtmann 
1918a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1919127178d2SJohan Hedberg 
1920127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1921127178d2SJohan Hedberg 
1922127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1923b644ba33SJohan Hedberg 
1924b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1925b644ba33SJohan Hedberg 		goto check_auth;
1926b644ba33SJohan Hedberg 
1927b644ba33SJohan Hedberg 	if (ev->status == 0)
1928b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1929b644ba33SJohan Hedberg 					strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1930b644ba33SJohan Hedberg 	else
1931b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1932b644ba33SJohan Hedberg 
1933b644ba33SJohan Hedberg check_auth:
193479c6c70cSJohan Hedberg 	if (!conn)
193579c6c70cSJohan Hedberg 		goto unlock;
193679c6c70cSJohan Hedberg 
193779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
193879c6c70cSJohan Hedberg 		goto unlock;
193979c6c70cSJohan Hedberg 
194051a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1941127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1942127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1943127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1944127178d2SJohan Hedberg 	}
1945127178d2SJohan Hedberg 
194679c6c70cSJohan Hedberg unlock:
1947127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1948a9de9248SMarcel Holtmann }
1949a9de9248SMarcel Holtmann 
1950a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1951a9de9248SMarcel Holtmann {
1952a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1953a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1954a9de9248SMarcel Holtmann 
1955a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1956a9de9248SMarcel Holtmann 
1957a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1958a9de9248SMarcel Holtmann 
1959a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1960a9de9248SMarcel Holtmann 	if (conn) {
1961a9de9248SMarcel Holtmann 		if (!ev->status) {
1962ae293196SMarcel Holtmann 			if (ev->encrypt) {
1963ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1964ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1965a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1966da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1967ae293196SMarcel Holtmann 			} else
1968a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1969a9de9248SMarcel Holtmann 		}
1970a9de9248SMarcel Holtmann 
197151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1972a9de9248SMarcel Holtmann 
1973f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1974f8558555SMarcel Holtmann 			if (!ev->status)
1975f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1976f8558555SMarcel Holtmann 
1977f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1978f8558555SMarcel Holtmann 			hci_conn_put(conn);
1979f8558555SMarcel Holtmann 		} else
1980a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1981a9de9248SMarcel Holtmann 	}
1982a9de9248SMarcel Holtmann 
1983a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1984a9de9248SMarcel Holtmann }
1985a9de9248SMarcel Holtmann 
1986a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1987a9de9248SMarcel Holtmann {
1988a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1989a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1990a9de9248SMarcel Holtmann 
1991a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1992a9de9248SMarcel Holtmann 
1993a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1994a9de9248SMarcel Holtmann 
1995a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1996a9de9248SMarcel Holtmann 	if (conn) {
1997a9de9248SMarcel Holtmann 		if (!ev->status)
1998a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1999a9de9248SMarcel Holtmann 
200051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2001a9de9248SMarcel Holtmann 
2002a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2003a9de9248SMarcel Holtmann 	}
2004a9de9248SMarcel Holtmann 
2005a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2006a9de9248SMarcel Holtmann }
2007a9de9248SMarcel Holtmann 
2008a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2009a9de9248SMarcel Holtmann {
2010a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2011a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2012a9de9248SMarcel Holtmann 
2013a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2014a9de9248SMarcel Holtmann 
2015a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2016a9de9248SMarcel Holtmann 
2017a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2018ccd556feSJohan Hedberg 	if (!conn)
2019ccd556feSJohan Hedberg 		goto unlock;
2020ccd556feSJohan Hedberg 
2021769be974SMarcel Holtmann 	if (!ev->status)
2022a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2023a9de9248SMarcel Holtmann 
2024ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2025ccd556feSJohan Hedberg 		goto unlock;
2026ccd556feSJohan Hedberg 
2027ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2028769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2029769be974SMarcel Holtmann 		cp.handle = ev->handle;
2030769be974SMarcel Holtmann 		cp.page = 0x01;
2031ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2032769be974SMarcel Holtmann 							sizeof(cp), &cp);
2033392599b9SJohan Hedberg 		goto unlock;
2034392599b9SJohan Hedberg 	}
2035392599b9SJohan Hedberg 
2036127178d2SJohan Hedberg 	if (!ev->status) {
2037127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2038127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2039127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2040127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2041127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2042b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2043b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2044b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2045b644ba33SJohan Hedberg 						conn->dev_class);
2046392599b9SJohan Hedberg 
2047127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2048769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2049769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2050769be974SMarcel Holtmann 		hci_conn_put(conn);
2051769be974SMarcel Holtmann 	}
2052769be974SMarcel Holtmann 
2053ccd556feSJohan Hedberg unlock:
2054a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2055a9de9248SMarcel Holtmann }
2056a9de9248SMarcel Holtmann 
2057a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2058a9de9248SMarcel Holtmann {
2059a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2060a9de9248SMarcel Holtmann }
2061a9de9248SMarcel Holtmann 
2062a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2063a9de9248SMarcel Holtmann {
2064a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2065a9de9248SMarcel Holtmann }
2066a9de9248SMarcel Holtmann 
2067a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2068a9de9248SMarcel Holtmann {
2069a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2070a9de9248SMarcel Holtmann 	__u16 opcode;
2071a9de9248SMarcel Holtmann 
2072a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2073a9de9248SMarcel Holtmann 
2074a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2075a9de9248SMarcel Holtmann 
2076a9de9248SMarcel Holtmann 	switch (opcode) {
2077a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2078a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2079a9de9248SMarcel Holtmann 		break;
2080a9de9248SMarcel Holtmann 
2081a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2082a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2083a9de9248SMarcel Holtmann 		break;
2084a9de9248SMarcel Holtmann 
2085a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2086a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2087a9de9248SMarcel Holtmann 		break;
2088a9de9248SMarcel Holtmann 
2089a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2090a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2091a9de9248SMarcel Holtmann 		break;
2092a9de9248SMarcel Holtmann 
2093e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2094e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2095e4e8e37cSMarcel Holtmann 		break;
2096e4e8e37cSMarcel Holtmann 
2097a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2098a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2099a9de9248SMarcel Holtmann 		break;
2100a9de9248SMarcel Holtmann 
2101e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2102e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2103e4e8e37cSMarcel Holtmann 		break;
2104e4e8e37cSMarcel Holtmann 
2105e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2106e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2107e4e8e37cSMarcel Holtmann 		break;
2108e4e8e37cSMarcel Holtmann 
2109a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2110a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2111a9de9248SMarcel Holtmann 		break;
2112a9de9248SMarcel Holtmann 
2113a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2114a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2115a9de9248SMarcel Holtmann 		break;
2116a9de9248SMarcel Holtmann 
2117a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2118a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2119a9de9248SMarcel Holtmann 		break;
2120a9de9248SMarcel Holtmann 
2121a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2122a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2123a9de9248SMarcel Holtmann 		break;
2124a9de9248SMarcel Holtmann 
2125a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2126a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2127a9de9248SMarcel Holtmann 		break;
2128a9de9248SMarcel Holtmann 
2129a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2130a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2131a9de9248SMarcel Holtmann 		break;
2132a9de9248SMarcel Holtmann 
2133a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2134a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2135a9de9248SMarcel Holtmann 		break;
2136a9de9248SMarcel Holtmann 
2137a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2138a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2139a9de9248SMarcel Holtmann 		break;
2140a9de9248SMarcel Holtmann 
2141a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2142a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2143a9de9248SMarcel Holtmann 		break;
2144a9de9248SMarcel Holtmann 
2145a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2146a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2147a9de9248SMarcel Holtmann 		break;
2148a9de9248SMarcel Holtmann 
2149a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2150a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2151a9de9248SMarcel Holtmann 		break;
2152a9de9248SMarcel Holtmann 
2153333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
2154333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
2155333140b5SMarcel Holtmann 		break;
2156333140b5SMarcel Holtmann 
2157333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2158333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2159333140b5SMarcel Holtmann 		break;
2160333140b5SMarcel Holtmann 
2161a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2162a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2163a9de9248SMarcel Holtmann 		break;
2164a9de9248SMarcel Holtmann 
2165a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2166a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2167a9de9248SMarcel Holtmann 		break;
2168a9de9248SMarcel Holtmann 
2169a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2170a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2171a9de9248SMarcel Holtmann 		break;
2172a9de9248SMarcel Holtmann 
2173971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2174971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2175971e3a4bSAndre Guedes 		break;
2176971e3a4bSAndre Guedes 
2177a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2178a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2179a9de9248SMarcel Holtmann 		break;
2180a9de9248SMarcel Holtmann 
2181a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2182a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2183a9de9248SMarcel Holtmann 		break;
2184a9de9248SMarcel Holtmann 
2185350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2186350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2187350ee4cfSAndrei Emeltchenko 		break;
2188350ee4cfSAndrei Emeltchenko 
218923bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
219023bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
219123bb5763SJohan Hedberg 		break;
219223bb5763SJohan Hedberg 
21931e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
21941e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
21951e89cffbSAndrei Emeltchenko 		break;
21961e89cffbSAndrei Emeltchenko 
2197928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2198928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2199928abaa7SAndrei Emeltchenko 		break;
2200928abaa7SAndrei Emeltchenko 
2201b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2202b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2203b0916ea0SJohan Hedberg 		break;
2204b0916ea0SJohan Hedberg 
2205d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2206d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2207d5859e22SJohan Hedberg 		break;
2208d5859e22SJohan Hedberg 
2209d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2210d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2211d5859e22SJohan Hedberg 		break;
2212d5859e22SJohan Hedberg 
2213d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2214d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2215d5859e22SJohan Hedberg 		break;
2216d5859e22SJohan Hedberg 
2217d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2218d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2219d5859e22SJohan Hedberg 		break;
2220d5859e22SJohan Hedberg 
2221980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2222980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2223980e1a53SJohan Hedberg 		break;
2224980e1a53SJohan Hedberg 
2225980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2226980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2227980e1a53SJohan Hedberg 		break;
2228980e1a53SJohan Hedberg 
2229c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2230c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2231c35938b2SSzymon Janc 		break;
2232c35938b2SSzymon Janc 
22336ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22346ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22356ed58ec5SVille Tervo 		break;
22366ed58ec5SVille Tervo 
2237a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2238a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2239a5c29683SJohan Hedberg 		break;
2240a5c29683SJohan Hedberg 
2241a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2242a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2243a5c29683SJohan Hedberg 		break;
2244a5c29683SJohan Hedberg 
22451143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
22461143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
22471143d458SBrian Gix 		break;
22481143d458SBrian Gix 
22491143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
22501143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
225107f7fa5dSAndre Guedes 
225207f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
225307f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
22541143d458SBrian Gix 		break;
22551143d458SBrian Gix 
2256eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2257eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2258eb9d91f5SAndre Guedes 		break;
2259eb9d91f5SAndre Guedes 
2260a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2261a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2262a7a595f6SVinicius Costa Gomes 		break;
2263a7a595f6SVinicius Costa Gomes 
2264a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2265a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2266a7a595f6SVinicius Costa Gomes 		break;
2267a7a595f6SVinicius Costa Gomes 
2268f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2269f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2270f9b49306SAndre Guedes 		break;
2271f9b49306SAndre Guedes 
2272a9de9248SMarcel Holtmann 	default:
2273a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2274a9de9248SMarcel Holtmann 		break;
2275a9de9248SMarcel Holtmann 	}
2276a9de9248SMarcel Holtmann 
22776bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
22786bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
22796bd32326SVille Tervo 
2280a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2281a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2282a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2283c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2284a9de9248SMarcel Holtmann 	}
2285a9de9248SMarcel Holtmann }
2286a9de9248SMarcel Holtmann 
2287a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2288a9de9248SMarcel Holtmann {
2289a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2290a9de9248SMarcel Holtmann 	__u16 opcode;
2291a9de9248SMarcel Holtmann 
2292a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2293a9de9248SMarcel Holtmann 
2294a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2295a9de9248SMarcel Holtmann 
2296a9de9248SMarcel Holtmann 	switch (opcode) {
2297a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2298a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2299a9de9248SMarcel Holtmann 		break;
2300a9de9248SMarcel Holtmann 
2301a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2302a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2303a9de9248SMarcel Holtmann 		break;
2304a9de9248SMarcel Holtmann 
2305a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2306a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2307a9de9248SMarcel Holtmann 		break;
2308a9de9248SMarcel Holtmann 
2309f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2310f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2311f8558555SMarcel Holtmann 		break;
2312f8558555SMarcel Holtmann 
2313f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2314f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2315f8558555SMarcel Holtmann 		break;
2316f8558555SMarcel Holtmann 
2317a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2318a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2319a9de9248SMarcel Holtmann 		break;
2320a9de9248SMarcel Holtmann 
2321769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2322769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2323769be974SMarcel Holtmann 		break;
2324769be974SMarcel Holtmann 
2325769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2326769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2327769be974SMarcel Holtmann 		break;
2328769be974SMarcel Holtmann 
2329a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2330a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2331a9de9248SMarcel Holtmann 		break;
2332a9de9248SMarcel Holtmann 
2333a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2334a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2335a9de9248SMarcel Holtmann 		break;
2336a9de9248SMarcel Holtmann 
2337a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2338a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2339a9de9248SMarcel Holtmann 		break;
2340a9de9248SMarcel Holtmann 
23418962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
23428962ee74SJohan Hedberg 		if (ev->status != 0)
234337d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
23448962ee74SJohan Hedberg 		break;
23458962ee74SJohan Hedberg 
2346fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2347fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2348fcd89c09SVille Tervo 		break;
2349fcd89c09SVille Tervo 
2350a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2351a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2352a7a595f6SVinicius Costa Gomes 		break;
2353a7a595f6SVinicius Costa Gomes 
2354a9de9248SMarcel Holtmann 	default:
2355a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2356a9de9248SMarcel Holtmann 		break;
2357a9de9248SMarcel Holtmann 	}
2358a9de9248SMarcel Holtmann 
23596bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23606bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23616bd32326SVille Tervo 
236210572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2363a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2364a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2365c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2366a9de9248SMarcel Holtmann 	}
2367a9de9248SMarcel Holtmann }
2368a9de9248SMarcel Holtmann 
2369a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2370a9de9248SMarcel Holtmann {
2371a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2372a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2373a9de9248SMarcel Holtmann 
2374a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2375a9de9248SMarcel Holtmann 
2376a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2377a9de9248SMarcel Holtmann 
2378a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2379a9de9248SMarcel Holtmann 	if (conn) {
2380a9de9248SMarcel Holtmann 		if (!ev->status) {
2381a9de9248SMarcel Holtmann 			if (ev->role)
2382a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2383a9de9248SMarcel Holtmann 			else
2384a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2385a9de9248SMarcel Holtmann 		}
2386a9de9248SMarcel Holtmann 
238751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2388a9de9248SMarcel Holtmann 
2389a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2390a9de9248SMarcel Holtmann 	}
2391a9de9248SMarcel Holtmann 
2392a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2393a9de9248SMarcel Holtmann }
2394a9de9248SMarcel Holtmann 
23951da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
23961da177e4SLinus Torvalds {
2397a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
23981da177e4SLinus Torvalds 	int i;
23991da177e4SLinus Torvalds 
240032ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
240132ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
240232ac5b9bSAndrei Emeltchenko 		return;
240332ac5b9bSAndrei Emeltchenko 	}
240432ac5b9bSAndrei Emeltchenko 
2405c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2406c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24071da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24081da177e4SLinus Torvalds 		return;
24091da177e4SLinus Torvalds 	}
24101da177e4SLinus Torvalds 
2411c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2412c5993de8SAndrei Emeltchenko 
2413613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2414613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24151da177e4SLinus Torvalds 		struct hci_conn *conn;
24161da177e4SLinus Torvalds 		__u16  handle, count;
24171da177e4SLinus Torvalds 
2418613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2419613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24201da177e4SLinus Torvalds 
24211da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2422f4280918SAndrei Emeltchenko 		if (!conn)
2423f4280918SAndrei Emeltchenko 			continue;
2424f4280918SAndrei Emeltchenko 
24251da177e4SLinus Torvalds 		conn->sent -= count;
24261da177e4SLinus Torvalds 
2427f4280918SAndrei Emeltchenko 		switch (conn->type) {
2428f4280918SAndrei Emeltchenko 		case ACL_LINK:
242970f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
243070f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24311da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2432f4280918SAndrei Emeltchenko 			break;
2433f4280918SAndrei Emeltchenko 
2434f4280918SAndrei Emeltchenko 		case LE_LINK:
24356ed58ec5SVille Tervo 			if (hdev->le_pkts) {
24366ed58ec5SVille Tervo 				hdev->le_cnt += count;
24376ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
24386ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
24396ed58ec5SVille Tervo 			} else {
24406ed58ec5SVille Tervo 				hdev->acl_cnt += count;
24416ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
24426ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
24436ed58ec5SVille Tervo 			}
2444f4280918SAndrei Emeltchenko 			break;
2445f4280918SAndrei Emeltchenko 
2446f4280918SAndrei Emeltchenko 		case SCO_LINK:
244770f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
244870f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
24495b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2450f4280918SAndrei Emeltchenko 			break;
2451f4280918SAndrei Emeltchenko 
2452f4280918SAndrei Emeltchenko 		default:
2453f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2454f4280918SAndrei Emeltchenko 			break;
24551da177e4SLinus Torvalds 		}
24561da177e4SLinus Torvalds 	}
2457a9de9248SMarcel Holtmann 
24583eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
24591da177e4SLinus Torvalds }
24601da177e4SLinus Torvalds 
246125e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
246225e89e99SAndrei Emeltchenko 							struct sk_buff *skb)
246325e89e99SAndrei Emeltchenko {
246425e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
246525e89e99SAndrei Emeltchenko 	int i;
246625e89e99SAndrei Emeltchenko 
246725e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
246825e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
246925e89e99SAndrei Emeltchenko 		return;
247025e89e99SAndrei Emeltchenko 	}
247125e89e99SAndrei Emeltchenko 
247225e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
247325e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
247425e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
247525e89e99SAndrei Emeltchenko 		return;
247625e89e99SAndrei Emeltchenko 	}
247725e89e99SAndrei Emeltchenko 
247825e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
247925e89e99SAndrei Emeltchenko 								ev->num_hndl);
248025e89e99SAndrei Emeltchenko 
248125e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
248225e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
248325e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
248425e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
248525e89e99SAndrei Emeltchenko 
248625e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
248725e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
248825e89e99SAndrei Emeltchenko 
248925e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
249025e89e99SAndrei Emeltchenko 		if (!conn)
249125e89e99SAndrei Emeltchenko 			continue;
249225e89e99SAndrei Emeltchenko 
249325e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
249425e89e99SAndrei Emeltchenko 
249525e89e99SAndrei Emeltchenko 		switch (conn->type) {
249625e89e99SAndrei Emeltchenko 		case ACL_LINK:
249725e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
249825e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
249925e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
250025e89e99SAndrei Emeltchenko 			break;
250125e89e99SAndrei Emeltchenko 
250225e89e99SAndrei Emeltchenko 		default:
250325e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
250425e89e99SAndrei Emeltchenko 			break;
250525e89e99SAndrei Emeltchenko 		}
250625e89e99SAndrei Emeltchenko 	}
250725e89e99SAndrei Emeltchenko 
250825e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
250925e89e99SAndrei Emeltchenko }
251025e89e99SAndrei Emeltchenko 
251104837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25121da177e4SLinus Torvalds {
2513a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
251404837f64SMarcel Holtmann 	struct hci_conn *conn;
25151da177e4SLinus Torvalds 
25161da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
25171da177e4SLinus Torvalds 
25181da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25191da177e4SLinus Torvalds 
252004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
252104837f64SMarcel Holtmann 	if (conn) {
252204837f64SMarcel Holtmann 		conn->mode = ev->mode;
252304837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
252404837f64SMarcel Holtmann 
252551a8efd7SJohan Hedberg 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
252604837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
252758a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
252804837f64SMarcel Holtmann 			else
252958a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
253004837f64SMarcel Holtmann 		}
2531e73439d8SMarcel Holtmann 
253251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2533e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
253404837f64SMarcel Holtmann 	}
253504837f64SMarcel Holtmann 
253604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
253704837f64SMarcel Holtmann }
253804837f64SMarcel Holtmann 
25391da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25401da177e4SLinus Torvalds {
2541052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2542052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2543052b30b0SMarcel Holtmann 
2544a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2545052b30b0SMarcel Holtmann 
2546052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2547052b30b0SMarcel Holtmann 
2548052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2549b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2550b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2551b6f98044SWaldemar Rymarkiewicz 
2552b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2553052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2554052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2555052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2556052b30b0SMarcel Holtmann 	}
2557052b30b0SMarcel Holtmann 
2558a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
255903b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
256003b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2561a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2562a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2563a770bb5aSWaldemar Rymarkiewicz 
2564a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2565a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2566a770bb5aSWaldemar Rymarkiewicz 		else
2567a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2568a770bb5aSWaldemar Rymarkiewicz 
2569744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2570a770bb5aSWaldemar Rymarkiewicz 	}
2571980e1a53SJohan Hedberg 
2572b6f98044SWaldemar Rymarkiewicz unlock:
2573052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
25741da177e4SLinus Torvalds }
25751da177e4SLinus Torvalds 
25761da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25771da177e4SLinus Torvalds {
257855ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
257955ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
258055ed8ca1SJohan Hedberg 	struct hci_conn *conn;
258155ed8ca1SJohan Hedberg 	struct link_key *key;
258255ed8ca1SJohan Hedberg 
2583a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
258455ed8ca1SJohan Hedberg 
2585a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
258655ed8ca1SJohan Hedberg 		return;
258755ed8ca1SJohan Hedberg 
258855ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
258955ed8ca1SJohan Hedberg 
259055ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
259155ed8ca1SJohan Hedberg 	if (!key) {
259255ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
259355ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
259455ed8ca1SJohan Hedberg 		goto not_found;
259555ed8ca1SJohan Hedberg 	}
259655ed8ca1SJohan Hedberg 
259755ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
259855ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
259955ed8ca1SJohan Hedberg 
2600a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2601b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
260255ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
260355ed8ca1SJohan Hedberg 		goto not_found;
260455ed8ca1SJohan Hedberg 	}
260555ed8ca1SJohan Hedberg 
260655ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
260760b83f57SWaldemar Rymarkiewicz 	if (conn) {
260860b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
260960b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
261060b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
261155ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
261255ed8ca1SJohan Hedberg 			goto not_found;
261355ed8ca1SJohan Hedberg 		}
261455ed8ca1SJohan Hedberg 
261560b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
261660b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
261760b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
261860b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
261960b83f57SWaldemar Rymarkiewicz 			goto not_found;
262060b83f57SWaldemar Rymarkiewicz 		}
262160b83f57SWaldemar Rymarkiewicz 
262260b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
262360b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
262460b83f57SWaldemar Rymarkiewicz 	}
262560b83f57SWaldemar Rymarkiewicz 
262655ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
262755ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
262855ed8ca1SJohan Hedberg 
262955ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
263055ed8ca1SJohan Hedberg 
263155ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
263255ed8ca1SJohan Hedberg 
263355ed8ca1SJohan Hedberg 	return;
263455ed8ca1SJohan Hedberg 
263555ed8ca1SJohan Hedberg not_found:
263655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
263755ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
26381da177e4SLinus Torvalds }
26391da177e4SLinus Torvalds 
26401da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
26411da177e4SLinus Torvalds {
2642052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2643052b30b0SMarcel Holtmann 	struct hci_conn *conn;
264455ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2645052b30b0SMarcel Holtmann 
2646a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2647052b30b0SMarcel Holtmann 
2648052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2649052b30b0SMarcel Holtmann 
2650052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2651052b30b0SMarcel Holtmann 	if (conn) {
2652052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2653052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2654980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
265513d39315SWaldemar Rymarkiewicz 
265613d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
265713d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
265813d39315SWaldemar Rymarkiewicz 
2659052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2660052b30b0SMarcel Holtmann 	}
2661052b30b0SMarcel Holtmann 
2662a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2663d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
266455ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
266555ed8ca1SJohan Hedberg 
2666052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26671da177e4SLinus Torvalds }
26681da177e4SLinus Torvalds 
266904837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
267004837f64SMarcel Holtmann {
2671a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
267204837f64SMarcel Holtmann 	struct hci_conn *conn;
267304837f64SMarcel Holtmann 
267404837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
267504837f64SMarcel Holtmann 
267604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
267704837f64SMarcel Holtmann 
267804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
26791da177e4SLinus Torvalds 	if (conn && !ev->status) {
26801da177e4SLinus Torvalds 		struct inquiry_entry *ie;
26811da177e4SLinus Torvalds 
2682cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2683cc11b9c1SAndrei Emeltchenko 		if (ie) {
26841da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
26851da177e4SLinus Torvalds 			ie->timestamp = jiffies;
26861da177e4SLinus Torvalds 		}
26871da177e4SLinus Torvalds 	}
26881da177e4SLinus Torvalds 
26891da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
26901da177e4SLinus Torvalds }
26911da177e4SLinus Torvalds 
2692a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2693a8746417SMarcel Holtmann {
2694a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2695a8746417SMarcel Holtmann 	struct hci_conn *conn;
2696a8746417SMarcel Holtmann 
2697a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2698a8746417SMarcel Holtmann 
2699a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2700a8746417SMarcel Holtmann 
2701a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2702a8746417SMarcel Holtmann 	if (conn && !ev->status)
2703a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2704a8746417SMarcel Holtmann 
2705a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2706a8746417SMarcel Holtmann }
2707a8746417SMarcel Holtmann 
270885a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
270985a1e930SMarcel Holtmann {
2710a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
271185a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
271285a1e930SMarcel Holtmann 
271385a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
271485a1e930SMarcel Holtmann 
271585a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
271685a1e930SMarcel Holtmann 
2717cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2718cc11b9c1SAndrei Emeltchenko 	if (ie) {
271985a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
272085a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
272185a1e930SMarcel Holtmann 	}
272285a1e930SMarcel Holtmann 
272385a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
272485a1e930SMarcel Holtmann }
272585a1e930SMarcel Holtmann 
2726a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2727a9de9248SMarcel Holtmann {
2728a9de9248SMarcel Holtmann 	struct inquiry_data data;
2729a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
27303175405bSJohan Hedberg 	bool name_known;
2731a9de9248SMarcel Holtmann 
2732a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2733a9de9248SMarcel Holtmann 
2734a9de9248SMarcel Holtmann 	if (!num_rsp)
2735a9de9248SMarcel Holtmann 		return;
2736a9de9248SMarcel Holtmann 
2737a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2738a9de9248SMarcel Holtmann 
2739a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2740138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2741138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2742a9de9248SMarcel Holtmann 
2743e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2744a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2745a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2746a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2747a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2748a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2749a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2750a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
275141a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27523175405bSJohan Hedberg 
27533175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27543175405bSJohan Hedberg 								false);
275548264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2756e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27577d262f86SAndre Guedes 						!name_known, NULL, 0);
2758a9de9248SMarcel Holtmann 		}
2759a9de9248SMarcel Holtmann 	} else {
2760a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2761a9de9248SMarcel Holtmann 
2762e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2763a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2764a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2765a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2766a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2767a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2768a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2769a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
277041a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27713175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27723175405bSJohan Hedberg 								false);
277348264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2774e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27757d262f86SAndre Guedes 						!name_known, NULL, 0);
2776a9de9248SMarcel Holtmann 		}
2777a9de9248SMarcel Holtmann 	}
2778a9de9248SMarcel Holtmann 
2779a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2780a9de9248SMarcel Holtmann }
2781a9de9248SMarcel Holtmann 
2782a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2783a9de9248SMarcel Holtmann {
278441a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
278541a96212SMarcel Holtmann 	struct hci_conn *conn;
278641a96212SMarcel Holtmann 
2787a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
278841a96212SMarcel Holtmann 
278941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
279041a96212SMarcel Holtmann 
279141a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2792ccd556feSJohan Hedberg 	if (!conn)
2793ccd556feSJohan Hedberg 		goto unlock;
2794ccd556feSJohan Hedberg 
2795769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
279641a96212SMarcel Holtmann 		struct inquiry_entry *ie;
279741a96212SMarcel Holtmann 
2798cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2799cc11b9c1SAndrei Emeltchenko 		if (ie)
280041a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
280141a96212SMarcel Holtmann 
280258a681efSJohan Hedberg 		if (ev->features[0] & 0x01)
280358a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
280441a96212SMarcel Holtmann 	}
280541a96212SMarcel Holtmann 
2806ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2807ccd556feSJohan Hedberg 		goto unlock;
2808ccd556feSJohan Hedberg 
2809127178d2SJohan Hedberg 	if (!ev->status) {
2810127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2811127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2812127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2813127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2814127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2815b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2816b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2817b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2818b644ba33SJohan Hedberg 						conn->dev_class);
2819392599b9SJohan Hedberg 
2820127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2821769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2822769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2823769be974SMarcel Holtmann 		hci_conn_put(conn);
2824769be974SMarcel Holtmann 	}
2825769be974SMarcel Holtmann 
2826ccd556feSJohan Hedberg unlock:
282741a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2828a9de9248SMarcel Holtmann }
2829a9de9248SMarcel Holtmann 
2830a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2831a9de9248SMarcel Holtmann {
2832b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2833b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2834b6a0dc82SMarcel Holtmann 
2835b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2836b6a0dc82SMarcel Holtmann 
2837b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2838b6a0dc82SMarcel Holtmann 
2839b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
28409dc0a3afSMarcel Holtmann 	if (!conn) {
28419dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
28429dc0a3afSMarcel Holtmann 			goto unlock;
28439dc0a3afSMarcel Holtmann 
28449dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2845b6a0dc82SMarcel Holtmann 		if (!conn)
2846b6a0dc82SMarcel Holtmann 			goto unlock;
2847b6a0dc82SMarcel Holtmann 
28489dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
28499dc0a3afSMarcel Holtmann 	}
28509dc0a3afSMarcel Holtmann 
2851732547f9SMarcel Holtmann 	switch (ev->status) {
2852732547f9SMarcel Holtmann 	case 0x00:
2853732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2854732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2855732547f9SMarcel Holtmann 
28569eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2857732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2858732547f9SMarcel Holtmann 		break;
2859732547f9SMarcel Holtmann 
2860705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2861732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
28621038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2863732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2864732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2865efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2866efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2867efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2868efc7688bSMarcel Holtmann 			goto unlock;
2869efc7688bSMarcel Holtmann 		}
2870732547f9SMarcel Holtmann 		/* fall through */
2871efc7688bSMarcel Holtmann 
2872732547f9SMarcel Holtmann 	default:
2873b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2874732547f9SMarcel Holtmann 		break;
2875732547f9SMarcel Holtmann 	}
2876b6a0dc82SMarcel Holtmann 
2877b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2878b6a0dc82SMarcel Holtmann 	if (ev->status)
2879b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2880b6a0dc82SMarcel Holtmann 
2881b6a0dc82SMarcel Holtmann unlock:
2882b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2883a9de9248SMarcel Holtmann }
2884a9de9248SMarcel Holtmann 
2885a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2886a9de9248SMarcel Holtmann {
2887a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2888a9de9248SMarcel Holtmann }
2889a9de9248SMarcel Holtmann 
289004837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
289104837f64SMarcel Holtmann {
2892a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
289304837f64SMarcel Holtmann 
289404837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
289504837f64SMarcel Holtmann }
289604837f64SMarcel Holtmann 
2897a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2898a9de9248SMarcel Holtmann {
2899a9de9248SMarcel Holtmann 	struct inquiry_data data;
2900a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2901a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2902a9de9248SMarcel Holtmann 
2903a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2904a9de9248SMarcel Holtmann 
2905a9de9248SMarcel Holtmann 	if (!num_rsp)
2906a9de9248SMarcel Holtmann 		return;
2907a9de9248SMarcel Holtmann 
2908a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2909a9de9248SMarcel Holtmann 
2910e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2911561aafbcSJohan Hedberg 		bool name_known;
2912561aafbcSJohan Hedberg 
2913a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2914a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2915a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2916a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2917a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2918a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2919a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
292041a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2921561aafbcSJohan Hedberg 
2922a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29234ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29244ddb1930SJohan Hedberg 							sizeof(info->data),
29254ddb1930SJohan Hedberg 							EIR_NAME_COMPLETE);
2926561aafbcSJohan Hedberg 		else
2927561aafbcSJohan Hedberg 			name_known = true;
2928561aafbcSJohan Hedberg 
29293175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known);
293048264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2931561aafbcSJohan Hedberg 						info->dev_class, info->rssi,
29327d262f86SAndre Guedes 						!name_known, info->data,
29337d262f86SAndre Guedes 						sizeof(info->data));
2934a9de9248SMarcel Holtmann 	}
2935a9de9248SMarcel Holtmann 
2936a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2937a9de9248SMarcel Holtmann }
2938a9de9248SMarcel Holtmann 
293917fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
294017fa4b9dSJohan Hedberg {
294117fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
294217fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
294317fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
294417fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
294517fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
294617fa4b9dSJohan Hedberg 			return 0x02;
294717fa4b9dSJohan Hedberg 		else
294817fa4b9dSJohan Hedberg 			return 0x03;
294917fa4b9dSJohan Hedberg 	}
295017fa4b9dSJohan Hedberg 
295117fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
295217fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
295358797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
295417fa4b9dSJohan Hedberg 
295517fa4b9dSJohan Hedberg 	return conn->auth_type;
295617fa4b9dSJohan Hedberg }
295717fa4b9dSJohan Hedberg 
29580493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29590493684eSMarcel Holtmann {
29600493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
29610493684eSMarcel Holtmann 	struct hci_conn *conn;
29620493684eSMarcel Holtmann 
29630493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
29640493684eSMarcel Holtmann 
29650493684eSMarcel Holtmann 	hci_dev_lock(hdev);
29660493684eSMarcel Holtmann 
29670493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
296803b555e1SJohan Hedberg 	if (!conn)
296903b555e1SJohan Hedberg 		goto unlock;
297003b555e1SJohan Hedberg 
29710493684eSMarcel Holtmann 	hci_conn_hold(conn);
29720493684eSMarcel Holtmann 
2973a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
297403b555e1SJohan Hedberg 		goto unlock;
297503b555e1SJohan Hedberg 
2976a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
297703b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
297817fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
297917fa4b9dSJohan Hedberg 
298017fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
29817a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
29827a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
29837a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
29847a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
29857cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
29867cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
298717fa4b9dSJohan Hedberg 
298858a681efSJohan Hedberg 		if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
2989ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2990ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2991ce85ee13SSzymon Janc 		else
2992ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2993ce85ee13SSzymon Janc 
299417fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
299517fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
299603b555e1SJohan Hedberg 	} else {
299703b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
299803b555e1SJohan Hedberg 
299903b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30009f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
300103b555e1SJohan Hedberg 
300203b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
300303b555e1SJohan Hedberg 							sizeof(cp), &cp);
300403b555e1SJohan Hedberg 	}
300503b555e1SJohan Hedberg 
300603b555e1SJohan Hedberg unlock:
300703b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
300803b555e1SJohan Hedberg }
300903b555e1SJohan Hedberg 
301003b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
301103b555e1SJohan Hedberg {
301203b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
301303b555e1SJohan Hedberg 	struct hci_conn *conn;
301403b555e1SJohan Hedberg 
301503b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
301603b555e1SJohan Hedberg 
301703b555e1SJohan Hedberg 	hci_dev_lock(hdev);
301803b555e1SJohan Hedberg 
301903b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
302003b555e1SJohan Hedberg 	if (!conn)
302103b555e1SJohan Hedberg 		goto unlock;
302203b555e1SJohan Hedberg 
302303b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
302403b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
302558a681efSJohan Hedberg 	if (ev->oob_data)
302658a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
302703b555e1SJohan Hedberg 
302803b555e1SJohan Hedberg unlock:
30290493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
30300493684eSMarcel Holtmann }
30310493684eSMarcel Holtmann 
3032a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3033a5c29683SJohan Hedberg 							struct sk_buff *skb)
3034a5c29683SJohan Hedberg {
3035a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
303655bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
30377a828908SJohan Hedberg 	struct hci_conn *conn;
3038a5c29683SJohan Hedberg 
3039a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3040a5c29683SJohan Hedberg 
3041a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3042a5c29683SJohan Hedberg 
3043a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
30447a828908SJohan Hedberg 		goto unlock;
30457a828908SJohan Hedberg 
30467a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
30477a828908SJohan Hedberg 	if (!conn)
30487a828908SJohan Hedberg 		goto unlock;
30497a828908SJohan Hedberg 
30507a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
30517a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
30527a828908SJohan Hedberg 
30537a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
30547a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
30557a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
30567a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
30577a828908SJohan Hedberg 	 * bit set. */
30587a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
30597a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
30607a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
30617a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
30627a828908SJohan Hedberg 		goto unlock;
30637a828908SJohan Hedberg 	}
30647a828908SJohan Hedberg 
30657a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
30667a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
30677a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
306855bc1a37SJohan Hedberg 
306955bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
307055bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
307155bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
307251a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
307355bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
307455bc1a37SJohan Hedberg 			confirm_hint = 1;
307555bc1a37SJohan Hedberg 			goto confirm;
307655bc1a37SJohan Hedberg 		}
307755bc1a37SJohan Hedberg 
30789f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
30799f61656aSJohan Hedberg 						hdev->auto_accept_delay);
30809f61656aSJohan Hedberg 
30819f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
30829f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
30839f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
30849f61656aSJohan Hedberg 			goto unlock;
30859f61656aSJohan Hedberg 		}
30869f61656aSJohan Hedberg 
30877a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
30887a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
30897a828908SJohan Hedberg 		goto unlock;
30907a828908SJohan Hedberg 	}
30917a828908SJohan Hedberg 
309255bc1a37SJohan Hedberg confirm:
3093744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
309455bc1a37SJohan Hedberg 								confirm_hint);
3095a5c29683SJohan Hedberg 
30967a828908SJohan Hedberg unlock:
3097a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3098a5c29683SJohan Hedberg }
3099a5c29683SJohan Hedberg 
31001143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
31011143d458SBrian Gix 							struct sk_buff *skb)
31021143d458SBrian Gix {
31031143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
31041143d458SBrian Gix 
31051143d458SBrian Gix 	BT_DBG("%s", hdev->name);
31061143d458SBrian Gix 
31071143d458SBrian Gix 	hci_dev_lock(hdev);
31081143d458SBrian Gix 
3109a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
31101143d458SBrian Gix 		mgmt_user_passkey_request(hdev, &ev->bdaddr);
31111143d458SBrian Gix 
31121143d458SBrian Gix 	hci_dev_unlock(hdev);
31131143d458SBrian Gix }
31141143d458SBrian Gix 
31150493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
31160493684eSMarcel Holtmann {
31170493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
31180493684eSMarcel Holtmann 	struct hci_conn *conn;
31190493684eSMarcel Holtmann 
31200493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31210493684eSMarcel Holtmann 
31220493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31230493684eSMarcel Holtmann 
31240493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31252a611692SJohan Hedberg 	if (!conn)
31262a611692SJohan Hedberg 		goto unlock;
31272a611692SJohan Hedberg 
31282a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
31292a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
31302a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
31312a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
31322a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
313351a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3134744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
31352a611692SJohan Hedberg 
31360493684eSMarcel Holtmann 	hci_conn_put(conn);
31370493684eSMarcel Holtmann 
31382a611692SJohan Hedberg unlock:
31390493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31400493684eSMarcel Holtmann }
31410493684eSMarcel Holtmann 
314241a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
314341a96212SMarcel Holtmann {
314441a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
314541a96212SMarcel Holtmann 	struct inquiry_entry *ie;
314641a96212SMarcel Holtmann 
314741a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
314841a96212SMarcel Holtmann 
314941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
315041a96212SMarcel Holtmann 
3151cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3152cc11b9c1SAndrei Emeltchenko 	if (ie)
315341a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
315441a96212SMarcel Holtmann 
315541a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
315641a96212SMarcel Holtmann }
315741a96212SMarcel Holtmann 
31582763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
31592763eda6SSzymon Janc 							struct sk_buff *skb)
31602763eda6SSzymon Janc {
31612763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
31622763eda6SSzymon Janc 	struct oob_data *data;
31632763eda6SSzymon Janc 
31642763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
31652763eda6SSzymon Janc 
31662763eda6SSzymon Janc 	hci_dev_lock(hdev);
31672763eda6SSzymon Janc 
3168a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3169e1ba1f15SSzymon Janc 		goto unlock;
3170e1ba1f15SSzymon Janc 
31712763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
31722763eda6SSzymon Janc 	if (data) {
31732763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
31742763eda6SSzymon Janc 
31752763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31762763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
31772763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
31782763eda6SSzymon Janc 
31792763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
31802763eda6SSzymon Janc 									&cp);
31812763eda6SSzymon Janc 	} else {
31822763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
31832763eda6SSzymon Janc 
31842763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31852763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
31862763eda6SSzymon Janc 									&cp);
31872763eda6SSzymon Janc 	}
31882763eda6SSzymon Janc 
3189e1ba1f15SSzymon Janc unlock:
31902763eda6SSzymon Janc 	hci_dev_unlock(hdev);
31912763eda6SSzymon Janc }
31922763eda6SSzymon Janc 
3193fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3194fcd89c09SVille Tervo {
3195fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3196fcd89c09SVille Tervo 	struct hci_conn *conn;
3197fcd89c09SVille Tervo 
3198fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3199fcd89c09SVille Tervo 
3200fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3201fcd89c09SVille Tervo 
3202fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3203b62f328bSVille Tervo 	if (!conn) {
3204b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3205b62f328bSVille Tervo 		if (!conn) {
3206b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3207b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3208b62f328bSVille Tervo 			return;
3209b62f328bSVille Tervo 		}
321029b7988aSAndre Guedes 
321129b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3212b62f328bSVille Tervo 	}
3213fcd89c09SVille Tervo 
3214fcd89c09SVille Tervo 	if (ev->status) {
321548264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
321648264f06SJohan Hedberg 						conn->dst_type, ev->status);
3217fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3218fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3219fcd89c09SVille Tervo 		hci_conn_del(conn);
3220fcd89c09SVille Tervo 		goto unlock;
3221fcd89c09SVille Tervo 	}
3222fcd89c09SVille Tervo 
3223b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3224b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
3225b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0, 0);
322683bc71b4SVinicius Costa Gomes 
32277b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3228fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3229fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3230fcd89c09SVille Tervo 
3231fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3232fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3233fcd89c09SVille Tervo 
3234fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3235fcd89c09SVille Tervo 
3236fcd89c09SVille Tervo unlock:
3237fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3238fcd89c09SVille Tervo }
3239fcd89c09SVille Tervo 
32409aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
32419aa04c91SAndre Guedes 						struct sk_buff *skb)
32429aa04c91SAndre Guedes {
3243e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3244e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
32453c9e9195SAndre Guedes 	s8 rssi;
32469aa04c91SAndre Guedes 
32479aa04c91SAndre Guedes 	hci_dev_lock(hdev);
32489aa04c91SAndre Guedes 
3249e95beb41SAndre Guedes 	while (num_reports--) {
3250e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3251e95beb41SAndre Guedes 
32529aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
32539aa04c91SAndre Guedes 
32543c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
32553c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
32563c9e9195SAndre Guedes 					NULL, rssi, 0, ev->data, ev->length);
32573c9e9195SAndre Guedes 
3258e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
32599aa04c91SAndre Guedes 	}
32609aa04c91SAndre Guedes 
32619aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
32629aa04c91SAndre Guedes }
32639aa04c91SAndre Guedes 
3264a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3265a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3266a7a595f6SVinicius Costa Gomes {
3267a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3268a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3269bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3270a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3271c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3272a7a595f6SVinicius Costa Gomes 
3273a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3274a7a595f6SVinicius Costa Gomes 
3275a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3276a7a595f6SVinicius Costa Gomes 
3277a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3278bea710feSVinicius Costa Gomes 	if (conn == NULL)
3279bea710feSVinicius Costa Gomes 		goto not_found;
3280a7a595f6SVinicius Costa Gomes 
3281bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3282bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3283bea710feSVinicius Costa Gomes 		goto not_found;
3284bea710feSVinicius Costa Gomes 
3285bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3286a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3287c9839a11SVinicius Costa Gomes 
3288c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3289c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3290a7a595f6SVinicius Costa Gomes 
3291a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3292a7a595f6SVinicius Costa Gomes 
3293c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3294c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3295c9839a11SVinicius Costa Gomes 		kfree(ltk);
3296c9839a11SVinicius Costa Gomes 	}
3297c9839a11SVinicius Costa Gomes 
3298a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3299bea710feSVinicius Costa Gomes 
3300bea710feSVinicius Costa Gomes 	return;
3301bea710feSVinicius Costa Gomes 
3302bea710feSVinicius Costa Gomes not_found:
3303bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3304bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3305bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3306a7a595f6SVinicius Costa Gomes }
3307a7a595f6SVinicius Costa Gomes 
3308fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3309fcd89c09SVille Tervo {
3310fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3311fcd89c09SVille Tervo 
3312fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3313fcd89c09SVille Tervo 
3314fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3315fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3316fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3317fcd89c09SVille Tervo 		break;
3318fcd89c09SVille Tervo 
33199aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
33209aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
33219aa04c91SAndre Guedes 		break;
33229aa04c91SAndre Guedes 
3323a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3324a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3325a7a595f6SVinicius Costa Gomes 		break;
3326a7a595f6SVinicius Costa Gomes 
3327fcd89c09SVille Tervo 	default:
3328fcd89c09SVille Tervo 		break;
3329fcd89c09SVille Tervo 	}
3330fcd89c09SVille Tervo }
3331fcd89c09SVille Tervo 
33321da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
33331da177e4SLinus Torvalds {
3334a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3335a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
33361da177e4SLinus Torvalds 
33371da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
33381da177e4SLinus Torvalds 
3339a9de9248SMarcel Holtmann 	switch (event) {
33401da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
33411da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
33421da177e4SLinus Torvalds 		break;
33431da177e4SLinus Torvalds 
33441da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
33451da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
33461da177e4SLinus Torvalds 		break;
33471da177e4SLinus Torvalds 
3348a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3349a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
335021d9e30eSMarcel Holtmann 		break;
335121d9e30eSMarcel Holtmann 
33521da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
33531da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
33541da177e4SLinus Torvalds 		break;
33551da177e4SLinus Torvalds 
33561da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
33571da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
33581da177e4SLinus Torvalds 		break;
33591da177e4SLinus Torvalds 
33601da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
33611da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
33621da177e4SLinus Torvalds 		break;
33631da177e4SLinus Torvalds 
3364a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3365a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3366a9de9248SMarcel Holtmann 		break;
3367a9de9248SMarcel Holtmann 
33681da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
33691da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
33701da177e4SLinus Torvalds 		break;
33711da177e4SLinus Torvalds 
3372a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3373a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3374a9de9248SMarcel Holtmann 		break;
3375a9de9248SMarcel Holtmann 
3376a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3377a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3378a9de9248SMarcel Holtmann 		break;
3379a9de9248SMarcel Holtmann 
3380a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3381a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3382a9de9248SMarcel Holtmann 		break;
3383a9de9248SMarcel Holtmann 
3384a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3385a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3386a9de9248SMarcel Holtmann 		break;
3387a9de9248SMarcel Holtmann 
3388a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3389a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3390a9de9248SMarcel Holtmann 		break;
3391a9de9248SMarcel Holtmann 
3392a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3393a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3394a9de9248SMarcel Holtmann 		break;
3395a9de9248SMarcel Holtmann 
3396a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3397a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3398a9de9248SMarcel Holtmann 		break;
3399a9de9248SMarcel Holtmann 
3400a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3401a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3402a9de9248SMarcel Holtmann 		break;
3403a9de9248SMarcel Holtmann 
3404a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3405a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
34061da177e4SLinus Torvalds 		break;
34071da177e4SLinus Torvalds 
34081da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
34091da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
34101da177e4SLinus Torvalds 		break;
34111da177e4SLinus Torvalds 
34121da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
34131da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
34141da177e4SLinus Torvalds 		break;
34151da177e4SLinus Torvalds 
34161da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
34171da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
34181da177e4SLinus Torvalds 		break;
34191da177e4SLinus Torvalds 
34201da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
34211da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
34221da177e4SLinus Torvalds 		break;
34231da177e4SLinus Torvalds 
3424a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3425a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3426a8746417SMarcel Holtmann 		break;
3427a8746417SMarcel Holtmann 
342885a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
342985a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
343085a1e930SMarcel Holtmann 		break;
343185a1e930SMarcel Holtmann 
3432a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3433a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3434a9de9248SMarcel Holtmann 		break;
3435a9de9248SMarcel Holtmann 
3436a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3437a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3438a9de9248SMarcel Holtmann 		break;
3439a9de9248SMarcel Holtmann 
3440a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3441a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3442a9de9248SMarcel Holtmann 		break;
3443a9de9248SMarcel Holtmann 
3444a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3445a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3446a9de9248SMarcel Holtmann 		break;
3447a9de9248SMarcel Holtmann 
344804837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
344904837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
345004837f64SMarcel Holtmann 		break;
345104837f64SMarcel Holtmann 
3452a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3453a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
34541da177e4SLinus Torvalds 		break;
34551da177e4SLinus Torvalds 
34560493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
34570493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
34580493684eSMarcel Holtmann 		break;
34590493684eSMarcel Holtmann 
346003b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
346103b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
346203b555e1SJohan Hedberg 		break;
346303b555e1SJohan Hedberg 
3464a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3465a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3466a5c29683SJohan Hedberg 		break;
3467a5c29683SJohan Hedberg 
34681143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
34691143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
34701143d458SBrian Gix 		break;
34711143d458SBrian Gix 
34720493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
34730493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
34740493684eSMarcel Holtmann 		break;
34750493684eSMarcel Holtmann 
347641a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
347741a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
347841a96212SMarcel Holtmann 		break;
347941a96212SMarcel Holtmann 
3480fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3481fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3482fcd89c09SVille Tervo 		break;
3483fcd89c09SVille Tervo 
34842763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
34852763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
34862763eda6SSzymon Janc 		break;
34872763eda6SSzymon Janc 
348825e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
348925e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
349025e89e99SAndrei Emeltchenko 		break;
349125e89e99SAndrei Emeltchenko 
34921da177e4SLinus Torvalds 	default:
3493a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
34941da177e4SLinus Torvalds 		break;
34951da177e4SLinus Torvalds 	}
34961da177e4SLinus Torvalds 
34971da177e4SLinus Torvalds 	kfree_skb(skb);
34981da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
34991da177e4SLinus Torvalds }
35001da177e4SLinus Torvalds 
35011da177e4SLinus Torvalds /* Generate internal stack event */
35021da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
35031da177e4SLinus Torvalds {
35041da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
35051da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
35061da177e4SLinus Torvalds 	struct sk_buff *skb;
35071da177e4SLinus Torvalds 
35081da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
35091da177e4SLinus Torvalds 	if (!skb)
35101da177e4SLinus Torvalds 		return;
35111da177e4SLinus Torvalds 
35121da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
35131da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
35141da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
35151da177e4SLinus Torvalds 
35161da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
35171da177e4SLinus Torvalds 	ev->type = type;
35181da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
35191da177e4SLinus Torvalds 
3520576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3521a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3522576c7d85SMarcel Holtmann 
35230d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
35241da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3525eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
35261da177e4SLinus Torvalds 	kfree_skb(skb);
35271da177e4SLinus Torvalds }
3528e6100a25SAndre Guedes 
3529669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3530e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3531