xref: /openbmc/linux/net/bluetooth/hci_event.c (revision afc747a6)
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 */
1997005ff17SJohan Hedberg 	hdev->dev_flags &= BIT(HCI_MGMT) | BIT(HCI_SETUP) | BIT(HCI_AUTO_OFF);
200a9de9248SMarcel Holtmann }
201a9de9248SMarcel Holtmann 
202a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
203a9de9248SMarcel Holtmann {
204a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2051da177e4SLinus Torvalds 	void *sent;
2061da177e4SLinus Torvalds 
207a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2081da177e4SLinus Torvalds 
209a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2101da177e4SLinus Torvalds 	if (!sent)
211a9de9248SMarcel Holtmann 		return;
2121da177e4SLinus Torvalds 
21356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21456e5cb86SJohan Hedberg 
215a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
216744cf19eSJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
217b312b161SJohan Hedberg 
21856e5cb86SJohan Hedberg 	if (status == 0)
2191f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
22056e5cb86SJohan Hedberg 
22156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
222a9de9248SMarcel Holtmann }
223a9de9248SMarcel Holtmann 
224a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
225a9de9248SMarcel Holtmann {
226a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
227a9de9248SMarcel Holtmann 
228a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
229a9de9248SMarcel Holtmann 
230a9de9248SMarcel Holtmann 	if (rp->status)
231a9de9248SMarcel Holtmann 		return;
232a9de9248SMarcel Holtmann 
2331f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
234a9de9248SMarcel Holtmann }
235a9de9248SMarcel Holtmann 
236a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
237a9de9248SMarcel Holtmann {
238a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
239a9de9248SMarcel Holtmann 	void *sent;
240a9de9248SMarcel Holtmann 
241a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
242a9de9248SMarcel Holtmann 
243a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
244a9de9248SMarcel Holtmann 	if (!sent)
245a9de9248SMarcel Holtmann 		return;
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds 	if (!status) {
248a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
249a9de9248SMarcel Holtmann 
2501da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2511da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2521da177e4SLinus Torvalds 		else
2531da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2541da177e4SLinus Torvalds 	}
255a9de9248SMarcel Holtmann 
25623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
257a9de9248SMarcel Holtmann }
2581da177e4SLinus Torvalds 
259a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
260a9de9248SMarcel Holtmann {
261a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
262a9de9248SMarcel Holtmann 	void *sent;
263a9de9248SMarcel Holtmann 
264a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
265a9de9248SMarcel Holtmann 
266a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2671da177e4SLinus Torvalds 	if (!sent)
268a9de9248SMarcel Holtmann 		return;
2691da177e4SLinus Torvalds 
2701da177e4SLinus Torvalds 	if (!status) {
271a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
272a9de9248SMarcel Holtmann 
2731da177e4SLinus Torvalds 		if (param)
2741da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2751da177e4SLinus Torvalds 		else
2761da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2771da177e4SLinus Torvalds 	}
278a9de9248SMarcel Holtmann 
27923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2801da177e4SLinus Torvalds }
2811da177e4SLinus Torvalds 
282a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
283a9de9248SMarcel Holtmann {
28436f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28536f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
286a9de9248SMarcel Holtmann 	void *sent;
2871da177e4SLinus Torvalds 
288a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
289a9de9248SMarcel Holtmann 
290a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2911da177e4SLinus Torvalds 	if (!sent)
292a9de9248SMarcel Holtmann 		return;
2931da177e4SLinus Torvalds 
29436f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
295a9de9248SMarcel Holtmann 
29656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29756e5cb86SJohan Hedberg 
2982d7cee58SJohan Hedberg 	if (status != 0) {
299744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3002d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3012d7cee58SJohan Hedberg 		goto done;
3022d7cee58SJohan Hedberg 	}
3032d7cee58SJohan Hedberg 
3049fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3059fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
306a9de9248SMarcel Holtmann 
30773f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3081da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3099fbcbb45SJohan Hedberg 		if (!old_iscan)
310744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31116ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
31216ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31316ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31416ab91abSJohan Hedberg 									to);
31516ab91abSJohan Hedberg 		}
3169fbcbb45SJohan Hedberg 	} else if (old_iscan)
317744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3181da177e4SLinus Torvalds 
3199fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3201da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3219fbcbb45SJohan Hedberg 		if (!old_pscan)
322744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3239fbcbb45SJohan Hedberg 	} else if (old_pscan)
324744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
325a9de9248SMarcel Holtmann 
32636f7fc7eSJohan Hedberg done:
32756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
32823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3291da177e4SLinus Torvalds }
3301da177e4SLinus Torvalds 
331a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
332a9de9248SMarcel Holtmann {
333a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
334a9de9248SMarcel Holtmann 
335a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
336a9de9248SMarcel Holtmann 
337a9de9248SMarcel Holtmann 	if (rp->status)
338a9de9248SMarcel Holtmann 		return;
339a9de9248SMarcel Holtmann 
340a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
341a9de9248SMarcel Holtmann 
342a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
343a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
344a9de9248SMarcel Holtmann }
345a9de9248SMarcel Holtmann 
346a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
347a9de9248SMarcel Holtmann {
348a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
349a9de9248SMarcel Holtmann 	void *sent;
350a9de9248SMarcel Holtmann 
351a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
352a9de9248SMarcel Holtmann 
353f383f275SMarcel Holtmann 	if (status)
354f383f275SMarcel Holtmann 		return;
355f383f275SMarcel Holtmann 
356a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
357a9de9248SMarcel Holtmann 	if (!sent)
358a9de9248SMarcel Holtmann 		return;
359a9de9248SMarcel Holtmann 
360a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
361a9de9248SMarcel Holtmann }
362a9de9248SMarcel Holtmann 
363a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
364a9de9248SMarcel Holtmann {
365a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
366a9de9248SMarcel Holtmann 	__u16 setting;
367a9de9248SMarcel Holtmann 
368a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
369a9de9248SMarcel Holtmann 
370a9de9248SMarcel Holtmann 	if (rp->status)
371a9de9248SMarcel Holtmann 		return;
372a9de9248SMarcel Holtmann 
373a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
374a9de9248SMarcel Holtmann 
375a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
376a9de9248SMarcel Holtmann 		return;
377a9de9248SMarcel Holtmann 
378a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
379a9de9248SMarcel Holtmann 
380a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
381a9de9248SMarcel Holtmann 
3823c54711cSGustavo F. Padovan 	if (hdev->notify)
383a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
384a9de9248SMarcel Holtmann }
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
387a9de9248SMarcel Holtmann {
388a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
389f383f275SMarcel Holtmann 	__u16 setting;
390a9de9248SMarcel Holtmann 	void *sent;
391a9de9248SMarcel Holtmann 
392a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
393a9de9248SMarcel Holtmann 
394f383f275SMarcel Holtmann 	if (status)
395f383f275SMarcel Holtmann 		return;
396f383f275SMarcel Holtmann 
397a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
398a9de9248SMarcel Holtmann 	if (!sent)
399a9de9248SMarcel Holtmann 		return;
400a9de9248SMarcel Holtmann 
401f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4021da177e4SLinus Torvalds 
403f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
404f383f275SMarcel Holtmann 		return;
405f383f275SMarcel Holtmann 
4061da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4071da177e4SLinus Torvalds 
408a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4091da177e4SLinus Torvalds 
4103c54711cSGustavo F. Padovan 	if (hdev->notify)
4111da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4121da177e4SLinus Torvalds }
4131da177e4SLinus Torvalds 
414a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4151da177e4SLinus Torvalds {
416a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4171da177e4SLinus Torvalds 
418a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4191da177e4SLinus Torvalds 
42023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4211143e5a6SMarcel Holtmann }
4221143e5a6SMarcel Holtmann 
423333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
424333140b5SMarcel Holtmann {
425333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
426333140b5SMarcel Holtmann 
427333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
428333140b5SMarcel Holtmann 
429333140b5SMarcel Holtmann 	if (rp->status)
430333140b5SMarcel Holtmann 		return;
431333140b5SMarcel Holtmann 
432333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
433333140b5SMarcel Holtmann }
434333140b5SMarcel Holtmann 
435333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
436333140b5SMarcel Holtmann {
437333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
438333140b5SMarcel Holtmann 	void *sent;
439333140b5SMarcel Holtmann 
440333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
441333140b5SMarcel Holtmann 
442333140b5SMarcel Holtmann 	if (status)
443333140b5SMarcel Holtmann 		return;
444333140b5SMarcel Holtmann 
445333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
446333140b5SMarcel Holtmann 	if (!sent)
447333140b5SMarcel Holtmann 		return;
448333140b5SMarcel Holtmann 
449333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
450333140b5SMarcel Holtmann }
451333140b5SMarcel Holtmann 
452d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
453d5859e22SJohan Hedberg {
454d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
455d5859e22SJohan Hedberg 		return 2;
456d5859e22SJohan Hedberg 
457d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
458d5859e22SJohan Hedberg 		return 1;
459d5859e22SJohan Hedberg 
460d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
461d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
462d5859e22SJohan Hedberg 		return 1;
463d5859e22SJohan Hedberg 
464d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
465d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
466d5859e22SJohan Hedberg 			return 1;
467d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
468d5859e22SJohan Hedberg 			return 1;
469d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
470d5859e22SJohan Hedberg 			return 1;
471d5859e22SJohan Hedberg 	}
472d5859e22SJohan Hedberg 
473d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
474d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
475d5859e22SJohan Hedberg 		return 1;
476d5859e22SJohan Hedberg 
477d5859e22SJohan Hedberg 	return 0;
478d5859e22SJohan Hedberg }
479d5859e22SJohan Hedberg 
480d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
481d5859e22SJohan Hedberg {
482d5859e22SJohan Hedberg 	u8 mode;
483d5859e22SJohan Hedberg 
484d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
485d5859e22SJohan Hedberg 
486d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
487d5859e22SJohan Hedberg }
488d5859e22SJohan Hedberg 
489d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
490d5859e22SJohan Hedberg {
491d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
492d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
493d5859e22SJohan Hedberg 	 * command otherwise */
494d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
495d5859e22SJohan Hedberg 
4966de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
4976de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
4985a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
4996de6c18dSVille Tervo 		return;
5006de6c18dSVille Tervo 
501d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
502d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
503d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
504d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
505d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
506d5859e22SJohan Hedberg 
507d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
508d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
509d5859e22SJohan Hedberg 
510d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
511d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
512d5859e22SJohan Hedberg 
513d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
514d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
515d5859e22SJohan Hedberg 
516d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
517d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
518d5859e22SJohan Hedberg 
519d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
520d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
521d5859e22SJohan Hedberg 
522d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
523d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
524d5859e22SJohan Hedberg 
525d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
526d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
527d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
528d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
529d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
530d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
531d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
532d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
533d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
534d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
535d5859e22SJohan Hedberg 					 * Features Notification */
536d5859e22SJohan Hedberg 	}
537d5859e22SJohan Hedberg 
538d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
539d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
540d5859e22SJohan Hedberg 
541d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
542d5859e22SJohan Hedberg }
543d5859e22SJohan Hedberg 
544e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
545e6100a25SAndre Guedes {
546e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
547e6100a25SAndre Guedes 
548e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
549e6100a25SAndre Guedes 
550e6100a25SAndre Guedes 	if (enable_le) {
551e6100a25SAndre Guedes 		cp.le = 1;
552e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
553e6100a25SAndre Guedes 	}
554e6100a25SAndre Guedes 
555e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
556e6100a25SAndre Guedes }
557e6100a25SAndre Guedes 
558d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
559d5859e22SJohan Hedberg {
560e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
561e61ef499SAndrei Emeltchenko 		return;
562e61ef499SAndrei Emeltchenko 
563d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
564d5859e22SJohan Hedberg 
565d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
566d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
567d5859e22SJohan Hedberg 
568d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
569d5859e22SJohan Hedberg 		u8 mode = 0x01;
570d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
571d5859e22SJohan Hedberg 	}
572d5859e22SJohan Hedberg 
573d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
574d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
575d5859e22SJohan Hedberg 
576d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
577d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
578971e3a4bSAndre Guedes 
579971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
580971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
581971e3a4bSAndre Guedes 
582971e3a4bSAndre Guedes 		cp.page = 0x01;
583971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
584971e3a4bSAndre Guedes 							sizeof(cp), &cp);
585971e3a4bSAndre Guedes 	}
586e6100a25SAndre Guedes 
587e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
588e6100a25SAndre Guedes 		hci_set_le_support(hdev);
589d5859e22SJohan Hedberg }
590d5859e22SJohan Hedberg 
591a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
592a9de9248SMarcel Holtmann {
593a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5941143e5a6SMarcel Holtmann 
595a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5961143e5a6SMarcel Holtmann 
597a9de9248SMarcel Holtmann 	if (rp->status)
598a9de9248SMarcel Holtmann 		return;
5991143e5a6SMarcel Holtmann 
600a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
601e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
602d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
603e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
604d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6051da177e4SLinus Torvalds 
606a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
607a9de9248SMarcel Holtmann 					hdev->manufacturer,
608a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
609d5859e22SJohan Hedberg 
610d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
611d5859e22SJohan Hedberg 		hci_setup(hdev);
612d5859e22SJohan Hedberg }
613d5859e22SJohan Hedberg 
614d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
615d5859e22SJohan Hedberg {
616d5859e22SJohan Hedberg 	u16 link_policy = 0;
617d5859e22SJohan Hedberg 
618d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
619d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
620d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
621d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
622d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
623d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
624d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
625d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
626d5859e22SJohan Hedberg 
627d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
628d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
629d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6301da177e4SLinus Torvalds }
6311da177e4SLinus Torvalds 
632a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
633a9de9248SMarcel Holtmann {
634a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
635a9de9248SMarcel Holtmann 
636a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
637a9de9248SMarcel Holtmann 
638a9de9248SMarcel Holtmann 	if (rp->status)
639d5859e22SJohan Hedberg 		goto done;
640a9de9248SMarcel Holtmann 
641a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
642d5859e22SJohan Hedberg 
643d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
644d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
645d5859e22SJohan Hedberg 
646d5859e22SJohan Hedberg done:
647d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
648a9de9248SMarcel Holtmann }
649a9de9248SMarcel Holtmann 
650a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
651a9de9248SMarcel Holtmann {
652a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
653a9de9248SMarcel Holtmann 
654a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
655a9de9248SMarcel Holtmann 
656a9de9248SMarcel Holtmann 	if (rp->status)
657a9de9248SMarcel Holtmann 		return;
658a9de9248SMarcel Holtmann 
659a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6601da177e4SLinus Torvalds 
6611da177e4SLinus Torvalds 	/* Adjust default settings according to features
6621da177e4SLinus Torvalds 	 * supported by device. */
663a9de9248SMarcel Holtmann 
6641da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6651da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6661da177e4SLinus Torvalds 
6671da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6681da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6691da177e4SLinus Torvalds 
6705b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6711da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6725b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6735b7f9909SMarcel Holtmann 	}
6741da177e4SLinus Torvalds 
6755b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6761da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6775b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6785b7f9909SMarcel Holtmann 	}
6795b7f9909SMarcel Holtmann 
6805b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6815b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6825b7f9909SMarcel Holtmann 
6835b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6845b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6855b7f9909SMarcel Holtmann 
6865b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6875b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6881da177e4SLinus Torvalds 
689efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
690efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
691efc7688bSMarcel Holtmann 
692efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
693efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
694efc7688bSMarcel Holtmann 
695efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
696efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
697efc7688bSMarcel Holtmann 
698a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
699a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
700a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
701a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
702a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7031da177e4SLinus Torvalds }
7041da177e4SLinus Torvalds 
705971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
706971e3a4bSAndre Guedes 							struct sk_buff *skb)
707971e3a4bSAndre Guedes {
708971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
709971e3a4bSAndre Guedes 
710971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
711971e3a4bSAndre Guedes 
712971e3a4bSAndre Guedes 	if (rp->status)
713971e3a4bSAndre Guedes 		return;
714971e3a4bSAndre Guedes 
715b5b32b65SAndre Guedes 	switch (rp->page) {
716b5b32b65SAndre Guedes 	case 0:
717b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
718b5b32b65SAndre Guedes 		break;
719b5b32b65SAndre Guedes 	case 1:
72059e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
721b5b32b65SAndre Guedes 		break;
722b5b32b65SAndre Guedes 	}
723971e3a4bSAndre Guedes 
724971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
725971e3a4bSAndre Guedes }
726971e3a4bSAndre Guedes 
7271e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7281e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7291e89cffbSAndrei Emeltchenko {
7301e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7311e89cffbSAndrei Emeltchenko 
7321e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7331e89cffbSAndrei Emeltchenko 
7341e89cffbSAndrei Emeltchenko 	if (rp->status)
7351e89cffbSAndrei Emeltchenko 		return;
7361e89cffbSAndrei Emeltchenko 
7371e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7381e89cffbSAndrei Emeltchenko 
7391e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7401e89cffbSAndrei Emeltchenko }
7411e89cffbSAndrei Emeltchenko 
742a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
743a9de9248SMarcel Holtmann {
744a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
745a9de9248SMarcel Holtmann 
746a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
747a9de9248SMarcel Holtmann 
748a9de9248SMarcel Holtmann 	if (rp->status)
749a9de9248SMarcel Holtmann 		return;
750a9de9248SMarcel Holtmann 
751a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
752a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
753a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
754a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
755da1f5198SMarcel Holtmann 
756da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
757da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
758da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
759da1f5198SMarcel Holtmann 	}
760da1f5198SMarcel Holtmann 
761da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
762da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7631da177e4SLinus Torvalds 
764a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
765a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
766a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7671da177e4SLinus Torvalds }
7681da177e4SLinus Torvalds 
769a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
770a9de9248SMarcel Holtmann {
771a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7721da177e4SLinus Torvalds 
773a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
774a9de9248SMarcel Holtmann 
775a9de9248SMarcel Holtmann 	if (!rp->status)
776a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
777a9de9248SMarcel Holtmann 
77823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
77923bb5763SJohan Hedberg }
78023bb5763SJohan Hedberg 
781350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
782350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
783350ee4cfSAndrei Emeltchenko {
784350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
785350ee4cfSAndrei Emeltchenko 
786350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
787350ee4cfSAndrei Emeltchenko 
788350ee4cfSAndrei Emeltchenko 	if (rp->status)
789350ee4cfSAndrei Emeltchenko 		return;
790350ee4cfSAndrei Emeltchenko 
791350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
792350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
793350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
794350ee4cfSAndrei Emeltchenko 
795350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
796350ee4cfSAndrei Emeltchenko 
797350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
798350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
799350ee4cfSAndrei Emeltchenko 
800350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
801350ee4cfSAndrei Emeltchenko }
802350ee4cfSAndrei Emeltchenko 
80323bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
80423bb5763SJohan Hedberg {
80523bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
80623bb5763SJohan Hedberg 
80723bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
80823bb5763SJohan Hedberg 
80923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8101da177e4SLinus Torvalds }
8111da177e4SLinus Torvalds 
812928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
813928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
814928abaa7SAndrei Emeltchenko {
815928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
816928abaa7SAndrei Emeltchenko 
817928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
818928abaa7SAndrei Emeltchenko 
819928abaa7SAndrei Emeltchenko 	if (rp->status)
820928abaa7SAndrei Emeltchenko 		return;
821928abaa7SAndrei Emeltchenko 
822928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
823928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
824928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
825928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
826928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
827928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
828928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
829928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
830928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
831928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
832928abaa7SAndrei Emeltchenko 
833928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
834928abaa7SAndrei Emeltchenko }
835928abaa7SAndrei Emeltchenko 
836b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
837b0916ea0SJohan Hedberg 							struct sk_buff *skb)
838b0916ea0SJohan Hedberg {
839b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
840b0916ea0SJohan Hedberg 
841b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
842b0916ea0SJohan Hedberg 
843b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
844b0916ea0SJohan Hedberg }
845b0916ea0SJohan Hedberg 
846d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
847d5859e22SJohan Hedberg {
848d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
849d5859e22SJohan Hedberg 
850d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
851d5859e22SJohan Hedberg 
852d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
853d5859e22SJohan Hedberg }
854d5859e22SJohan Hedberg 
855d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
856d5859e22SJohan Hedberg 							struct sk_buff *skb)
857d5859e22SJohan Hedberg {
858d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
859d5859e22SJohan Hedberg 
860d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
861d5859e22SJohan Hedberg 
862d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
863d5859e22SJohan Hedberg }
864d5859e22SJohan Hedberg 
865d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
866d5859e22SJohan Hedberg 							struct sk_buff *skb)
867d5859e22SJohan Hedberg {
868d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
869d5859e22SJohan Hedberg 
870d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
871d5859e22SJohan Hedberg 
872d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
873d5859e22SJohan Hedberg }
874d5859e22SJohan Hedberg 
875d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
876d5859e22SJohan Hedberg {
877d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
878d5859e22SJohan Hedberg 
879d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
880d5859e22SJohan Hedberg 
881d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
882d5859e22SJohan Hedberg }
883d5859e22SJohan Hedberg 
884980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
885980e1a53SJohan Hedberg {
886980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
887980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
888980e1a53SJohan Hedberg 	struct hci_conn *conn;
889980e1a53SJohan Hedberg 
890980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
891980e1a53SJohan Hedberg 
89256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
89356e5cb86SJohan Hedberg 
894a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
895744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
896980e1a53SJohan Hedberg 
897980e1a53SJohan Hedberg 	if (rp->status != 0)
89856e5cb86SJohan Hedberg 		goto unlock;
899980e1a53SJohan Hedberg 
900980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
901980e1a53SJohan Hedberg 	if (!cp)
90256e5cb86SJohan Hedberg 		goto unlock;
903980e1a53SJohan Hedberg 
904980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
905980e1a53SJohan Hedberg 	if (conn)
906980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
90756e5cb86SJohan Hedberg 
90856e5cb86SJohan Hedberg unlock:
90956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
910980e1a53SJohan Hedberg }
911980e1a53SJohan Hedberg 
912980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
913980e1a53SJohan Hedberg {
914980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
915980e1a53SJohan Hedberg 
916980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
917980e1a53SJohan Hedberg 
91856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
91956e5cb86SJohan Hedberg 
920a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
921744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
922980e1a53SJohan Hedberg 								rp->status);
92356e5cb86SJohan Hedberg 
92456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
925980e1a53SJohan Hedberg }
92656e5cb86SJohan Hedberg 
9276ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9286ed58ec5SVille Tervo 				       struct sk_buff *skb)
9296ed58ec5SVille Tervo {
9306ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9316ed58ec5SVille Tervo 
9326ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9336ed58ec5SVille Tervo 
9346ed58ec5SVille Tervo 	if (rp->status)
9356ed58ec5SVille Tervo 		return;
9366ed58ec5SVille Tervo 
9376ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9386ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9396ed58ec5SVille Tervo 
9406ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9416ed58ec5SVille Tervo 
9426ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9436ed58ec5SVille Tervo 
9446ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9456ed58ec5SVille Tervo }
946980e1a53SJohan Hedberg 
947a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
948a5c29683SJohan Hedberg {
949a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
950a5c29683SJohan Hedberg 
951a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
952a5c29683SJohan Hedberg 
95356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
95456e5cb86SJohan Hedberg 
955a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
956744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
957a5c29683SJohan Hedberg 								rp->status);
95856e5cb86SJohan Hedberg 
95956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
960a5c29683SJohan Hedberg }
961a5c29683SJohan Hedberg 
962a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
963a5c29683SJohan Hedberg 							struct sk_buff *skb)
964a5c29683SJohan Hedberg {
965a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
966a5c29683SJohan Hedberg 
967a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
968a5c29683SJohan Hedberg 
96956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
97056e5cb86SJohan Hedberg 
971a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
972744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
973a5c29683SJohan Hedberg 								rp->status);
97456e5cb86SJohan Hedberg 
97556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
976a5c29683SJohan Hedberg }
977a5c29683SJohan Hedberg 
9781143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9791143d458SBrian Gix {
9801143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9811143d458SBrian Gix 
9821143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9831143d458SBrian Gix 
9841143d458SBrian Gix 	hci_dev_lock(hdev);
9851143d458SBrian Gix 
986a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9871143d458SBrian Gix 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
9881143d458SBrian Gix 								rp->status);
9891143d458SBrian Gix 
9901143d458SBrian Gix 	hci_dev_unlock(hdev);
9911143d458SBrian Gix }
9921143d458SBrian Gix 
9931143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9941143d458SBrian Gix 							struct sk_buff *skb)
9951143d458SBrian Gix {
9961143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9971143d458SBrian Gix 
9981143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9991143d458SBrian Gix 
10001143d458SBrian Gix 	hci_dev_lock(hdev);
10011143d458SBrian Gix 
1002a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10031143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
10041143d458SBrian Gix 								rp->status);
10051143d458SBrian Gix 
10061143d458SBrian Gix 	hci_dev_unlock(hdev);
10071143d458SBrian Gix }
10081143d458SBrian Gix 
1009c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1010c35938b2SSzymon Janc 							struct sk_buff *skb)
1011c35938b2SSzymon Janc {
1012c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1013c35938b2SSzymon Janc 
1014c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1015c35938b2SSzymon Janc 
101656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1017744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1018c35938b2SSzymon Janc 						rp->randomizer, rp->status);
101956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1020c35938b2SSzymon Janc }
1021c35938b2SSzymon Janc 
102207f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
102307f7fa5dSAndre Guedes {
102407f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
102507f7fa5dSAndre Guedes 
102607f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
102707f7fa5dSAndre Guedes }
102807f7fa5dSAndre Guedes 
1029eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1030eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1031eb9d91f5SAndre Guedes {
1032eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1033eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1034eb9d91f5SAndre Guedes 
1035eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1036eb9d91f5SAndre Guedes 
1037eb9d91f5SAndre Guedes 	if (status)
1038eb9d91f5SAndre Guedes 		return;
1039eb9d91f5SAndre Guedes 
1040eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1041eb9d91f5SAndre Guedes 	if (!cp)
1042eb9d91f5SAndre Guedes 		return;
1043eb9d91f5SAndre Guedes 
104468a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
104568a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
1046d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1047d23264a8SAndre Guedes 
1048db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1049a8f13c8cSAndre Guedes 
1050a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1051eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1052a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
105368a8aea4SAndrei Emeltchenko 		break;
105468a8aea4SAndrei Emeltchenko 
105568a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1056d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1057d23264a8SAndre Guedes 
1058d084329eSAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
105968a8aea4SAndrei Emeltchenko 		break;
106068a8aea4SAndrei Emeltchenko 
106168a8aea4SAndrei Emeltchenko 	default:
106268a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
106368a8aea4SAndrei Emeltchenko 		break;
106435815085SAndre Guedes 	}
1065eb9d91f5SAndre Guedes }
1066eb9d91f5SAndre Guedes 
1067a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1068a7a595f6SVinicius Costa Gomes {
1069a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1070a7a595f6SVinicius Costa Gomes 
1071a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1072a7a595f6SVinicius Costa Gomes 
1073a7a595f6SVinicius Costa Gomes 	if (rp->status)
1074a7a595f6SVinicius Costa Gomes 		return;
1075a7a595f6SVinicius Costa Gomes 
1076a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1077a7a595f6SVinicius Costa Gomes }
1078a7a595f6SVinicius Costa Gomes 
1079a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1080a7a595f6SVinicius Costa Gomes {
1081a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1082a7a595f6SVinicius Costa Gomes 
1083a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1084a7a595f6SVinicius Costa Gomes 
1085a7a595f6SVinicius Costa Gomes 	if (rp->status)
1086a7a595f6SVinicius Costa Gomes 		return;
1087a7a595f6SVinicius Costa Gomes 
1088a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1089a7a595f6SVinicius Costa Gomes }
1090a7a595f6SVinicius Costa Gomes 
1091f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1092f9b49306SAndre Guedes 							struct sk_buff *skb)
1093f9b49306SAndre Guedes {
1094f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1095f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1096f9b49306SAndre Guedes 
1097f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1098f9b49306SAndre Guedes 
1099f9b49306SAndre Guedes 	if (status)
1100f9b49306SAndre Guedes 		return;
1101f9b49306SAndre Guedes 
1102f9b49306SAndre Guedes 	cp.page = 0x01;
1103f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1104f9b49306SAndre Guedes }
1105f9b49306SAndre Guedes 
1106a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1107a9de9248SMarcel Holtmann {
1108a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1109a9de9248SMarcel Holtmann 
1110a9de9248SMarcel Holtmann 	if (status) {
111123bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1112a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
111356e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1114a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11157a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
111656e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1117314b2381SJohan Hedberg 		return;
1118314b2381SJohan Hedberg 	}
1119314b2381SJohan Hedberg 
112089352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
112189352e7dSAndre Guedes 
112256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
112330dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_INQUIRY);
112456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1125a9de9248SMarcel Holtmann }
1126a9de9248SMarcel Holtmann 
11271da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11281da177e4SLinus Torvalds {
1129a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11301da177e4SLinus Torvalds 	struct hci_conn *conn;
11311da177e4SLinus Torvalds 
1132a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1133a9de9248SMarcel Holtmann 
1134a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11351da177e4SLinus Torvalds 	if (!cp)
11361da177e4SLinus Torvalds 		return;
11371da177e4SLinus Torvalds 
11381da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11391da177e4SLinus Torvalds 
11401da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11411da177e4SLinus Torvalds 
1142a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11431da177e4SLinus Torvalds 
11441da177e4SLinus Torvalds 	if (status) {
11451da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11464c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11471da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11481da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11491da177e4SLinus Torvalds 				hci_conn_del(conn);
11504c67bc74SMarcel Holtmann 			} else
11514c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11521da177e4SLinus Torvalds 		}
11531da177e4SLinus Torvalds 	} else {
11541da177e4SLinus Torvalds 		if (!conn) {
11551da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11561da177e4SLinus Torvalds 			if (conn) {
11571da177e4SLinus Torvalds 				conn->out = 1;
11581da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11591da177e4SLinus Torvalds 			} else
1160893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11611da177e4SLinus Torvalds 		}
11621da177e4SLinus Torvalds 	}
11631da177e4SLinus Torvalds 
11641da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11651da177e4SLinus Torvalds }
11661da177e4SLinus Torvalds 
1167a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11681da177e4SLinus Torvalds {
1169a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11701da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11711da177e4SLinus Torvalds 	__u16 handle;
11721da177e4SLinus Torvalds 
1173b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1174b6a0dc82SMarcel Holtmann 
1175a9de9248SMarcel Holtmann 	if (!status)
1176a9de9248SMarcel Holtmann 		return;
1177a9de9248SMarcel Holtmann 
1178a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11791da177e4SLinus Torvalds 	if (!cp)
1180a9de9248SMarcel Holtmann 		return;
11811da177e4SLinus Torvalds 
11821da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11831da177e4SLinus Torvalds 
1184a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
11851da177e4SLinus Torvalds 
11861da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11871da177e4SLinus Torvalds 
11881da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11895a08ecceSAndrei Emeltchenko 	if (acl) {
11905a08ecceSAndrei Emeltchenko 		sco = acl->link;
11915a08ecceSAndrei Emeltchenko 		if (sco) {
11921da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11931da177e4SLinus Torvalds 
11941da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11951da177e4SLinus Torvalds 			hci_conn_del(sco);
11961da177e4SLinus Torvalds 		}
11975a08ecceSAndrei Emeltchenko 	}
11981da177e4SLinus Torvalds 
11991da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12001da177e4SLinus Torvalds }
12011da177e4SLinus Torvalds 
1202f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1203f8558555SMarcel Holtmann {
1204f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1205f8558555SMarcel Holtmann 	struct hci_conn *conn;
1206f8558555SMarcel Holtmann 
1207f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1208f8558555SMarcel Holtmann 
1209f8558555SMarcel Holtmann 	if (!status)
1210f8558555SMarcel Holtmann 		return;
1211f8558555SMarcel Holtmann 
1212f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1213f8558555SMarcel Holtmann 	if (!cp)
1214f8558555SMarcel Holtmann 		return;
1215f8558555SMarcel Holtmann 
1216f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1217f8558555SMarcel Holtmann 
1218f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1219f8558555SMarcel Holtmann 	if (conn) {
1220f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1221f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1222f8558555SMarcel Holtmann 			hci_conn_put(conn);
1223f8558555SMarcel Holtmann 		}
1224f8558555SMarcel Holtmann 	}
1225f8558555SMarcel Holtmann 
1226f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1227f8558555SMarcel Holtmann }
1228f8558555SMarcel Holtmann 
1229f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1230f8558555SMarcel Holtmann {
1231f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1232f8558555SMarcel Holtmann 	struct hci_conn *conn;
1233f8558555SMarcel Holtmann 
1234f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1235f8558555SMarcel Holtmann 
1236f8558555SMarcel Holtmann 	if (!status)
1237f8558555SMarcel Holtmann 		return;
1238f8558555SMarcel Holtmann 
1239f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1240f8558555SMarcel Holtmann 	if (!cp)
1241f8558555SMarcel Holtmann 		return;
1242f8558555SMarcel Holtmann 
1243f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1244f8558555SMarcel Holtmann 
1245f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1246f8558555SMarcel Holtmann 	if (conn) {
1247f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1248f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1249f8558555SMarcel Holtmann 			hci_conn_put(conn);
1250f8558555SMarcel Holtmann 		}
1251f8558555SMarcel Holtmann 	}
1252f8558555SMarcel Holtmann 
1253f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1254f8558555SMarcel Holtmann }
1255f8558555SMarcel Holtmann 
1256127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1257392599b9SJohan Hedberg 							struct hci_conn *conn)
1258392599b9SJohan Hedberg {
1259392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1260392599b9SJohan Hedberg 		return 0;
1261392599b9SJohan Hedberg 
1262765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1263392599b9SJohan Hedberg 		return 0;
1264392599b9SJohan Hedberg 
1265392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1266e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1267392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1268e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1269e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1270392599b9SJohan Hedberg 		return 0;
1271392599b9SJohan Hedberg 
1272392599b9SJohan Hedberg 	return 1;
1273392599b9SJohan Hedberg }
1274392599b9SJohan Hedberg 
127530dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
127630dc78e1SJohan Hedberg {
127730dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
127830dc78e1SJohan Hedberg 
127930dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
128030dc78e1SJohan Hedberg 
128130dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
128230dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
128330dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
128430dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
128530dc78e1SJohan Hedberg 
128630dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
128730dc78e1SJohan Hedberg }
128830dc78e1SJohan Hedberg 
128930dc78e1SJohan Hedberg static void hci_resolve_next_name(struct hci_dev *hdev, bdaddr_t *bdaddr)
129030dc78e1SJohan Hedberg {
129130dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
129230dc78e1SJohan Hedberg 	struct inquiry_entry *e;
129330dc78e1SJohan Hedberg 
129430dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
129530dc78e1SJohan Hedberg 		goto discov_complete;
129630dc78e1SJohan Hedberg 
129730dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
129830dc78e1SJohan Hedberg 		return;
129930dc78e1SJohan Hedberg 
130030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
130130dc78e1SJohan Hedberg 	if (e) {
130230dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
130330dc78e1SJohan Hedberg 		list_del(&e->list);
130430dc78e1SJohan Hedberg 	}
130530dc78e1SJohan Hedberg 
130630dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve))
130730dc78e1SJohan Hedberg 		goto discov_complete;
130830dc78e1SJohan Hedberg 
130930dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
131030dc78e1SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
131130dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
131230dc78e1SJohan Hedberg 		return;
131330dc78e1SJohan Hedberg 	}
131430dc78e1SJohan Hedberg 
131530dc78e1SJohan Hedberg discov_complete:
131630dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
131730dc78e1SJohan Hedberg }
131830dc78e1SJohan Hedberg 
1319a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13201da177e4SLinus Torvalds {
1321127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1322127178d2SJohan Hedberg 	struct hci_conn *conn;
1323127178d2SJohan Hedberg 
1324a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1325127178d2SJohan Hedberg 
1326127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1327127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1328127178d2SJohan Hedberg 	if (!status)
1329127178d2SJohan Hedberg 		return;
1330127178d2SJohan Hedberg 
1331127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1332127178d2SJohan Hedberg 	if (!cp)
1333127178d2SJohan Hedberg 		return;
1334127178d2SJohan Hedberg 
1335127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1336127178d2SJohan Hedberg 
1337a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
133830dc78e1SJohan Hedberg 		hci_resolve_next_name(hdev, &cp->bdaddr);
133930dc78e1SJohan Hedberg 
1340127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
134179c6c70cSJohan Hedberg 	if (!conn)
134279c6c70cSJohan Hedberg 		goto unlock;
134379c6c70cSJohan Hedberg 
134479c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
134579c6c70cSJohan Hedberg 		goto unlock;
134679c6c70cSJohan Hedberg 
134779c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1348127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1349127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1350127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1351127178d2SJohan Hedberg 	}
1352127178d2SJohan Hedberg 
135379c6c70cSJohan Hedberg unlock:
1354127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1355a9de9248SMarcel Holtmann }
13561da177e4SLinus Torvalds 
1357769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1358769be974SMarcel Holtmann {
1359769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1360769be974SMarcel Holtmann 	struct hci_conn *conn;
1361769be974SMarcel Holtmann 
1362769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1363769be974SMarcel Holtmann 
1364769be974SMarcel Holtmann 	if (!status)
1365769be974SMarcel Holtmann 		return;
1366769be974SMarcel Holtmann 
1367769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1368769be974SMarcel Holtmann 	if (!cp)
1369769be974SMarcel Holtmann 		return;
1370769be974SMarcel Holtmann 
1371769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1372769be974SMarcel Holtmann 
1373769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1374769be974SMarcel Holtmann 	if (conn) {
1375769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1376769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1377769be974SMarcel Holtmann 			hci_conn_put(conn);
1378769be974SMarcel Holtmann 		}
1379769be974SMarcel Holtmann 	}
1380769be974SMarcel Holtmann 
1381769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1382769be974SMarcel Holtmann }
1383769be974SMarcel Holtmann 
1384769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1385769be974SMarcel Holtmann {
1386769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1387769be974SMarcel Holtmann 	struct hci_conn *conn;
1388769be974SMarcel Holtmann 
1389769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1390769be974SMarcel Holtmann 
1391769be974SMarcel Holtmann 	if (!status)
1392769be974SMarcel Holtmann 		return;
1393769be974SMarcel Holtmann 
1394769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1395769be974SMarcel Holtmann 	if (!cp)
1396769be974SMarcel Holtmann 		return;
1397769be974SMarcel Holtmann 
1398769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1399769be974SMarcel Holtmann 
1400769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1401769be974SMarcel Holtmann 	if (conn) {
1402769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1403769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1404769be974SMarcel Holtmann 			hci_conn_put(conn);
1405769be974SMarcel Holtmann 		}
1406769be974SMarcel Holtmann 	}
1407769be974SMarcel Holtmann 
1408769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1409769be974SMarcel Holtmann }
1410769be974SMarcel Holtmann 
1411a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1412a9de9248SMarcel Holtmann {
1413b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1414b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1415b6a0dc82SMarcel Holtmann 	__u16 handle;
1416b6a0dc82SMarcel Holtmann 
1417a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1418b6a0dc82SMarcel Holtmann 
1419b6a0dc82SMarcel Holtmann 	if (!status)
1420b6a0dc82SMarcel Holtmann 		return;
1421b6a0dc82SMarcel Holtmann 
1422b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1423b6a0dc82SMarcel Holtmann 	if (!cp)
1424b6a0dc82SMarcel Holtmann 		return;
1425b6a0dc82SMarcel Holtmann 
1426b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1427b6a0dc82SMarcel Holtmann 
1428b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1429b6a0dc82SMarcel Holtmann 
1430b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1431b6a0dc82SMarcel Holtmann 
1432b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14335a08ecceSAndrei Emeltchenko 	if (acl) {
14345a08ecceSAndrei Emeltchenko 		sco = acl->link;
14355a08ecceSAndrei Emeltchenko 		if (sco) {
1436b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1437b6a0dc82SMarcel Holtmann 
1438b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1439b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1440b6a0dc82SMarcel Holtmann 		}
14415a08ecceSAndrei Emeltchenko 	}
1442b6a0dc82SMarcel Holtmann 
1443b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1444a9de9248SMarcel Holtmann }
1445a9de9248SMarcel Holtmann 
1446a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1447a9de9248SMarcel Holtmann {
1448a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
144904837f64SMarcel Holtmann 	struct hci_conn *conn;
145004837f64SMarcel Holtmann 
1451a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1452a9de9248SMarcel Holtmann 
1453a9de9248SMarcel Holtmann 	if (!status)
1454a9de9248SMarcel Holtmann 		return;
1455a9de9248SMarcel Holtmann 
1456a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
145704837f64SMarcel Holtmann 	if (!cp)
1458a9de9248SMarcel Holtmann 		return;
145904837f64SMarcel Holtmann 
146004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
146104837f64SMarcel Holtmann 
146204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1463e73439d8SMarcel Holtmann 	if (conn) {
146404837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
146504837f64SMarcel Holtmann 
1466e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1467e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1468e73439d8SMarcel Holtmann 	}
1469e73439d8SMarcel Holtmann 
147004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
147104837f64SMarcel Holtmann }
147204837f64SMarcel Holtmann 
1473a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1474a9de9248SMarcel Holtmann {
1475a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
147604837f64SMarcel Holtmann 	struct hci_conn *conn;
147704837f64SMarcel Holtmann 
1478a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1479a9de9248SMarcel Holtmann 
1480a9de9248SMarcel Holtmann 	if (!status)
1481a9de9248SMarcel Holtmann 		return;
1482a9de9248SMarcel Holtmann 
1483a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
148404837f64SMarcel Holtmann 	if (!cp)
1485a9de9248SMarcel Holtmann 		return;
148604837f64SMarcel Holtmann 
148704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
148804837f64SMarcel Holtmann 
148904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1490e73439d8SMarcel Holtmann 	if (conn) {
149104837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
149204837f64SMarcel Holtmann 
1493e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1494e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1495e73439d8SMarcel Holtmann 	}
1496e73439d8SMarcel Holtmann 
149704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
149804837f64SMarcel Holtmann }
149904837f64SMarcel Holtmann 
1500fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1501fcd89c09SVille Tervo {
1502fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1503fcd89c09SVille Tervo 	struct hci_conn *conn;
1504fcd89c09SVille Tervo 
1505fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1506fcd89c09SVille Tervo 
1507fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1508fcd89c09SVille Tervo 	if (!cp)
1509fcd89c09SVille Tervo 		return;
1510fcd89c09SVille Tervo 
1511fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1512fcd89c09SVille Tervo 
1513fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1514fcd89c09SVille Tervo 
1515fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1516fcd89c09SVille Tervo 		conn);
1517fcd89c09SVille Tervo 
1518fcd89c09SVille Tervo 	if (status) {
1519fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1520fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1521fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1522fcd89c09SVille Tervo 			hci_conn_del(conn);
1523fcd89c09SVille Tervo 		}
1524fcd89c09SVille Tervo 	} else {
1525fcd89c09SVille Tervo 		if (!conn) {
1526fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
152729b7988aSAndre Guedes 			if (conn) {
152829b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1529fcd89c09SVille Tervo 				conn->out = 1;
153029b7988aSAndre Guedes 			} else {
1531fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1532fcd89c09SVille Tervo 			}
1533fcd89c09SVille Tervo 		}
153429b7988aSAndre Guedes 	}
1535fcd89c09SVille Tervo 
1536fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1537fcd89c09SVille Tervo }
1538fcd89c09SVille Tervo 
1539a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1540a7a595f6SVinicius Costa Gomes {
1541a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1542a7a595f6SVinicius Costa Gomes }
1543a7a595f6SVinicius Costa Gomes 
15441da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15451da177e4SLinus Torvalds {
15461da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
154730dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
154830dc78e1SJohan Hedberg 	struct inquiry_entry *e;
15491da177e4SLinus Torvalds 
15501da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
15511da177e4SLinus Torvalds 
155223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
15536bd57416SMarcel Holtmann 
1554a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
155589352e7dSAndre Guedes 
155689352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
155789352e7dSAndre Guedes 		return;
155889352e7dSAndre Guedes 
1559a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
156030dc78e1SJohan Hedberg 		return;
156130dc78e1SJohan Hedberg 
156256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
156330dc78e1SJohan Hedberg 
156430dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_INQUIRY)
156530dc78e1SJohan Hedberg 		goto unlock;
156630dc78e1SJohan Hedberg 
156730dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1568ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
156930dc78e1SJohan Hedberg 		goto unlock;
157030dc78e1SJohan Hedberg 	}
157130dc78e1SJohan Hedberg 
157230dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
157330dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
157430dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
157530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
157630dc78e1SJohan Hedberg 	} else {
157730dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
157830dc78e1SJohan Hedberg 	}
157930dc78e1SJohan Hedberg 
158030dc78e1SJohan Hedberg unlock:
158156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
15821da177e4SLinus Torvalds }
15831da177e4SLinus Torvalds 
15841da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
15851da177e4SLinus Torvalds {
158645bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1587a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
15881da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
15891da177e4SLinus Torvalds 
15901da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
15911da177e4SLinus Torvalds 
159245bb4bf0SMarcel Holtmann 	if (!num_rsp)
159345bb4bf0SMarcel Holtmann 		return;
159445bb4bf0SMarcel Holtmann 
15951da177e4SLinus Torvalds 	hci_dev_lock(hdev);
159645bb4bf0SMarcel Holtmann 
1597e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
15983175405bSJohan Hedberg 		bool name_known;
15993175405bSJohan Hedberg 
16001da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16011da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16021da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16031da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16041da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16051da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16061da177e4SLinus Torvalds 		data.rssi		= 0x00;
160741a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16083175405bSJohan Hedberg 
16093175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false);
161048264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
16117d262f86SAndre Guedes 					info->dev_class, 0, !name_known,
16127d262f86SAndre Guedes 					NULL, 0);
16131da177e4SLinus Torvalds 	}
161445bb4bf0SMarcel Holtmann 
16151da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16161da177e4SLinus Torvalds }
16171da177e4SLinus Torvalds 
1618a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16191da177e4SLinus Torvalds {
1620a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1621a9de9248SMarcel Holtmann 	struct hci_conn *conn;
16221da177e4SLinus Torvalds 
1623a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
162445bb4bf0SMarcel Holtmann 
16251da177e4SLinus Torvalds 	hci_dev_lock(hdev);
162645bb4bf0SMarcel Holtmann 
1627a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16289499237aSMarcel Holtmann 	if (!conn) {
16299499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16309499237aSMarcel Holtmann 			goto unlock;
16319499237aSMarcel Holtmann 
16329499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1633a9de9248SMarcel Holtmann 		if (!conn)
1634a9de9248SMarcel Holtmann 			goto unlock;
163545bb4bf0SMarcel Holtmann 
16369499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16379499237aSMarcel Holtmann 	}
16389499237aSMarcel Holtmann 
1639a9de9248SMarcel Holtmann 	if (!ev->status) {
1640a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1641769be974SMarcel Holtmann 
1642769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1643769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1644769be974SMarcel Holtmann 			hci_conn_hold(conn);
1645052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1646afc747a6SJohan Hedberg 			mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
164748264f06SJohan Hedberg 							conn->dst_type);
1648769be974SMarcel Holtmann 		} else
1649a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1650a9de9248SMarcel Holtmann 
16519eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
16527d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
16537d0db0a3SMarcel Holtmann 
1654a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1655a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1656a9de9248SMarcel Holtmann 
1657a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1658a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1659a9de9248SMarcel Holtmann 
1660a9de9248SMarcel Holtmann 		/* Get remote features */
1661a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1662a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1663a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1664769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1665769be974SMarcel Holtmann 							sizeof(cp), &cp);
166645bb4bf0SMarcel Holtmann 		}
1667a9de9248SMarcel Holtmann 
1668a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1669d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1670a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1671a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1672a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1673a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1674a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1675a9de9248SMarcel Holtmann 		}
167617d5c04cSJohan Hedberg 	} else {
1677a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
167817d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1679744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
168048264f06SJohan Hedberg 						conn->dst_type, ev->status);
168117d5c04cSJohan Hedberg 	}
168245bb4bf0SMarcel Holtmann 
1683e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1684e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
168545bb4bf0SMarcel Holtmann 
1686769be974SMarcel Holtmann 	if (ev->status) {
1687a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1688a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1689c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1690c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1691a9de9248SMarcel Holtmann 
1692a9de9248SMarcel Holtmann unlock:
16931da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1694a9de9248SMarcel Holtmann 
1695a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
16961da177e4SLinus Torvalds }
16971da177e4SLinus Torvalds 
16981da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
16991da177e4SLinus Torvalds {
1700a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17011da177e4SLinus Torvalds 	int mask = hdev->link_mode;
17021da177e4SLinus Torvalds 
1703a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
17041da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
17051da177e4SLinus Torvalds 
17061da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
17071da177e4SLinus Torvalds 
1708138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1709138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
17101da177e4SLinus Torvalds 		/* Connection accepted */
1711c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17121da177e4SLinus Torvalds 		struct hci_conn *conn;
17131da177e4SLinus Torvalds 
17141da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1715b6a0dc82SMarcel Holtmann 
1716cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1717cc11b9c1SAndrei Emeltchenko 		if (ie)
1718c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1719c7bdd502SMarcel Holtmann 
17201da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17211da177e4SLinus Torvalds 		if (!conn) {
1722cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1723cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1724893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17251da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17261da177e4SLinus Torvalds 				return;
17271da177e4SLinus Torvalds 			}
17281da177e4SLinus Torvalds 		}
1729b6a0dc82SMarcel Holtmann 
17301da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
17311da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1732b6a0dc82SMarcel Holtmann 
17331da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17341da177e4SLinus Torvalds 
1735b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1736b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1737b6a0dc82SMarcel Holtmann 
17381da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17391da177e4SLinus Torvalds 
17401da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17411da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17421da177e4SLinus Torvalds 			else
17431da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17441da177e4SLinus Torvalds 
1745b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1746b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1747b6a0dc82SMarcel Holtmann 		} else {
1748b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1749b6a0dc82SMarcel Holtmann 
1750b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1751a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1752b6a0dc82SMarcel Holtmann 
1753b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1754b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1755b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1756b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1757b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1758b6a0dc82SMarcel Holtmann 
1759b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1760b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1761b6a0dc82SMarcel Holtmann 		}
17621da177e4SLinus Torvalds 	} else {
17631da177e4SLinus Torvalds 		/* Connection rejected */
17641da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
17651da177e4SLinus Torvalds 
17661da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
17679f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1768a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
17691da177e4SLinus Torvalds 	}
17701da177e4SLinus Torvalds }
17711da177e4SLinus Torvalds 
17721da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17731da177e4SLinus Torvalds {
1774a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
177504837f64SMarcel Holtmann 	struct hci_conn *conn;
17761da177e4SLinus Torvalds 
17771da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds 	hci_dev_lock(hdev);
17801da177e4SLinus Torvalds 
178104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1782f7520543SJohan Hedberg 	if (!conn)
1783f7520543SJohan Hedberg 		goto unlock;
1784f7520543SJohan Hedberg 
178537d9ef76SJohan Hedberg 	if (ev->status == 0)
17861da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
17877d0db0a3SMarcel Holtmann 
178837d9ef76SJohan Hedberg 	if (conn->type == ACL_LINK || conn->type == LE_LINK) {
178937d9ef76SJohan Hedberg 		if (ev->status != 0)
179037d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
179137d9ef76SJohan Hedberg 		else
1792afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
179348264f06SJohan Hedberg 							conn->dst_type);
179437d9ef76SJohan Hedberg 	}
1795f7520543SJohan Hedberg 
179637d9ef76SJohan Hedberg 	if (ev->status == 0) {
17972950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
17981da177e4SLinus Torvalds 		hci_conn_del(conn);
179937d9ef76SJohan Hedberg 	}
18001da177e4SLinus Torvalds 
1801f7520543SJohan Hedberg unlock:
18021da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18031da177e4SLinus Torvalds }
18041da177e4SLinus Torvalds 
1805a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1806a9de9248SMarcel Holtmann {
1807a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1808a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1809a9de9248SMarcel Holtmann 
1810a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1811a9de9248SMarcel Holtmann 
1812a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1813a9de9248SMarcel Holtmann 
1814a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1815d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1816d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1817d7556e20SWaldemar Rymarkiewicz 
1818765c2a96SJohan Hedberg 	if (!ev->status) {
181919f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1820d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1821d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
182219f8def0SWaldemar Rymarkiewicz 		} else {
1823a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1824765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
182519f8def0SWaldemar Rymarkiewicz 		}
18262a611692SJohan Hedberg 	} else {
1827744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
18282a611692SJohan Hedberg 	}
1829a9de9248SMarcel Holtmann 
1830a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
183119f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1832a9de9248SMarcel Holtmann 
1833f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1834d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1835f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1836f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1837f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1838d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1839d7556e20SWaldemar Rymarkiewicz 									&cp);
1840f8558555SMarcel Holtmann 		} else {
1841f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1842f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1843f8558555SMarcel Holtmann 			hci_conn_put(conn);
1844f8558555SMarcel Holtmann 		}
1845052b30b0SMarcel Holtmann 	} else {
1846a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1847a9de9248SMarcel Holtmann 
1848052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1849052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1850052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1851052b30b0SMarcel Holtmann 	}
1852052b30b0SMarcel Holtmann 
1853a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1854a9de9248SMarcel Holtmann 		if (!ev->status) {
1855a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1856f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1857f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1858d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1859d7556e20SWaldemar Rymarkiewicz 									&cp);
1860a9de9248SMarcel Holtmann 		} else {
1861a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1862a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1863a9de9248SMarcel Holtmann 		}
1864a9de9248SMarcel Holtmann 	}
1865a9de9248SMarcel Holtmann 
1866d7556e20SWaldemar Rymarkiewicz unlock:
1867a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1868a9de9248SMarcel Holtmann }
1869a9de9248SMarcel Holtmann 
1870a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1871a9de9248SMarcel Holtmann {
1872127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1873127178d2SJohan Hedberg 	struct hci_conn *conn;
1874127178d2SJohan Hedberg 
1875a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1876a9de9248SMarcel Holtmann 
1877a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1878127178d2SJohan Hedberg 
1879127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1880127178d2SJohan Hedberg 
1881a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
188230dc78e1SJohan Hedberg 		if (ev->status == 0)
1883744cf19eSJohan Hedberg 			mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
1884a88a9652SJohan Hedberg 
188530dc78e1SJohan Hedberg 		hci_resolve_next_name(hdev, &ev->bdaddr);
188630dc78e1SJohan Hedberg 	}
188730dc78e1SJohan Hedberg 
1888127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
188979c6c70cSJohan Hedberg 	if (!conn)
189079c6c70cSJohan Hedberg 		goto unlock;
189179c6c70cSJohan Hedberg 
189279c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
189379c6c70cSJohan Hedberg 		goto unlock;
189479c6c70cSJohan Hedberg 
189579c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1896127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1897127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1898127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1899127178d2SJohan Hedberg 	}
1900127178d2SJohan Hedberg 
190179c6c70cSJohan Hedberg unlock:
1902127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1903a9de9248SMarcel Holtmann }
1904a9de9248SMarcel Holtmann 
1905a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1906a9de9248SMarcel Holtmann {
1907a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1908a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1909a9de9248SMarcel Holtmann 
1910a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1911a9de9248SMarcel Holtmann 
1912a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1913a9de9248SMarcel Holtmann 
1914a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1915a9de9248SMarcel Holtmann 	if (conn) {
1916a9de9248SMarcel Holtmann 		if (!ev->status) {
1917ae293196SMarcel Holtmann 			if (ev->encrypt) {
1918ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1919ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1920a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1921da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1922ae293196SMarcel Holtmann 			} else
1923a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1924a9de9248SMarcel Holtmann 		}
1925a9de9248SMarcel Holtmann 
1926a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1927a9de9248SMarcel Holtmann 
1928f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1929f8558555SMarcel Holtmann 			if (!ev->status)
1930f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1931f8558555SMarcel Holtmann 
1932f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1933f8558555SMarcel Holtmann 			hci_conn_put(conn);
1934f8558555SMarcel Holtmann 		} else
1935a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1936a9de9248SMarcel Holtmann 	}
1937a9de9248SMarcel Holtmann 
1938a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1939a9de9248SMarcel Holtmann }
1940a9de9248SMarcel Holtmann 
1941a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1942a9de9248SMarcel Holtmann {
1943a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1944a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1945a9de9248SMarcel Holtmann 
1946a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1947a9de9248SMarcel Holtmann 
1948a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1949a9de9248SMarcel Holtmann 
1950a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1951a9de9248SMarcel Holtmann 	if (conn) {
1952a9de9248SMarcel Holtmann 		if (!ev->status)
1953a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1954a9de9248SMarcel Holtmann 
1955a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1956a9de9248SMarcel Holtmann 
1957a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1958a9de9248SMarcel Holtmann 	}
1959a9de9248SMarcel Holtmann 
1960a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1961a9de9248SMarcel Holtmann }
1962a9de9248SMarcel Holtmann 
1963a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1964a9de9248SMarcel Holtmann {
1965a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1966a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1967a9de9248SMarcel Holtmann 
1968a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1969a9de9248SMarcel Holtmann 
1970a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1971a9de9248SMarcel Holtmann 
1972a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1973ccd556feSJohan Hedberg 	if (!conn)
1974ccd556feSJohan Hedberg 		goto unlock;
1975ccd556feSJohan Hedberg 
1976769be974SMarcel Holtmann 	if (!ev->status)
1977a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1978a9de9248SMarcel Holtmann 
1979ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1980ccd556feSJohan Hedberg 		goto unlock;
1981ccd556feSJohan Hedberg 
1982ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1983769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1984769be974SMarcel Holtmann 		cp.handle = ev->handle;
1985769be974SMarcel Holtmann 		cp.page = 0x01;
1986ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1987769be974SMarcel Holtmann 							sizeof(cp), &cp);
1988392599b9SJohan Hedberg 		goto unlock;
1989392599b9SJohan Hedberg 	}
1990392599b9SJohan Hedberg 
1991127178d2SJohan Hedberg 	if (!ev->status) {
1992127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1993127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1994127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1995127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1996127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1997127178d2SJohan Hedberg 	}
1998392599b9SJohan Hedberg 
1999127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2000769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2001769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2002769be974SMarcel Holtmann 		hci_conn_put(conn);
2003769be974SMarcel Holtmann 	}
2004769be974SMarcel Holtmann 
2005ccd556feSJohan Hedberg unlock:
2006a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2007a9de9248SMarcel Holtmann }
2008a9de9248SMarcel Holtmann 
2009a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2010a9de9248SMarcel Holtmann {
2011a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2012a9de9248SMarcel Holtmann }
2013a9de9248SMarcel Holtmann 
2014a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2015a9de9248SMarcel Holtmann {
2016a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2017a9de9248SMarcel Holtmann }
2018a9de9248SMarcel Holtmann 
2019a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2020a9de9248SMarcel Holtmann {
2021a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2022a9de9248SMarcel Holtmann 	__u16 opcode;
2023a9de9248SMarcel Holtmann 
2024a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2025a9de9248SMarcel Holtmann 
2026a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2027a9de9248SMarcel Holtmann 
2028a9de9248SMarcel Holtmann 	switch (opcode) {
2029a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2030a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2031a9de9248SMarcel Holtmann 		break;
2032a9de9248SMarcel Holtmann 
2033a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2034a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2035a9de9248SMarcel Holtmann 		break;
2036a9de9248SMarcel Holtmann 
2037a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2038a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2039a9de9248SMarcel Holtmann 		break;
2040a9de9248SMarcel Holtmann 
2041a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2042a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2043a9de9248SMarcel Holtmann 		break;
2044a9de9248SMarcel Holtmann 
2045e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2046e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2047e4e8e37cSMarcel Holtmann 		break;
2048e4e8e37cSMarcel Holtmann 
2049a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2050a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2051a9de9248SMarcel Holtmann 		break;
2052a9de9248SMarcel Holtmann 
2053e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2054e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2055e4e8e37cSMarcel Holtmann 		break;
2056e4e8e37cSMarcel Holtmann 
2057e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2058e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2059e4e8e37cSMarcel Holtmann 		break;
2060e4e8e37cSMarcel Holtmann 
2061a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2062a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2063a9de9248SMarcel Holtmann 		break;
2064a9de9248SMarcel Holtmann 
2065a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2066a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2067a9de9248SMarcel Holtmann 		break;
2068a9de9248SMarcel Holtmann 
2069a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2070a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2071a9de9248SMarcel Holtmann 		break;
2072a9de9248SMarcel Holtmann 
2073a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2074a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2075a9de9248SMarcel Holtmann 		break;
2076a9de9248SMarcel Holtmann 
2077a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2078a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2079a9de9248SMarcel Holtmann 		break;
2080a9de9248SMarcel Holtmann 
2081a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2082a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2083a9de9248SMarcel Holtmann 		break;
2084a9de9248SMarcel Holtmann 
2085a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2086a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2087a9de9248SMarcel Holtmann 		break;
2088a9de9248SMarcel Holtmann 
2089a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2090a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2091a9de9248SMarcel Holtmann 		break;
2092a9de9248SMarcel Holtmann 
2093a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2094a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2095a9de9248SMarcel Holtmann 		break;
2096a9de9248SMarcel Holtmann 
2097a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2098a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2099a9de9248SMarcel Holtmann 		break;
2100a9de9248SMarcel Holtmann 
2101a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2102a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2103a9de9248SMarcel Holtmann 		break;
2104a9de9248SMarcel Holtmann 
2105333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
2106333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
2107333140b5SMarcel Holtmann 		break;
2108333140b5SMarcel Holtmann 
2109333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2110333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2111333140b5SMarcel Holtmann 		break;
2112333140b5SMarcel Holtmann 
2113a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2114a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2115a9de9248SMarcel Holtmann 		break;
2116a9de9248SMarcel Holtmann 
2117a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2118a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2119a9de9248SMarcel Holtmann 		break;
2120a9de9248SMarcel Holtmann 
2121a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2122a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2123a9de9248SMarcel Holtmann 		break;
2124a9de9248SMarcel Holtmann 
2125971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2126971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2127971e3a4bSAndre Guedes 		break;
2128971e3a4bSAndre Guedes 
2129a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2130a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2131a9de9248SMarcel Holtmann 		break;
2132a9de9248SMarcel Holtmann 
2133a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2134a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2135a9de9248SMarcel Holtmann 		break;
2136a9de9248SMarcel Holtmann 
2137350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2138350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2139350ee4cfSAndrei Emeltchenko 		break;
2140350ee4cfSAndrei Emeltchenko 
214123bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
214223bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
214323bb5763SJohan Hedberg 		break;
214423bb5763SJohan Hedberg 
21451e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
21461e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
21471e89cffbSAndrei Emeltchenko 		break;
21481e89cffbSAndrei Emeltchenko 
2149928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2150928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2151928abaa7SAndrei Emeltchenko 		break;
2152928abaa7SAndrei Emeltchenko 
2153b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2154b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2155b0916ea0SJohan Hedberg 		break;
2156b0916ea0SJohan Hedberg 
2157d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2158d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2159d5859e22SJohan Hedberg 		break;
2160d5859e22SJohan Hedberg 
2161d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2162d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2163d5859e22SJohan Hedberg 		break;
2164d5859e22SJohan Hedberg 
2165d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2166d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2167d5859e22SJohan Hedberg 		break;
2168d5859e22SJohan Hedberg 
2169d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2170d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2171d5859e22SJohan Hedberg 		break;
2172d5859e22SJohan Hedberg 
2173980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2174980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2175980e1a53SJohan Hedberg 		break;
2176980e1a53SJohan Hedberg 
2177980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2178980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2179980e1a53SJohan Hedberg 		break;
2180980e1a53SJohan Hedberg 
2181c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2182c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2183c35938b2SSzymon Janc 		break;
2184c35938b2SSzymon Janc 
21856ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
21866ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
21876ed58ec5SVille Tervo 		break;
21886ed58ec5SVille Tervo 
2189a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2190a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2191a5c29683SJohan Hedberg 		break;
2192a5c29683SJohan Hedberg 
2193a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2194a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2195a5c29683SJohan Hedberg 		break;
2196a5c29683SJohan Hedberg 
21971143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
21981143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
21991143d458SBrian Gix 		break;
22001143d458SBrian Gix 
22011143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
22021143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
220307f7fa5dSAndre Guedes 
220407f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
220507f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
22061143d458SBrian Gix 		break;
22071143d458SBrian Gix 
2208eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2209eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2210eb9d91f5SAndre Guedes 		break;
2211eb9d91f5SAndre Guedes 
2212a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2213a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2214a7a595f6SVinicius Costa Gomes 		break;
2215a7a595f6SVinicius Costa Gomes 
2216a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2217a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2218a7a595f6SVinicius Costa Gomes 		break;
2219a7a595f6SVinicius Costa Gomes 
2220f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2221f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2222f9b49306SAndre Guedes 		break;
2223f9b49306SAndre Guedes 
2224a9de9248SMarcel Holtmann 	default:
2225a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2226a9de9248SMarcel Holtmann 		break;
2227a9de9248SMarcel Holtmann 	}
2228a9de9248SMarcel Holtmann 
22296bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
22306bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
22316bd32326SVille Tervo 
2232a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2233a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2234a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2235c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2236a9de9248SMarcel Holtmann 	}
2237a9de9248SMarcel Holtmann }
2238a9de9248SMarcel Holtmann 
2239a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2240a9de9248SMarcel Holtmann {
2241a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2242a9de9248SMarcel Holtmann 	__u16 opcode;
2243a9de9248SMarcel Holtmann 
2244a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2245a9de9248SMarcel Holtmann 
2246a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2247a9de9248SMarcel Holtmann 
2248a9de9248SMarcel Holtmann 	switch (opcode) {
2249a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2250a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2251a9de9248SMarcel Holtmann 		break;
2252a9de9248SMarcel Holtmann 
2253a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2254a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2255a9de9248SMarcel Holtmann 		break;
2256a9de9248SMarcel Holtmann 
2257a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2258a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2259a9de9248SMarcel Holtmann 		break;
2260a9de9248SMarcel Holtmann 
2261f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2262f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2263f8558555SMarcel Holtmann 		break;
2264f8558555SMarcel Holtmann 
2265f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2266f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2267f8558555SMarcel Holtmann 		break;
2268f8558555SMarcel Holtmann 
2269a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2270a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2271a9de9248SMarcel Holtmann 		break;
2272a9de9248SMarcel Holtmann 
2273769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2274769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2275769be974SMarcel Holtmann 		break;
2276769be974SMarcel Holtmann 
2277769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2278769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2279769be974SMarcel Holtmann 		break;
2280769be974SMarcel Holtmann 
2281a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2282a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2283a9de9248SMarcel Holtmann 		break;
2284a9de9248SMarcel Holtmann 
2285a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2286a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2287a9de9248SMarcel Holtmann 		break;
2288a9de9248SMarcel Holtmann 
2289a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2290a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2291a9de9248SMarcel Holtmann 		break;
2292a9de9248SMarcel Holtmann 
22938962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
22948962ee74SJohan Hedberg 		if (ev->status != 0)
229537d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
22968962ee74SJohan Hedberg 		break;
22978962ee74SJohan Hedberg 
2298fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2299fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2300fcd89c09SVille Tervo 		break;
2301fcd89c09SVille Tervo 
2302a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2303a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2304a7a595f6SVinicius Costa Gomes 		break;
2305a7a595f6SVinicius Costa Gomes 
2306a9de9248SMarcel Holtmann 	default:
2307a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2308a9de9248SMarcel Holtmann 		break;
2309a9de9248SMarcel Holtmann 	}
2310a9de9248SMarcel Holtmann 
23116bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23126bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23136bd32326SVille Tervo 
231410572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2315a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2316a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2317c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2318a9de9248SMarcel Holtmann 	}
2319a9de9248SMarcel Holtmann }
2320a9de9248SMarcel Holtmann 
2321a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2322a9de9248SMarcel Holtmann {
2323a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2324a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2325a9de9248SMarcel Holtmann 
2326a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2327a9de9248SMarcel Holtmann 
2328a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2329a9de9248SMarcel Holtmann 
2330a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2331a9de9248SMarcel Holtmann 	if (conn) {
2332a9de9248SMarcel Holtmann 		if (!ev->status) {
2333a9de9248SMarcel Holtmann 			if (ev->role)
2334a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2335a9de9248SMarcel Holtmann 			else
2336a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2337a9de9248SMarcel Holtmann 		}
2338a9de9248SMarcel Holtmann 
2339a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2340a9de9248SMarcel Holtmann 
2341a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2342a9de9248SMarcel Holtmann 	}
2343a9de9248SMarcel Holtmann 
2344a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2345a9de9248SMarcel Holtmann }
2346a9de9248SMarcel Holtmann 
23471da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
23481da177e4SLinus Torvalds {
2349a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
23501da177e4SLinus Torvalds 	int i;
23511da177e4SLinus Torvalds 
235232ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
235332ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
235432ac5b9bSAndrei Emeltchenko 		return;
235532ac5b9bSAndrei Emeltchenko 	}
235632ac5b9bSAndrei Emeltchenko 
2357c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2358c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
23591da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
23601da177e4SLinus Torvalds 		return;
23611da177e4SLinus Torvalds 	}
23621da177e4SLinus Torvalds 
2363c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2364c5993de8SAndrei Emeltchenko 
2365613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2366613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
23671da177e4SLinus Torvalds 		struct hci_conn *conn;
23681da177e4SLinus Torvalds 		__u16  handle, count;
23691da177e4SLinus Torvalds 
2370613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2371613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
23721da177e4SLinus Torvalds 
23731da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2374f4280918SAndrei Emeltchenko 		if (!conn)
2375f4280918SAndrei Emeltchenko 			continue;
2376f4280918SAndrei Emeltchenko 
23771da177e4SLinus Torvalds 		conn->sent -= count;
23781da177e4SLinus Torvalds 
2379f4280918SAndrei Emeltchenko 		switch (conn->type) {
2380f4280918SAndrei Emeltchenko 		case ACL_LINK:
238170f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
238270f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
23831da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2384f4280918SAndrei Emeltchenko 			break;
2385f4280918SAndrei Emeltchenko 
2386f4280918SAndrei Emeltchenko 		case LE_LINK:
23876ed58ec5SVille Tervo 			if (hdev->le_pkts) {
23886ed58ec5SVille Tervo 				hdev->le_cnt += count;
23896ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
23906ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
23916ed58ec5SVille Tervo 			} else {
23926ed58ec5SVille Tervo 				hdev->acl_cnt += count;
23936ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
23946ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
23956ed58ec5SVille Tervo 			}
2396f4280918SAndrei Emeltchenko 			break;
2397f4280918SAndrei Emeltchenko 
2398f4280918SAndrei Emeltchenko 		case SCO_LINK:
239970f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
240070f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
24015b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2402f4280918SAndrei Emeltchenko 			break;
2403f4280918SAndrei Emeltchenko 
2404f4280918SAndrei Emeltchenko 		default:
2405f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2406f4280918SAndrei Emeltchenko 			break;
24071da177e4SLinus Torvalds 		}
24081da177e4SLinus Torvalds 	}
2409a9de9248SMarcel Holtmann 
24103eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
24111da177e4SLinus Torvalds }
24121da177e4SLinus Torvalds 
241325e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
241425e89e99SAndrei Emeltchenko 							struct sk_buff *skb)
241525e89e99SAndrei Emeltchenko {
241625e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
241725e89e99SAndrei Emeltchenko 	int i;
241825e89e99SAndrei Emeltchenko 
241925e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
242025e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
242125e89e99SAndrei Emeltchenko 		return;
242225e89e99SAndrei Emeltchenko 	}
242325e89e99SAndrei Emeltchenko 
242425e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
242525e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
242625e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
242725e89e99SAndrei Emeltchenko 		return;
242825e89e99SAndrei Emeltchenko 	}
242925e89e99SAndrei Emeltchenko 
243025e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
243125e89e99SAndrei Emeltchenko 								ev->num_hndl);
243225e89e99SAndrei Emeltchenko 
243325e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
243425e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
243525e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
243625e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
243725e89e99SAndrei Emeltchenko 
243825e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
243925e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
244025e89e99SAndrei Emeltchenko 
244125e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
244225e89e99SAndrei Emeltchenko 		if (!conn)
244325e89e99SAndrei Emeltchenko 			continue;
244425e89e99SAndrei Emeltchenko 
244525e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
244625e89e99SAndrei Emeltchenko 
244725e89e99SAndrei Emeltchenko 		switch (conn->type) {
244825e89e99SAndrei Emeltchenko 		case ACL_LINK:
244925e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
245025e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
245125e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
245225e89e99SAndrei Emeltchenko 			break;
245325e89e99SAndrei Emeltchenko 
245425e89e99SAndrei Emeltchenko 		default:
245525e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
245625e89e99SAndrei Emeltchenko 			break;
245725e89e99SAndrei Emeltchenko 		}
245825e89e99SAndrei Emeltchenko 	}
245925e89e99SAndrei Emeltchenko 
246025e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
246125e89e99SAndrei Emeltchenko }
246225e89e99SAndrei Emeltchenko 
246304837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
24641da177e4SLinus Torvalds {
2465a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
246604837f64SMarcel Holtmann 	struct hci_conn *conn;
24671da177e4SLinus Torvalds 
24681da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
24691da177e4SLinus Torvalds 
24701da177e4SLinus Torvalds 	hci_dev_lock(hdev);
24711da177e4SLinus Torvalds 
247204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
247304837f64SMarcel Holtmann 	if (conn) {
247404837f64SMarcel Holtmann 		conn->mode = ev->mode;
247504837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
247604837f64SMarcel Holtmann 
247704837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
247804837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
247904837f64SMarcel Holtmann 				conn->power_save = 1;
248004837f64SMarcel Holtmann 			else
248104837f64SMarcel Holtmann 				conn->power_save = 0;
248204837f64SMarcel Holtmann 		}
2483e73439d8SMarcel Holtmann 
2484e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2485e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
248604837f64SMarcel Holtmann 	}
248704837f64SMarcel Holtmann 
248804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
248904837f64SMarcel Holtmann }
249004837f64SMarcel Holtmann 
24911da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
24921da177e4SLinus Torvalds {
2493052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2494052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2495052b30b0SMarcel Holtmann 
2496a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2497052b30b0SMarcel Holtmann 
2498052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2499052b30b0SMarcel Holtmann 
2500052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2501b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2502b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2503b6f98044SWaldemar Rymarkiewicz 
2504b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2505052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2506052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2507052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2508052b30b0SMarcel Holtmann 	}
2509052b30b0SMarcel Holtmann 
2510a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
251103b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
251203b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2513a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2514a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2515a770bb5aSWaldemar Rymarkiewicz 
2516a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2517a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2518a770bb5aSWaldemar Rymarkiewicz 		else
2519a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2520a770bb5aSWaldemar Rymarkiewicz 
2521744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2522a770bb5aSWaldemar Rymarkiewicz 	}
2523980e1a53SJohan Hedberg 
2524b6f98044SWaldemar Rymarkiewicz unlock:
2525052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
25261da177e4SLinus Torvalds }
25271da177e4SLinus Torvalds 
25281da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25291da177e4SLinus Torvalds {
253055ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
253155ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
253255ed8ca1SJohan Hedberg 	struct hci_conn *conn;
253355ed8ca1SJohan Hedberg 	struct link_key *key;
253455ed8ca1SJohan Hedberg 
2535a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
253655ed8ca1SJohan Hedberg 
2537a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
253855ed8ca1SJohan Hedberg 		return;
253955ed8ca1SJohan Hedberg 
254055ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
254155ed8ca1SJohan Hedberg 
254255ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
254355ed8ca1SJohan Hedberg 	if (!key) {
254455ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
254555ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
254655ed8ca1SJohan Hedberg 		goto not_found;
254755ed8ca1SJohan Hedberg 	}
254855ed8ca1SJohan Hedberg 
254955ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
255055ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
255155ed8ca1SJohan Hedberg 
2552a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2553b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
255455ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
255555ed8ca1SJohan Hedberg 		goto not_found;
255655ed8ca1SJohan Hedberg 	}
255755ed8ca1SJohan Hedberg 
255855ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
255960b83f57SWaldemar Rymarkiewicz 	if (conn) {
256060b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
256160b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
256260b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
256355ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
256455ed8ca1SJohan Hedberg 			goto not_found;
256555ed8ca1SJohan Hedberg 		}
256655ed8ca1SJohan Hedberg 
256760b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
256860b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
256960b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
257060b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
257160b83f57SWaldemar Rymarkiewicz 			goto not_found;
257260b83f57SWaldemar Rymarkiewicz 		}
257360b83f57SWaldemar Rymarkiewicz 
257460b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
257560b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
257660b83f57SWaldemar Rymarkiewicz 	}
257760b83f57SWaldemar Rymarkiewicz 
257855ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
257955ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
258055ed8ca1SJohan Hedberg 
258155ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
258255ed8ca1SJohan Hedberg 
258355ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
258455ed8ca1SJohan Hedberg 
258555ed8ca1SJohan Hedberg 	return;
258655ed8ca1SJohan Hedberg 
258755ed8ca1SJohan Hedberg not_found:
258855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
258955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
25901da177e4SLinus Torvalds }
25911da177e4SLinus Torvalds 
25921da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
25931da177e4SLinus Torvalds {
2594052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2595052b30b0SMarcel Holtmann 	struct hci_conn *conn;
259655ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2597052b30b0SMarcel Holtmann 
2598a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2599052b30b0SMarcel Holtmann 
2600052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2601052b30b0SMarcel Holtmann 
2602052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2603052b30b0SMarcel Holtmann 	if (conn) {
2604052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2605052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2606980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
260713d39315SWaldemar Rymarkiewicz 
260813d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
260913d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
261013d39315SWaldemar Rymarkiewicz 
2611052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2612052b30b0SMarcel Holtmann 	}
2613052b30b0SMarcel Holtmann 
2614a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2615d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
261655ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
261755ed8ca1SJohan Hedberg 
2618052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26191da177e4SLinus Torvalds }
26201da177e4SLinus Torvalds 
262104837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
262204837f64SMarcel Holtmann {
2623a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
262404837f64SMarcel Holtmann 	struct hci_conn *conn;
262504837f64SMarcel Holtmann 
262604837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
262704837f64SMarcel Holtmann 
262804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
262904837f64SMarcel Holtmann 
263004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
26311da177e4SLinus Torvalds 	if (conn && !ev->status) {
26321da177e4SLinus Torvalds 		struct inquiry_entry *ie;
26331da177e4SLinus Torvalds 
2634cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2635cc11b9c1SAndrei Emeltchenko 		if (ie) {
26361da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
26371da177e4SLinus Torvalds 			ie->timestamp = jiffies;
26381da177e4SLinus Torvalds 		}
26391da177e4SLinus Torvalds 	}
26401da177e4SLinus Torvalds 
26411da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
26421da177e4SLinus Torvalds }
26431da177e4SLinus Torvalds 
2644a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2645a8746417SMarcel Holtmann {
2646a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2647a8746417SMarcel Holtmann 	struct hci_conn *conn;
2648a8746417SMarcel Holtmann 
2649a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2650a8746417SMarcel Holtmann 
2651a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2652a8746417SMarcel Holtmann 
2653a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2654a8746417SMarcel Holtmann 	if (conn && !ev->status)
2655a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2656a8746417SMarcel Holtmann 
2657a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2658a8746417SMarcel Holtmann }
2659a8746417SMarcel Holtmann 
266085a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
266185a1e930SMarcel Holtmann {
2662a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
266385a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
266485a1e930SMarcel Holtmann 
266585a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
266685a1e930SMarcel Holtmann 
266785a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
266885a1e930SMarcel Holtmann 
2669cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2670cc11b9c1SAndrei Emeltchenko 	if (ie) {
267185a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
267285a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
267385a1e930SMarcel Holtmann 	}
267485a1e930SMarcel Holtmann 
267585a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
267685a1e930SMarcel Holtmann }
267785a1e930SMarcel Holtmann 
2678a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2679a9de9248SMarcel Holtmann {
2680a9de9248SMarcel Holtmann 	struct inquiry_data data;
2681a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
26823175405bSJohan Hedberg 	bool name_known;
2683a9de9248SMarcel Holtmann 
2684a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2685a9de9248SMarcel Holtmann 
2686a9de9248SMarcel Holtmann 	if (!num_rsp)
2687a9de9248SMarcel Holtmann 		return;
2688a9de9248SMarcel Holtmann 
2689a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2690a9de9248SMarcel Holtmann 
2691a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2692138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2693138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2694a9de9248SMarcel Holtmann 
2695e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2696a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2697a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2698a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2699a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2700a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2701a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2702a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
270341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27043175405bSJohan Hedberg 
27053175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27063175405bSJohan Hedberg 								false);
270748264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2708e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27097d262f86SAndre Guedes 						!name_known, NULL, 0);
2710a9de9248SMarcel Holtmann 		}
2711a9de9248SMarcel Holtmann 	} else {
2712a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2713a9de9248SMarcel Holtmann 
2714e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2715a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2716a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2717a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2718a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2719a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2720a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2721a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
272241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27233175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27243175405bSJohan Hedberg 								false);
272548264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2726e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27277d262f86SAndre Guedes 						!name_known, NULL, 0);
2728a9de9248SMarcel Holtmann 		}
2729a9de9248SMarcel Holtmann 	}
2730a9de9248SMarcel Holtmann 
2731a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2732a9de9248SMarcel Holtmann }
2733a9de9248SMarcel Holtmann 
2734a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2735a9de9248SMarcel Holtmann {
273641a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
273741a96212SMarcel Holtmann 	struct hci_conn *conn;
273841a96212SMarcel Holtmann 
2739a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
274041a96212SMarcel Holtmann 
274141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
274241a96212SMarcel Holtmann 
274341a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2744ccd556feSJohan Hedberg 	if (!conn)
2745ccd556feSJohan Hedberg 		goto unlock;
2746ccd556feSJohan Hedberg 
2747769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
274841a96212SMarcel Holtmann 		struct inquiry_entry *ie;
274941a96212SMarcel Holtmann 
2750cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2751cc11b9c1SAndrei Emeltchenko 		if (ie)
275241a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
275341a96212SMarcel Holtmann 
275441a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
275541a96212SMarcel Holtmann 	}
275641a96212SMarcel Holtmann 
2757ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2758ccd556feSJohan Hedberg 		goto unlock;
2759ccd556feSJohan Hedberg 
2760127178d2SJohan Hedberg 	if (!ev->status) {
2761127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2762127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2763127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2764127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2765127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2766127178d2SJohan Hedberg 	}
2767392599b9SJohan Hedberg 
2768127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2769769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2770769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2771769be974SMarcel Holtmann 		hci_conn_put(conn);
2772769be974SMarcel Holtmann 	}
2773769be974SMarcel Holtmann 
2774ccd556feSJohan Hedberg unlock:
277541a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2776a9de9248SMarcel Holtmann }
2777a9de9248SMarcel Holtmann 
2778a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2779a9de9248SMarcel Holtmann {
2780b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2781b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2782b6a0dc82SMarcel Holtmann 
2783b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2784b6a0dc82SMarcel Holtmann 
2785b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2786b6a0dc82SMarcel Holtmann 
2787b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
27889dc0a3afSMarcel Holtmann 	if (!conn) {
27899dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
27909dc0a3afSMarcel Holtmann 			goto unlock;
27919dc0a3afSMarcel Holtmann 
27929dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2793b6a0dc82SMarcel Holtmann 		if (!conn)
2794b6a0dc82SMarcel Holtmann 			goto unlock;
2795b6a0dc82SMarcel Holtmann 
27969dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
27979dc0a3afSMarcel Holtmann 	}
27989dc0a3afSMarcel Holtmann 
2799732547f9SMarcel Holtmann 	switch (ev->status) {
2800732547f9SMarcel Holtmann 	case 0x00:
2801732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2802732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2803732547f9SMarcel Holtmann 
28049eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2805732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2806732547f9SMarcel Holtmann 		break;
2807732547f9SMarcel Holtmann 
2808705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2809732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
28101038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2811732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2812732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2813efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2814efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2815efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2816efc7688bSMarcel Holtmann 			goto unlock;
2817efc7688bSMarcel Holtmann 		}
2818732547f9SMarcel Holtmann 		/* fall through */
2819efc7688bSMarcel Holtmann 
2820732547f9SMarcel Holtmann 	default:
2821b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2822732547f9SMarcel Holtmann 		break;
2823732547f9SMarcel Holtmann 	}
2824b6a0dc82SMarcel Holtmann 
2825b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2826b6a0dc82SMarcel Holtmann 	if (ev->status)
2827b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2828b6a0dc82SMarcel Holtmann 
2829b6a0dc82SMarcel Holtmann unlock:
2830b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2831a9de9248SMarcel Holtmann }
2832a9de9248SMarcel Holtmann 
2833a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2834a9de9248SMarcel Holtmann {
2835a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2836a9de9248SMarcel Holtmann }
2837a9de9248SMarcel Holtmann 
283804837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
283904837f64SMarcel Holtmann {
2840a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
284104837f64SMarcel Holtmann 
284204837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
284304837f64SMarcel Holtmann }
284404837f64SMarcel Holtmann 
2845561aafbcSJohan Hedberg static inline bool eir_has_complete_name(u8 *data, size_t data_len)
2846561aafbcSJohan Hedberg {
2847561aafbcSJohan Hedberg 	u8 field_len;
2848561aafbcSJohan Hedberg 	size_t parsed;
2849561aafbcSJohan Hedberg 
2850561aafbcSJohan Hedberg 	for (parsed = 0; parsed < data_len - 1; parsed += field_len) {
2851561aafbcSJohan Hedberg 		field_len = data[0];
2852561aafbcSJohan Hedberg 
2853561aafbcSJohan Hedberg 		if (field_len == 0)
2854561aafbcSJohan Hedberg 			break;
2855561aafbcSJohan Hedberg 
2856561aafbcSJohan Hedberg 		parsed += field_len + 1;
2857561aafbcSJohan Hedberg 
2858561aafbcSJohan Hedberg 		if (parsed > data_len)
2859561aafbcSJohan Hedberg 			break;
2860561aafbcSJohan Hedberg 
2861561aafbcSJohan Hedberg 		if (data[1] == EIR_NAME_COMPLETE)
2862561aafbcSJohan Hedberg 			return true;
2863561aafbcSJohan Hedberg 
2864561aafbcSJohan Hedberg 		data += field_len + 1;
2865561aafbcSJohan Hedberg 	}
2866561aafbcSJohan Hedberg 
2867561aafbcSJohan Hedberg 	return false;
2868561aafbcSJohan Hedberg }
2869561aafbcSJohan Hedberg 
2870a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2871a9de9248SMarcel Holtmann {
2872a9de9248SMarcel Holtmann 	struct inquiry_data data;
2873a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2874a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2875a9de9248SMarcel Holtmann 
2876a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2877a9de9248SMarcel Holtmann 
2878a9de9248SMarcel Holtmann 	if (!num_rsp)
2879a9de9248SMarcel Holtmann 		return;
2880a9de9248SMarcel Holtmann 
2881a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2882a9de9248SMarcel Holtmann 
2883e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2884561aafbcSJohan Hedberg 		bool name_known;
2885561aafbcSJohan Hedberg 
2886a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2887a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2888a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2889a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2890a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2891a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2892a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
289341a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2894561aafbcSJohan Hedberg 
2895a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
2896561aafbcSJohan Hedberg 			name_known = eir_has_complete_name(info->data,
2897561aafbcSJohan Hedberg 							sizeof(info->data));
2898561aafbcSJohan Hedberg 		else
2899561aafbcSJohan Hedberg 			name_known = true;
2900561aafbcSJohan Hedberg 
29013175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known);
290248264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2903561aafbcSJohan Hedberg 						info->dev_class, info->rssi,
29047d262f86SAndre Guedes 						!name_known, info->data,
29057d262f86SAndre Guedes 						sizeof(info->data));
2906a9de9248SMarcel Holtmann 	}
2907a9de9248SMarcel Holtmann 
2908a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2909a9de9248SMarcel Holtmann }
2910a9de9248SMarcel Holtmann 
291117fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
291217fa4b9dSJohan Hedberg {
291317fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
291417fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
291517fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
291617fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
291717fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
291817fa4b9dSJohan Hedberg 			return 0x02;
291917fa4b9dSJohan Hedberg 		else
292017fa4b9dSJohan Hedberg 			return 0x03;
292117fa4b9dSJohan Hedberg 	}
292217fa4b9dSJohan Hedberg 
292317fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
292417fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
292558797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
292617fa4b9dSJohan Hedberg 
292717fa4b9dSJohan Hedberg 	return conn->auth_type;
292817fa4b9dSJohan Hedberg }
292917fa4b9dSJohan Hedberg 
29300493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29310493684eSMarcel Holtmann {
29320493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
29330493684eSMarcel Holtmann 	struct hci_conn *conn;
29340493684eSMarcel Holtmann 
29350493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
29360493684eSMarcel Holtmann 
29370493684eSMarcel Holtmann 	hci_dev_lock(hdev);
29380493684eSMarcel Holtmann 
29390493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
294003b555e1SJohan Hedberg 	if (!conn)
294103b555e1SJohan Hedberg 		goto unlock;
294203b555e1SJohan Hedberg 
29430493684eSMarcel Holtmann 	hci_conn_hold(conn);
29440493684eSMarcel Holtmann 
2945a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
294603b555e1SJohan Hedberg 		goto unlock;
294703b555e1SJohan Hedberg 
2948a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
294903b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
295017fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
295117fa4b9dSJohan Hedberg 
295217fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
295317fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
29547cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
29557cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
295617fa4b9dSJohan Hedberg 
2957ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2958ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2959ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2960ce85ee13SSzymon Janc 		else
2961ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2962ce85ee13SSzymon Janc 
296317fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
296417fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
296503b555e1SJohan Hedberg 	} else {
296603b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
296703b555e1SJohan Hedberg 
296803b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
29699f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
297003b555e1SJohan Hedberg 
297103b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
297203b555e1SJohan Hedberg 							sizeof(cp), &cp);
297303b555e1SJohan Hedberg 	}
297403b555e1SJohan Hedberg 
297503b555e1SJohan Hedberg unlock:
297603b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
297703b555e1SJohan Hedberg }
297803b555e1SJohan Hedberg 
297903b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
298003b555e1SJohan Hedberg {
298103b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
298203b555e1SJohan Hedberg 	struct hci_conn *conn;
298303b555e1SJohan Hedberg 
298403b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
298503b555e1SJohan Hedberg 
298603b555e1SJohan Hedberg 	hci_dev_lock(hdev);
298703b555e1SJohan Hedberg 
298803b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
298903b555e1SJohan Hedberg 	if (!conn)
299003b555e1SJohan Hedberg 		goto unlock;
299103b555e1SJohan Hedberg 
299203b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
299303b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
299403b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
299503b555e1SJohan Hedberg 
299603b555e1SJohan Hedberg unlock:
29970493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
29980493684eSMarcel Holtmann }
29990493684eSMarcel Holtmann 
3000a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3001a5c29683SJohan Hedberg 							struct sk_buff *skb)
3002a5c29683SJohan Hedberg {
3003a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
300455bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
30057a828908SJohan Hedberg 	struct hci_conn *conn;
3006a5c29683SJohan Hedberg 
3007a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3008a5c29683SJohan Hedberg 
3009a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3010a5c29683SJohan Hedberg 
3011a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
30127a828908SJohan Hedberg 		goto unlock;
30137a828908SJohan Hedberg 
30147a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
30157a828908SJohan Hedberg 	if (!conn)
30167a828908SJohan Hedberg 		goto unlock;
30177a828908SJohan Hedberg 
30187a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
30197a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
30207a828908SJohan Hedberg 
30217a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
30227a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
30237a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
30247a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
30257a828908SJohan Hedberg 	 * bit set. */
30267a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
30277a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
30287a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
30297a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
30307a828908SJohan Hedberg 		goto unlock;
30317a828908SJohan Hedberg 	}
30327a828908SJohan Hedberg 
30337a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
30347a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
30357a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
303655bc1a37SJohan Hedberg 
303755bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
303855bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
303955bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
304055bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
304155bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
304255bc1a37SJohan Hedberg 			confirm_hint = 1;
304355bc1a37SJohan Hedberg 			goto confirm;
304455bc1a37SJohan Hedberg 		}
304555bc1a37SJohan Hedberg 
30469f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
30479f61656aSJohan Hedberg 						hdev->auto_accept_delay);
30489f61656aSJohan Hedberg 
30499f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
30509f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
30519f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
30529f61656aSJohan Hedberg 			goto unlock;
30539f61656aSJohan Hedberg 		}
30549f61656aSJohan Hedberg 
30557a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
30567a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
30577a828908SJohan Hedberg 		goto unlock;
30587a828908SJohan Hedberg 	}
30597a828908SJohan Hedberg 
306055bc1a37SJohan Hedberg confirm:
3061744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
306255bc1a37SJohan Hedberg 								confirm_hint);
3063a5c29683SJohan Hedberg 
30647a828908SJohan Hedberg unlock:
3065a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3066a5c29683SJohan Hedberg }
3067a5c29683SJohan Hedberg 
30681143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
30691143d458SBrian Gix 							struct sk_buff *skb)
30701143d458SBrian Gix {
30711143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
30721143d458SBrian Gix 
30731143d458SBrian Gix 	BT_DBG("%s", hdev->name);
30741143d458SBrian Gix 
30751143d458SBrian Gix 	hci_dev_lock(hdev);
30761143d458SBrian Gix 
3077a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
30781143d458SBrian Gix 		mgmt_user_passkey_request(hdev, &ev->bdaddr);
30791143d458SBrian Gix 
30801143d458SBrian Gix 	hci_dev_unlock(hdev);
30811143d458SBrian Gix }
30821143d458SBrian Gix 
30830493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
30840493684eSMarcel Holtmann {
30850493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
30860493684eSMarcel Holtmann 	struct hci_conn *conn;
30870493684eSMarcel Holtmann 
30880493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30890493684eSMarcel Holtmann 
30900493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30910493684eSMarcel Holtmann 
30920493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
30932a611692SJohan Hedberg 	if (!conn)
30942a611692SJohan Hedberg 		goto unlock;
30952a611692SJohan Hedberg 
30962a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
30972a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
30982a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
30992a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
31002a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
31012a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
3102744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
31032a611692SJohan Hedberg 
31040493684eSMarcel Holtmann 	hci_conn_put(conn);
31050493684eSMarcel Holtmann 
31062a611692SJohan Hedberg unlock:
31070493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31080493684eSMarcel Holtmann }
31090493684eSMarcel Holtmann 
311041a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
311141a96212SMarcel Holtmann {
311241a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
311341a96212SMarcel Holtmann 	struct inquiry_entry *ie;
311441a96212SMarcel Holtmann 
311541a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
311641a96212SMarcel Holtmann 
311741a96212SMarcel Holtmann 	hci_dev_lock(hdev);
311841a96212SMarcel Holtmann 
3119cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3120cc11b9c1SAndrei Emeltchenko 	if (ie)
312141a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
312241a96212SMarcel Holtmann 
312341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
312441a96212SMarcel Holtmann }
312541a96212SMarcel Holtmann 
31262763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
31272763eda6SSzymon Janc 							struct sk_buff *skb)
31282763eda6SSzymon Janc {
31292763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
31302763eda6SSzymon Janc 	struct oob_data *data;
31312763eda6SSzymon Janc 
31322763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
31332763eda6SSzymon Janc 
31342763eda6SSzymon Janc 	hci_dev_lock(hdev);
31352763eda6SSzymon Janc 
3136a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3137e1ba1f15SSzymon Janc 		goto unlock;
3138e1ba1f15SSzymon Janc 
31392763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
31402763eda6SSzymon Janc 	if (data) {
31412763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
31422763eda6SSzymon Janc 
31432763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31442763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
31452763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
31462763eda6SSzymon Janc 
31472763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
31482763eda6SSzymon Janc 									&cp);
31492763eda6SSzymon Janc 	} else {
31502763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
31512763eda6SSzymon Janc 
31522763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31532763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
31542763eda6SSzymon Janc 									&cp);
31552763eda6SSzymon Janc 	}
31562763eda6SSzymon Janc 
3157e1ba1f15SSzymon Janc unlock:
31582763eda6SSzymon Janc 	hci_dev_unlock(hdev);
31592763eda6SSzymon Janc }
31602763eda6SSzymon Janc 
3161fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3162fcd89c09SVille Tervo {
3163fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3164fcd89c09SVille Tervo 	struct hci_conn *conn;
3165fcd89c09SVille Tervo 
3166fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3167fcd89c09SVille Tervo 
3168fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3169fcd89c09SVille Tervo 
3170fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3171b62f328bSVille Tervo 	if (!conn) {
3172b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3173b62f328bSVille Tervo 		if (!conn) {
3174b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3175b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3176b62f328bSVille Tervo 			return;
3177b62f328bSVille Tervo 		}
317829b7988aSAndre Guedes 
317929b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3180b62f328bSVille Tervo 	}
3181fcd89c09SVille Tervo 
3182fcd89c09SVille Tervo 	if (ev->status) {
318348264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
318448264f06SJohan Hedberg 						conn->dst_type, ev->status);
3185fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3186fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3187fcd89c09SVille Tervo 		hci_conn_del(conn);
3188fcd89c09SVille Tervo 		goto unlock;
3189fcd89c09SVille Tervo 	}
3190fcd89c09SVille Tervo 
3191afc747a6SJohan Hedberg 	mgmt_device_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
319283bc71b4SVinicius Costa Gomes 
31937b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3194fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3195fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3196fcd89c09SVille Tervo 
3197fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3198fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3199fcd89c09SVille Tervo 
3200fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3201fcd89c09SVille Tervo 
3202fcd89c09SVille Tervo unlock:
3203fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3204fcd89c09SVille Tervo }
3205fcd89c09SVille Tervo 
32069aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
32079aa04c91SAndre Guedes 						struct sk_buff *skb)
32089aa04c91SAndre Guedes {
3209e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3210e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
32113c9e9195SAndre Guedes 	s8 rssi;
32129aa04c91SAndre Guedes 
32139aa04c91SAndre Guedes 	hci_dev_lock(hdev);
32149aa04c91SAndre Guedes 
3215e95beb41SAndre Guedes 	while (num_reports--) {
3216e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3217e95beb41SAndre Guedes 
32189aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
32199aa04c91SAndre Guedes 
32203c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
32213c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
32223c9e9195SAndre Guedes 					NULL, rssi, 0, ev->data, ev->length);
32233c9e9195SAndre Guedes 
3224e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
32259aa04c91SAndre Guedes 	}
32269aa04c91SAndre Guedes 
32279aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
32289aa04c91SAndre Guedes }
32299aa04c91SAndre Guedes 
3230a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3231a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3232a7a595f6SVinicius Costa Gomes {
3233a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3234a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3235bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3236a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3237bea710feSVinicius Costa Gomes 	struct link_key *ltk;
3238a7a595f6SVinicius Costa Gomes 
3239a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3240a7a595f6SVinicius Costa Gomes 
3241a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3242a7a595f6SVinicius Costa Gomes 
3243a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3244bea710feSVinicius Costa Gomes 	if (conn == NULL)
3245bea710feSVinicius Costa Gomes 		goto not_found;
3246a7a595f6SVinicius Costa Gomes 
3247bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3248bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3249bea710feSVinicius Costa Gomes 		goto not_found;
3250bea710feSVinicius Costa Gomes 
3251bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3252a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3253726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
3254a7a595f6SVinicius Costa Gomes 
3255a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3256a7a595f6SVinicius Costa Gomes 
3257a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3258bea710feSVinicius Costa Gomes 
3259bea710feSVinicius Costa Gomes 	return;
3260bea710feSVinicius Costa Gomes 
3261bea710feSVinicius Costa Gomes not_found:
3262bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3263bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3264bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3265a7a595f6SVinicius Costa Gomes }
3266a7a595f6SVinicius Costa Gomes 
3267fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3268fcd89c09SVille Tervo {
3269fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3270fcd89c09SVille Tervo 
3271fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3272fcd89c09SVille Tervo 
3273fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3274fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3275fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3276fcd89c09SVille Tervo 		break;
3277fcd89c09SVille Tervo 
32789aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
32799aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
32809aa04c91SAndre Guedes 		break;
32819aa04c91SAndre Guedes 
3282a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3283a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3284a7a595f6SVinicius Costa Gomes 		break;
3285a7a595f6SVinicius Costa Gomes 
3286fcd89c09SVille Tervo 	default:
3287fcd89c09SVille Tervo 		break;
3288fcd89c09SVille Tervo 	}
3289fcd89c09SVille Tervo }
3290fcd89c09SVille Tervo 
32911da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
32921da177e4SLinus Torvalds {
3293a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3294a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
32951da177e4SLinus Torvalds 
32961da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
32971da177e4SLinus Torvalds 
3298a9de9248SMarcel Holtmann 	switch (event) {
32991da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
33001da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
33011da177e4SLinus Torvalds 		break;
33021da177e4SLinus Torvalds 
33031da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
33041da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
33051da177e4SLinus Torvalds 		break;
33061da177e4SLinus Torvalds 
3307a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3308a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
330921d9e30eSMarcel Holtmann 		break;
331021d9e30eSMarcel Holtmann 
33111da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
33121da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
33131da177e4SLinus Torvalds 		break;
33141da177e4SLinus Torvalds 
33151da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
33161da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
33171da177e4SLinus Torvalds 		break;
33181da177e4SLinus Torvalds 
33191da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
33201da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
33211da177e4SLinus Torvalds 		break;
33221da177e4SLinus Torvalds 
3323a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3324a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3325a9de9248SMarcel Holtmann 		break;
3326a9de9248SMarcel Holtmann 
33271da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
33281da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
33291da177e4SLinus Torvalds 		break;
33301da177e4SLinus Torvalds 
3331a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3332a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3333a9de9248SMarcel Holtmann 		break;
3334a9de9248SMarcel Holtmann 
3335a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3336a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3337a9de9248SMarcel Holtmann 		break;
3338a9de9248SMarcel Holtmann 
3339a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3340a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3341a9de9248SMarcel Holtmann 		break;
3342a9de9248SMarcel Holtmann 
3343a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3344a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3345a9de9248SMarcel Holtmann 		break;
3346a9de9248SMarcel Holtmann 
3347a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3348a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3349a9de9248SMarcel Holtmann 		break;
3350a9de9248SMarcel Holtmann 
3351a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3352a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3353a9de9248SMarcel Holtmann 		break;
3354a9de9248SMarcel Holtmann 
3355a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3356a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3357a9de9248SMarcel Holtmann 		break;
3358a9de9248SMarcel Holtmann 
3359a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3360a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3361a9de9248SMarcel Holtmann 		break;
3362a9de9248SMarcel Holtmann 
3363a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3364a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
33651da177e4SLinus Torvalds 		break;
33661da177e4SLinus Torvalds 
33671da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
33681da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
33691da177e4SLinus Torvalds 		break;
33701da177e4SLinus Torvalds 
33711da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
33721da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
33731da177e4SLinus Torvalds 		break;
33741da177e4SLinus Torvalds 
33751da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
33761da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
33771da177e4SLinus Torvalds 		break;
33781da177e4SLinus Torvalds 
33791da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
33801da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
33811da177e4SLinus Torvalds 		break;
33821da177e4SLinus Torvalds 
3383a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3384a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3385a8746417SMarcel Holtmann 		break;
3386a8746417SMarcel Holtmann 
338785a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
338885a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
338985a1e930SMarcel Holtmann 		break;
339085a1e930SMarcel Holtmann 
3391a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3392a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3393a9de9248SMarcel Holtmann 		break;
3394a9de9248SMarcel Holtmann 
3395a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3396a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3397a9de9248SMarcel Holtmann 		break;
3398a9de9248SMarcel Holtmann 
3399a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3400a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3401a9de9248SMarcel Holtmann 		break;
3402a9de9248SMarcel Holtmann 
3403a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3404a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3405a9de9248SMarcel Holtmann 		break;
3406a9de9248SMarcel Holtmann 
340704837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
340804837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
340904837f64SMarcel Holtmann 		break;
341004837f64SMarcel Holtmann 
3411a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3412a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
34131da177e4SLinus Torvalds 		break;
34141da177e4SLinus Torvalds 
34150493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
34160493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
34170493684eSMarcel Holtmann 		break;
34180493684eSMarcel Holtmann 
341903b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
342003b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
342103b555e1SJohan Hedberg 		break;
342203b555e1SJohan Hedberg 
3423a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3424a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3425a5c29683SJohan Hedberg 		break;
3426a5c29683SJohan Hedberg 
34271143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
34281143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
34291143d458SBrian Gix 		break;
34301143d458SBrian Gix 
34310493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
34320493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
34330493684eSMarcel Holtmann 		break;
34340493684eSMarcel Holtmann 
343541a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
343641a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
343741a96212SMarcel Holtmann 		break;
343841a96212SMarcel Holtmann 
3439fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3440fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3441fcd89c09SVille Tervo 		break;
3442fcd89c09SVille Tervo 
34432763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
34442763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
34452763eda6SSzymon Janc 		break;
34462763eda6SSzymon Janc 
344725e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
344825e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
344925e89e99SAndrei Emeltchenko 		break;
345025e89e99SAndrei Emeltchenko 
34511da177e4SLinus Torvalds 	default:
3452a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
34531da177e4SLinus Torvalds 		break;
34541da177e4SLinus Torvalds 	}
34551da177e4SLinus Torvalds 
34561da177e4SLinus Torvalds 	kfree_skb(skb);
34571da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
34581da177e4SLinus Torvalds }
34591da177e4SLinus Torvalds 
34601da177e4SLinus Torvalds /* Generate internal stack event */
34611da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
34621da177e4SLinus Torvalds {
34631da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
34641da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
34651da177e4SLinus Torvalds 	struct sk_buff *skb;
34661da177e4SLinus Torvalds 
34671da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
34681da177e4SLinus Torvalds 	if (!skb)
34691da177e4SLinus Torvalds 		return;
34701da177e4SLinus Torvalds 
34711da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
34721da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
34731da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
34741da177e4SLinus Torvalds 
34751da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
34761da177e4SLinus Torvalds 	ev->type = type;
34771da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
34781da177e4SLinus Torvalds 
3479576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3480a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3481576c7d85SMarcel Holtmann 
34820d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
34831da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3484eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
34851da177e4SLinus Torvalds 	kfree_skb(skb);
34861da177e4SLinus Torvalds }
3487e6100a25SAndre Guedes 
3488669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3489e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3490