xref: /openbmc/linux/net/bluetooth/hci_event.c (revision a8b2d5c2)
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 
198d23264a8SAndre Guedes 	hdev->dev_flags = 0;
199a9de9248SMarcel Holtmann }
200a9de9248SMarcel Holtmann 
201a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
202a9de9248SMarcel Holtmann {
203a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2041da177e4SLinus Torvalds 	void *sent;
2051da177e4SLinus Torvalds 
206a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2071da177e4SLinus Torvalds 
208a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2091da177e4SLinus Torvalds 	if (!sent)
210a9de9248SMarcel Holtmann 		return;
2111da177e4SLinus Torvalds 
21256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21356e5cb86SJohan Hedberg 
214a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
215744cf19eSJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
216b312b161SJohan Hedberg 
21756e5cb86SJohan Hedberg 	if (status == 0)
2181f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
21956e5cb86SJohan Hedberg 
22056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
221a9de9248SMarcel Holtmann }
222a9de9248SMarcel Holtmann 
223a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
224a9de9248SMarcel Holtmann {
225a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
226a9de9248SMarcel Holtmann 
227a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
228a9de9248SMarcel Holtmann 
229a9de9248SMarcel Holtmann 	if (rp->status)
230a9de9248SMarcel Holtmann 		return;
231a9de9248SMarcel Holtmann 
2321f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
233a9de9248SMarcel Holtmann }
234a9de9248SMarcel Holtmann 
235a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
236a9de9248SMarcel Holtmann {
237a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
238a9de9248SMarcel Holtmann 	void *sent;
239a9de9248SMarcel Holtmann 
240a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
241a9de9248SMarcel Holtmann 
242a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
243a9de9248SMarcel Holtmann 	if (!sent)
244a9de9248SMarcel Holtmann 		return;
2451da177e4SLinus Torvalds 
2461da177e4SLinus Torvalds 	if (!status) {
247a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
248a9de9248SMarcel Holtmann 
2491da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2501da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2511da177e4SLinus Torvalds 		else
2521da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2531da177e4SLinus Torvalds 	}
254a9de9248SMarcel Holtmann 
25523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
256a9de9248SMarcel Holtmann }
2571da177e4SLinus Torvalds 
258a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
259a9de9248SMarcel Holtmann {
260a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
261a9de9248SMarcel Holtmann 	void *sent;
262a9de9248SMarcel Holtmann 
263a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
264a9de9248SMarcel Holtmann 
265a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2661da177e4SLinus Torvalds 	if (!sent)
267a9de9248SMarcel Holtmann 		return;
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds 	if (!status) {
270a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
271a9de9248SMarcel Holtmann 
2721da177e4SLinus Torvalds 		if (param)
2731da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2741da177e4SLinus Torvalds 		else
2751da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2761da177e4SLinus Torvalds 	}
277a9de9248SMarcel Holtmann 
27823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2791da177e4SLinus Torvalds }
2801da177e4SLinus Torvalds 
281a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
282a9de9248SMarcel Holtmann {
28336f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28436f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
285a9de9248SMarcel Holtmann 	void *sent;
2861da177e4SLinus Torvalds 
287a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
288a9de9248SMarcel Holtmann 
289a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2901da177e4SLinus Torvalds 	if (!sent)
291a9de9248SMarcel Holtmann 		return;
2921da177e4SLinus Torvalds 
29336f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
294a9de9248SMarcel Holtmann 
29556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29656e5cb86SJohan Hedberg 
2972d7cee58SJohan Hedberg 	if (status != 0) {
298744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
2992d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3002d7cee58SJohan Hedberg 		goto done;
3012d7cee58SJohan Hedberg 	}
3022d7cee58SJohan Hedberg 
3039fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3049fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
305a9de9248SMarcel Holtmann 
30673f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3071da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3089fbcbb45SJohan Hedberg 		if (!old_iscan)
309744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31016ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
31116ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31216ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31316ab91abSJohan Hedberg 									to);
31416ab91abSJohan Hedberg 		}
3159fbcbb45SJohan Hedberg 	} else if (old_iscan)
316744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3171da177e4SLinus Torvalds 
3189fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3191da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3209fbcbb45SJohan Hedberg 		if (!old_pscan)
321744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3229fbcbb45SJohan Hedberg 	} else if (old_pscan)
323744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
324a9de9248SMarcel Holtmann 
32536f7fc7eSJohan Hedberg done:
32656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
32723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3281da177e4SLinus Torvalds }
3291da177e4SLinus Torvalds 
330a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
331a9de9248SMarcel Holtmann {
332a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
333a9de9248SMarcel Holtmann 
334a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
335a9de9248SMarcel Holtmann 
336a9de9248SMarcel Holtmann 	if (rp->status)
337a9de9248SMarcel Holtmann 		return;
338a9de9248SMarcel Holtmann 
339a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
340a9de9248SMarcel Holtmann 
341a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
342a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
343a9de9248SMarcel Holtmann }
344a9de9248SMarcel Holtmann 
345a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
346a9de9248SMarcel Holtmann {
347a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
348a9de9248SMarcel Holtmann 	void *sent;
349a9de9248SMarcel Holtmann 
350a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
351a9de9248SMarcel Holtmann 
352f383f275SMarcel Holtmann 	if (status)
353f383f275SMarcel Holtmann 		return;
354f383f275SMarcel Holtmann 
355a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
356a9de9248SMarcel Holtmann 	if (!sent)
357a9de9248SMarcel Holtmann 		return;
358a9de9248SMarcel Holtmann 
359a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
360a9de9248SMarcel Holtmann }
361a9de9248SMarcel Holtmann 
362a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
363a9de9248SMarcel Holtmann {
364a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
365a9de9248SMarcel Holtmann 	__u16 setting;
366a9de9248SMarcel Holtmann 
367a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
368a9de9248SMarcel Holtmann 
369a9de9248SMarcel Holtmann 	if (rp->status)
370a9de9248SMarcel Holtmann 		return;
371a9de9248SMarcel Holtmann 
372a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
373a9de9248SMarcel Holtmann 
374a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
375a9de9248SMarcel Holtmann 		return;
376a9de9248SMarcel Holtmann 
377a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
378a9de9248SMarcel Holtmann 
379a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
380a9de9248SMarcel Holtmann 
3813c54711cSGustavo F. Padovan 	if (hdev->notify)
382a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
383a9de9248SMarcel Holtmann }
384a9de9248SMarcel Holtmann 
385a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
386a9de9248SMarcel Holtmann {
387a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
388f383f275SMarcel Holtmann 	__u16 setting;
389a9de9248SMarcel Holtmann 	void *sent;
390a9de9248SMarcel Holtmann 
391a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
392a9de9248SMarcel Holtmann 
393f383f275SMarcel Holtmann 	if (status)
394f383f275SMarcel Holtmann 		return;
395f383f275SMarcel Holtmann 
396a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
397a9de9248SMarcel Holtmann 	if (!sent)
398a9de9248SMarcel Holtmann 		return;
399a9de9248SMarcel Holtmann 
400f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4011da177e4SLinus Torvalds 
402f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
403f383f275SMarcel Holtmann 		return;
404f383f275SMarcel Holtmann 
4051da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4061da177e4SLinus Torvalds 
407a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4081da177e4SLinus Torvalds 
4093c54711cSGustavo F. Padovan 	if (hdev->notify)
4101da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4111da177e4SLinus Torvalds }
4121da177e4SLinus Torvalds 
413a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4141da177e4SLinus Torvalds {
415a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4161da177e4SLinus Torvalds 
417a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4181da177e4SLinus Torvalds 
41923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4201143e5a6SMarcel Holtmann }
4211143e5a6SMarcel Holtmann 
422333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
423333140b5SMarcel Holtmann {
424333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
425333140b5SMarcel Holtmann 
426333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
427333140b5SMarcel Holtmann 
428333140b5SMarcel Holtmann 	if (rp->status)
429333140b5SMarcel Holtmann 		return;
430333140b5SMarcel Holtmann 
431333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
432333140b5SMarcel Holtmann }
433333140b5SMarcel Holtmann 
434333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
435333140b5SMarcel Holtmann {
436333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
437333140b5SMarcel Holtmann 	void *sent;
438333140b5SMarcel Holtmann 
439333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
440333140b5SMarcel Holtmann 
441333140b5SMarcel Holtmann 	if (status)
442333140b5SMarcel Holtmann 		return;
443333140b5SMarcel Holtmann 
444333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
445333140b5SMarcel Holtmann 	if (!sent)
446333140b5SMarcel Holtmann 		return;
447333140b5SMarcel Holtmann 
448333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
449333140b5SMarcel Holtmann }
450333140b5SMarcel Holtmann 
451d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
452d5859e22SJohan Hedberg {
453d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
454d5859e22SJohan Hedberg 		return 2;
455d5859e22SJohan Hedberg 
456d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
457d5859e22SJohan Hedberg 		return 1;
458d5859e22SJohan Hedberg 
459d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
460d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
461d5859e22SJohan Hedberg 		return 1;
462d5859e22SJohan Hedberg 
463d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
464d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
465d5859e22SJohan Hedberg 			return 1;
466d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
467d5859e22SJohan Hedberg 			return 1;
468d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
469d5859e22SJohan Hedberg 			return 1;
470d5859e22SJohan Hedberg 	}
471d5859e22SJohan Hedberg 
472d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
473d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
474d5859e22SJohan Hedberg 		return 1;
475d5859e22SJohan Hedberg 
476d5859e22SJohan Hedberg 	return 0;
477d5859e22SJohan Hedberg }
478d5859e22SJohan Hedberg 
479d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
480d5859e22SJohan Hedberg {
481d5859e22SJohan Hedberg 	u8 mode;
482d5859e22SJohan Hedberg 
483d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
484d5859e22SJohan Hedberg 
485d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
486d5859e22SJohan Hedberg }
487d5859e22SJohan Hedberg 
488d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
489d5859e22SJohan Hedberg {
490d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
491d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
492d5859e22SJohan Hedberg 	 * command otherwise */
493d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
494d5859e22SJohan Hedberg 
4956de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
4966de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
4975a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
4986de6c18dSVille Tervo 		return;
4996de6c18dSVille Tervo 
500d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
501d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
502d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
503d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
504d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
505d5859e22SJohan Hedberg 
506d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
507d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
508d5859e22SJohan Hedberg 
509d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
510d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
511d5859e22SJohan Hedberg 
512d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
513d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
514d5859e22SJohan Hedberg 
515d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
516d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
517d5859e22SJohan Hedberg 
518d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
519d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
520d5859e22SJohan Hedberg 
521d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
522d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
523d5859e22SJohan Hedberg 
524d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
525d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
526d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
527d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
528d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
529d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
530d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
531d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
532d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
533d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
534d5859e22SJohan Hedberg 					 * Features Notification */
535d5859e22SJohan Hedberg 	}
536d5859e22SJohan Hedberg 
537d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
538d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
539d5859e22SJohan Hedberg 
540d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
541d5859e22SJohan Hedberg }
542d5859e22SJohan Hedberg 
543e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
544e6100a25SAndre Guedes {
545e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
546e6100a25SAndre Guedes 
547e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
548e6100a25SAndre Guedes 
549e6100a25SAndre Guedes 	if (enable_le) {
550e6100a25SAndre Guedes 		cp.le = 1;
551e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
552e6100a25SAndre Guedes 	}
553e6100a25SAndre Guedes 
554e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
555e6100a25SAndre Guedes }
556e6100a25SAndre Guedes 
557d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
558d5859e22SJohan Hedberg {
559e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
560e61ef499SAndrei Emeltchenko 		return;
561e61ef499SAndrei Emeltchenko 
562d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
563d5859e22SJohan Hedberg 
564d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
565d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
566d5859e22SJohan Hedberg 
567d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
568d5859e22SJohan Hedberg 		u8 mode = 0x01;
569d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
570d5859e22SJohan Hedberg 	}
571d5859e22SJohan Hedberg 
572d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
573d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
574d5859e22SJohan Hedberg 
575d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
576d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
577971e3a4bSAndre Guedes 
578971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
579971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
580971e3a4bSAndre Guedes 
581971e3a4bSAndre Guedes 		cp.page = 0x01;
582971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
583971e3a4bSAndre Guedes 							sizeof(cp), &cp);
584971e3a4bSAndre Guedes 	}
585e6100a25SAndre Guedes 
586e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
587e6100a25SAndre Guedes 		hci_set_le_support(hdev);
588d5859e22SJohan Hedberg }
589d5859e22SJohan Hedberg 
590a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
591a9de9248SMarcel Holtmann {
592a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5931143e5a6SMarcel Holtmann 
594a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5951143e5a6SMarcel Holtmann 
596a9de9248SMarcel Holtmann 	if (rp->status)
597a9de9248SMarcel Holtmann 		return;
5981143e5a6SMarcel Holtmann 
599a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
600e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
601d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
602e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
603d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6041da177e4SLinus Torvalds 
605a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
606a9de9248SMarcel Holtmann 					hdev->manufacturer,
607a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
608d5859e22SJohan Hedberg 
609d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
610d5859e22SJohan Hedberg 		hci_setup(hdev);
611d5859e22SJohan Hedberg }
612d5859e22SJohan Hedberg 
613d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
614d5859e22SJohan Hedberg {
615d5859e22SJohan Hedberg 	u16 link_policy = 0;
616d5859e22SJohan Hedberg 
617d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
618d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
619d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
620d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
621d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
622d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
623d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
624d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
625d5859e22SJohan Hedberg 
626d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
627d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
628d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6291da177e4SLinus Torvalds }
6301da177e4SLinus Torvalds 
631a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
632a9de9248SMarcel Holtmann {
633a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
634a9de9248SMarcel Holtmann 
635a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
636a9de9248SMarcel Holtmann 
637a9de9248SMarcel Holtmann 	if (rp->status)
638d5859e22SJohan Hedberg 		goto done;
639a9de9248SMarcel Holtmann 
640a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
641d5859e22SJohan Hedberg 
642d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
643d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
644d5859e22SJohan Hedberg 
645d5859e22SJohan Hedberg done:
646d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
647a9de9248SMarcel Holtmann }
648a9de9248SMarcel Holtmann 
649a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
650a9de9248SMarcel Holtmann {
651a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
652a9de9248SMarcel Holtmann 
653a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
654a9de9248SMarcel Holtmann 
655a9de9248SMarcel Holtmann 	if (rp->status)
656a9de9248SMarcel Holtmann 		return;
657a9de9248SMarcel Holtmann 
658a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6591da177e4SLinus Torvalds 
6601da177e4SLinus Torvalds 	/* Adjust default settings according to features
6611da177e4SLinus Torvalds 	 * supported by device. */
662a9de9248SMarcel Holtmann 
6631da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6641da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6651da177e4SLinus Torvalds 
6661da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6671da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6681da177e4SLinus Torvalds 
6695b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6701da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6715b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6725b7f9909SMarcel Holtmann 	}
6731da177e4SLinus Torvalds 
6745b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6751da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6765b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6775b7f9909SMarcel Holtmann 	}
6785b7f9909SMarcel Holtmann 
6795b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6805b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6815b7f9909SMarcel Holtmann 
6825b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6835b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6845b7f9909SMarcel Holtmann 
6855b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6865b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6871da177e4SLinus Torvalds 
688efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
689efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
690efc7688bSMarcel Holtmann 
691efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
692efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
693efc7688bSMarcel Holtmann 
694efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
695efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
696efc7688bSMarcel Holtmann 
697a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
698a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
699a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
700a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
701a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7021da177e4SLinus Torvalds }
7031da177e4SLinus Torvalds 
704971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
705971e3a4bSAndre Guedes 							struct sk_buff *skb)
706971e3a4bSAndre Guedes {
707971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
708971e3a4bSAndre Guedes 
709971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
710971e3a4bSAndre Guedes 
711971e3a4bSAndre Guedes 	if (rp->status)
712971e3a4bSAndre Guedes 		return;
713971e3a4bSAndre Guedes 
714b5b32b65SAndre Guedes 	switch (rp->page) {
715b5b32b65SAndre Guedes 	case 0:
716b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
717b5b32b65SAndre Guedes 		break;
718b5b32b65SAndre Guedes 	case 1:
71959e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
720b5b32b65SAndre Guedes 		break;
721b5b32b65SAndre Guedes 	}
722971e3a4bSAndre Guedes 
723971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
724971e3a4bSAndre Guedes }
725971e3a4bSAndre Guedes 
7261e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7271e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7281e89cffbSAndrei Emeltchenko {
7291e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7301e89cffbSAndrei Emeltchenko 
7311e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7321e89cffbSAndrei Emeltchenko 
7331e89cffbSAndrei Emeltchenko 	if (rp->status)
7341e89cffbSAndrei Emeltchenko 		return;
7351e89cffbSAndrei Emeltchenko 
7361e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7371e89cffbSAndrei Emeltchenko 
7381e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7391e89cffbSAndrei Emeltchenko }
7401e89cffbSAndrei Emeltchenko 
741a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
742a9de9248SMarcel Holtmann {
743a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
744a9de9248SMarcel Holtmann 
745a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
746a9de9248SMarcel Holtmann 
747a9de9248SMarcel Holtmann 	if (rp->status)
748a9de9248SMarcel Holtmann 		return;
749a9de9248SMarcel Holtmann 
750a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
751a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
752a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
753a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
754da1f5198SMarcel Holtmann 
755da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
756da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
757da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
758da1f5198SMarcel Holtmann 	}
759da1f5198SMarcel Holtmann 
760da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
761da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7621da177e4SLinus Torvalds 
763a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
764a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
765a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7661da177e4SLinus Torvalds }
7671da177e4SLinus Torvalds 
768a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
769a9de9248SMarcel Holtmann {
770a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7711da177e4SLinus Torvalds 
772a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
773a9de9248SMarcel Holtmann 
774a9de9248SMarcel Holtmann 	if (!rp->status)
775a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
776a9de9248SMarcel Holtmann 
77723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
77823bb5763SJohan Hedberg }
77923bb5763SJohan Hedberg 
780350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
781350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
782350ee4cfSAndrei Emeltchenko {
783350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
784350ee4cfSAndrei Emeltchenko 
785350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
786350ee4cfSAndrei Emeltchenko 
787350ee4cfSAndrei Emeltchenko 	if (rp->status)
788350ee4cfSAndrei Emeltchenko 		return;
789350ee4cfSAndrei Emeltchenko 
790350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
791350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
792350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
793350ee4cfSAndrei Emeltchenko 
794350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
795350ee4cfSAndrei Emeltchenko 
796350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
797350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
798350ee4cfSAndrei Emeltchenko 
799350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
800350ee4cfSAndrei Emeltchenko }
801350ee4cfSAndrei Emeltchenko 
80223bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
80323bb5763SJohan Hedberg {
80423bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
80523bb5763SJohan Hedberg 
80623bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
80723bb5763SJohan Hedberg 
80823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8091da177e4SLinus Torvalds }
8101da177e4SLinus Torvalds 
811928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
812928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
813928abaa7SAndrei Emeltchenko {
814928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
815928abaa7SAndrei Emeltchenko 
816928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
817928abaa7SAndrei Emeltchenko 
818928abaa7SAndrei Emeltchenko 	if (rp->status)
819928abaa7SAndrei Emeltchenko 		return;
820928abaa7SAndrei Emeltchenko 
821928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
822928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
823928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
824928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
825928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
826928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
827928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
828928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
829928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
830928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
831928abaa7SAndrei Emeltchenko 
832928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
833928abaa7SAndrei Emeltchenko }
834928abaa7SAndrei Emeltchenko 
835b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
836b0916ea0SJohan Hedberg 							struct sk_buff *skb)
837b0916ea0SJohan Hedberg {
838b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
839b0916ea0SJohan Hedberg 
840b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
841b0916ea0SJohan Hedberg 
842b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
843b0916ea0SJohan Hedberg }
844b0916ea0SJohan Hedberg 
845d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
846d5859e22SJohan Hedberg {
847d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
848d5859e22SJohan Hedberg 
849d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
850d5859e22SJohan Hedberg 
851d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
852d5859e22SJohan Hedberg }
853d5859e22SJohan Hedberg 
854d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
855d5859e22SJohan Hedberg 							struct sk_buff *skb)
856d5859e22SJohan Hedberg {
857d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
858d5859e22SJohan Hedberg 
859d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
860d5859e22SJohan Hedberg 
861d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
862d5859e22SJohan Hedberg }
863d5859e22SJohan Hedberg 
864d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
865d5859e22SJohan Hedberg 							struct sk_buff *skb)
866d5859e22SJohan Hedberg {
867d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
868d5859e22SJohan Hedberg 
869d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
870d5859e22SJohan Hedberg 
871d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
872d5859e22SJohan Hedberg }
873d5859e22SJohan Hedberg 
874d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
875d5859e22SJohan Hedberg {
876d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
877d5859e22SJohan Hedberg 
878d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
879d5859e22SJohan Hedberg 
880d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
881d5859e22SJohan Hedberg }
882d5859e22SJohan Hedberg 
883980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
884980e1a53SJohan Hedberg {
885980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
886980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
887980e1a53SJohan Hedberg 	struct hci_conn *conn;
888980e1a53SJohan Hedberg 
889980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
890980e1a53SJohan Hedberg 
89156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
89256e5cb86SJohan Hedberg 
893a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
894744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
895980e1a53SJohan Hedberg 
896980e1a53SJohan Hedberg 	if (rp->status != 0)
89756e5cb86SJohan Hedberg 		goto unlock;
898980e1a53SJohan Hedberg 
899980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
900980e1a53SJohan Hedberg 	if (!cp)
90156e5cb86SJohan Hedberg 		goto unlock;
902980e1a53SJohan Hedberg 
903980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
904980e1a53SJohan Hedberg 	if (conn)
905980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
90656e5cb86SJohan Hedberg 
90756e5cb86SJohan Hedberg unlock:
90856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
909980e1a53SJohan Hedberg }
910980e1a53SJohan Hedberg 
911980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
912980e1a53SJohan Hedberg {
913980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
914980e1a53SJohan Hedberg 
915980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
916980e1a53SJohan Hedberg 
91756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
91856e5cb86SJohan Hedberg 
919a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
920744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
921980e1a53SJohan Hedberg 								rp->status);
92256e5cb86SJohan Hedberg 
92356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
924980e1a53SJohan Hedberg }
92556e5cb86SJohan Hedberg 
9266ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9276ed58ec5SVille Tervo 				       struct sk_buff *skb)
9286ed58ec5SVille Tervo {
9296ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9306ed58ec5SVille Tervo 
9316ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9326ed58ec5SVille Tervo 
9336ed58ec5SVille Tervo 	if (rp->status)
9346ed58ec5SVille Tervo 		return;
9356ed58ec5SVille Tervo 
9366ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9376ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9386ed58ec5SVille Tervo 
9396ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9406ed58ec5SVille Tervo 
9416ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9426ed58ec5SVille Tervo 
9436ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9446ed58ec5SVille Tervo }
945980e1a53SJohan Hedberg 
946a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
947a5c29683SJohan Hedberg {
948a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
949a5c29683SJohan Hedberg 
950a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
951a5c29683SJohan Hedberg 
95256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
95356e5cb86SJohan Hedberg 
954a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
955744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
956a5c29683SJohan Hedberg 								rp->status);
95756e5cb86SJohan Hedberg 
95856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
959a5c29683SJohan Hedberg }
960a5c29683SJohan Hedberg 
961a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
962a5c29683SJohan Hedberg 							struct sk_buff *skb)
963a5c29683SJohan Hedberg {
964a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
965a5c29683SJohan Hedberg 
966a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
967a5c29683SJohan Hedberg 
96856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96956e5cb86SJohan Hedberg 
970a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
971744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
972a5c29683SJohan Hedberg 								rp->status);
97356e5cb86SJohan Hedberg 
97456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
975a5c29683SJohan Hedberg }
976a5c29683SJohan Hedberg 
9771143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9781143d458SBrian Gix {
9791143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9801143d458SBrian Gix 
9811143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9821143d458SBrian Gix 
9831143d458SBrian Gix 	hci_dev_lock(hdev);
9841143d458SBrian Gix 
985a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9861143d458SBrian Gix 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
9871143d458SBrian Gix 								rp->status);
9881143d458SBrian Gix 
9891143d458SBrian Gix 	hci_dev_unlock(hdev);
9901143d458SBrian Gix }
9911143d458SBrian Gix 
9921143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9931143d458SBrian Gix 							struct sk_buff *skb)
9941143d458SBrian Gix {
9951143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9961143d458SBrian Gix 
9971143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9981143d458SBrian Gix 
9991143d458SBrian Gix 	hci_dev_lock(hdev);
10001143d458SBrian Gix 
1001a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10021143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
10031143d458SBrian Gix 								rp->status);
10041143d458SBrian Gix 
10051143d458SBrian Gix 	hci_dev_unlock(hdev);
10061143d458SBrian Gix }
10071143d458SBrian Gix 
1008c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1009c35938b2SSzymon Janc 							struct sk_buff *skb)
1010c35938b2SSzymon Janc {
1011c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1012c35938b2SSzymon Janc 
1013c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1014c35938b2SSzymon Janc 
101556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1016744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1017c35938b2SSzymon Janc 						rp->randomizer, rp->status);
101856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1019c35938b2SSzymon Janc }
1020c35938b2SSzymon Janc 
102107f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
102207f7fa5dSAndre Guedes {
102307f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
102407f7fa5dSAndre Guedes 
102507f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
102607f7fa5dSAndre Guedes }
102707f7fa5dSAndre Guedes 
1028eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1029eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1030eb9d91f5SAndre Guedes {
1031eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1032eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1033eb9d91f5SAndre Guedes 
1034eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1035eb9d91f5SAndre Guedes 
1036eb9d91f5SAndre Guedes 	if (status)
1037eb9d91f5SAndre Guedes 		return;
1038eb9d91f5SAndre Guedes 
1039eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1040eb9d91f5SAndre Guedes 	if (!cp)
1041eb9d91f5SAndre Guedes 		return;
1042eb9d91f5SAndre Guedes 
104368a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
104468a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
1045d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1046d23264a8SAndre Guedes 
1047db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1048a8f13c8cSAndre Guedes 
1049a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1050eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1051a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
105268a8aea4SAndrei Emeltchenko 		break;
105368a8aea4SAndrei Emeltchenko 
105468a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1055d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1056d23264a8SAndre Guedes 
1057d084329eSAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
105868a8aea4SAndrei Emeltchenko 		break;
105968a8aea4SAndrei Emeltchenko 
106068a8aea4SAndrei Emeltchenko 	default:
106168a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
106268a8aea4SAndrei Emeltchenko 		break;
106335815085SAndre Guedes 	}
1064eb9d91f5SAndre Guedes }
1065eb9d91f5SAndre Guedes 
1066a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1067a7a595f6SVinicius Costa Gomes {
1068a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1069a7a595f6SVinicius Costa Gomes 
1070a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1071a7a595f6SVinicius Costa Gomes 
1072a7a595f6SVinicius Costa Gomes 	if (rp->status)
1073a7a595f6SVinicius Costa Gomes 		return;
1074a7a595f6SVinicius Costa Gomes 
1075a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1076a7a595f6SVinicius Costa Gomes }
1077a7a595f6SVinicius Costa Gomes 
1078a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1079a7a595f6SVinicius Costa Gomes {
1080a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1081a7a595f6SVinicius Costa Gomes 
1082a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1083a7a595f6SVinicius Costa Gomes 
1084a7a595f6SVinicius Costa Gomes 	if (rp->status)
1085a7a595f6SVinicius Costa Gomes 		return;
1086a7a595f6SVinicius Costa Gomes 
1087a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1088a7a595f6SVinicius Costa Gomes }
1089a7a595f6SVinicius Costa Gomes 
1090f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1091f9b49306SAndre Guedes 							struct sk_buff *skb)
1092f9b49306SAndre Guedes {
1093f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1094f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1095f9b49306SAndre Guedes 
1096f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1097f9b49306SAndre Guedes 
1098f9b49306SAndre Guedes 	if (status)
1099f9b49306SAndre Guedes 		return;
1100f9b49306SAndre Guedes 
1101f9b49306SAndre Guedes 	cp.page = 0x01;
1102f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1103f9b49306SAndre Guedes }
1104f9b49306SAndre Guedes 
1105a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1106a9de9248SMarcel Holtmann {
1107a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1108a9de9248SMarcel Holtmann 
1109a9de9248SMarcel Holtmann 	if (status) {
111023bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1111a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
111256e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1113a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11147a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
111556e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1116314b2381SJohan Hedberg 		return;
1117314b2381SJohan Hedberg 	}
1118314b2381SJohan Hedberg 
111989352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
112089352e7dSAndre Guedes 
112156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
112230dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_INQUIRY);
112356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1124a9de9248SMarcel Holtmann }
1125a9de9248SMarcel Holtmann 
11261da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11271da177e4SLinus Torvalds {
1128a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11291da177e4SLinus Torvalds 	struct hci_conn *conn;
11301da177e4SLinus Torvalds 
1131a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1132a9de9248SMarcel Holtmann 
1133a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11341da177e4SLinus Torvalds 	if (!cp)
11351da177e4SLinus Torvalds 		return;
11361da177e4SLinus Torvalds 
11371da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11381da177e4SLinus Torvalds 
11391da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11401da177e4SLinus Torvalds 
1141a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11421da177e4SLinus Torvalds 
11431da177e4SLinus Torvalds 	if (status) {
11441da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11454c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11461da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11471da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11481da177e4SLinus Torvalds 				hci_conn_del(conn);
11494c67bc74SMarcel Holtmann 			} else
11504c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11511da177e4SLinus Torvalds 		}
11521da177e4SLinus Torvalds 	} else {
11531da177e4SLinus Torvalds 		if (!conn) {
11541da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11551da177e4SLinus Torvalds 			if (conn) {
11561da177e4SLinus Torvalds 				conn->out = 1;
11571da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11581da177e4SLinus Torvalds 			} else
1159893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11601da177e4SLinus Torvalds 		}
11611da177e4SLinus Torvalds 	}
11621da177e4SLinus Torvalds 
11631da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11641da177e4SLinus Torvalds }
11651da177e4SLinus Torvalds 
1166a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11671da177e4SLinus Torvalds {
1168a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11691da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11701da177e4SLinus Torvalds 	__u16 handle;
11711da177e4SLinus Torvalds 
1172b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1173b6a0dc82SMarcel Holtmann 
1174a9de9248SMarcel Holtmann 	if (!status)
1175a9de9248SMarcel Holtmann 		return;
1176a9de9248SMarcel Holtmann 
1177a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11781da177e4SLinus Torvalds 	if (!cp)
1179a9de9248SMarcel Holtmann 		return;
11801da177e4SLinus Torvalds 
11811da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11821da177e4SLinus Torvalds 
1183a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
11841da177e4SLinus Torvalds 
11851da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11861da177e4SLinus Torvalds 
11871da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11885a08ecceSAndrei Emeltchenko 	if (acl) {
11895a08ecceSAndrei Emeltchenko 		sco = acl->link;
11905a08ecceSAndrei Emeltchenko 		if (sco) {
11911da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11941da177e4SLinus Torvalds 			hci_conn_del(sco);
11951da177e4SLinus Torvalds 		}
11965a08ecceSAndrei Emeltchenko 	}
11971da177e4SLinus Torvalds 
11981da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11991da177e4SLinus Torvalds }
12001da177e4SLinus Torvalds 
1201f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1202f8558555SMarcel Holtmann {
1203f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1204f8558555SMarcel Holtmann 	struct hci_conn *conn;
1205f8558555SMarcel Holtmann 
1206f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1207f8558555SMarcel Holtmann 
1208f8558555SMarcel Holtmann 	if (!status)
1209f8558555SMarcel Holtmann 		return;
1210f8558555SMarcel Holtmann 
1211f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1212f8558555SMarcel Holtmann 	if (!cp)
1213f8558555SMarcel Holtmann 		return;
1214f8558555SMarcel Holtmann 
1215f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1216f8558555SMarcel Holtmann 
1217f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1218f8558555SMarcel Holtmann 	if (conn) {
1219f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1220f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1221f8558555SMarcel Holtmann 			hci_conn_put(conn);
1222f8558555SMarcel Holtmann 		}
1223f8558555SMarcel Holtmann 	}
1224f8558555SMarcel Holtmann 
1225f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1226f8558555SMarcel Holtmann }
1227f8558555SMarcel Holtmann 
1228f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1229f8558555SMarcel Holtmann {
1230f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1231f8558555SMarcel Holtmann 	struct hci_conn *conn;
1232f8558555SMarcel Holtmann 
1233f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1234f8558555SMarcel Holtmann 
1235f8558555SMarcel Holtmann 	if (!status)
1236f8558555SMarcel Holtmann 		return;
1237f8558555SMarcel Holtmann 
1238f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1239f8558555SMarcel Holtmann 	if (!cp)
1240f8558555SMarcel Holtmann 		return;
1241f8558555SMarcel Holtmann 
1242f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1243f8558555SMarcel Holtmann 
1244f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1245f8558555SMarcel Holtmann 	if (conn) {
1246f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1247f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1248f8558555SMarcel Holtmann 			hci_conn_put(conn);
1249f8558555SMarcel Holtmann 		}
1250f8558555SMarcel Holtmann 	}
1251f8558555SMarcel Holtmann 
1252f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1253f8558555SMarcel Holtmann }
1254f8558555SMarcel Holtmann 
1255127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1256392599b9SJohan Hedberg 							struct hci_conn *conn)
1257392599b9SJohan Hedberg {
1258392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1259392599b9SJohan Hedberg 		return 0;
1260392599b9SJohan Hedberg 
1261765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1262392599b9SJohan Hedberg 		return 0;
1263392599b9SJohan Hedberg 
1264392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1265e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1266392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1267e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1268e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1269392599b9SJohan Hedberg 		return 0;
1270392599b9SJohan Hedberg 
1271392599b9SJohan Hedberg 	return 1;
1272392599b9SJohan Hedberg }
1273392599b9SJohan Hedberg 
127430dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
127530dc78e1SJohan Hedberg {
127630dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
127730dc78e1SJohan Hedberg 
127830dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
127930dc78e1SJohan Hedberg 
128030dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
128130dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
128230dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
128330dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
128430dc78e1SJohan Hedberg 
128530dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
128630dc78e1SJohan Hedberg }
128730dc78e1SJohan Hedberg 
128830dc78e1SJohan Hedberg static void hci_resolve_next_name(struct hci_dev *hdev, bdaddr_t *bdaddr)
128930dc78e1SJohan Hedberg {
129030dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
129130dc78e1SJohan Hedberg 	struct inquiry_entry *e;
129230dc78e1SJohan Hedberg 
129330dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
129430dc78e1SJohan Hedberg 		goto discov_complete;
129530dc78e1SJohan Hedberg 
129630dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
129730dc78e1SJohan Hedberg 		return;
129830dc78e1SJohan Hedberg 
129930dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
130030dc78e1SJohan Hedberg 	if (e) {
130130dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
130230dc78e1SJohan Hedberg 		list_del(&e->list);
130330dc78e1SJohan Hedberg 	}
130430dc78e1SJohan Hedberg 
130530dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve))
130630dc78e1SJohan Hedberg 		goto discov_complete;
130730dc78e1SJohan Hedberg 
130830dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
130930dc78e1SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
131030dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
131130dc78e1SJohan Hedberg 		return;
131230dc78e1SJohan Hedberg 	}
131330dc78e1SJohan Hedberg 
131430dc78e1SJohan Hedberg discov_complete:
131530dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
131630dc78e1SJohan Hedberg }
131730dc78e1SJohan Hedberg 
1318a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13191da177e4SLinus Torvalds {
1320127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1321127178d2SJohan Hedberg 	struct hci_conn *conn;
1322127178d2SJohan Hedberg 
1323a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1324127178d2SJohan Hedberg 
1325127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1326127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1327127178d2SJohan Hedberg 	if (!status)
1328127178d2SJohan Hedberg 		return;
1329127178d2SJohan Hedberg 
1330127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1331127178d2SJohan Hedberg 	if (!cp)
1332127178d2SJohan Hedberg 		return;
1333127178d2SJohan Hedberg 
1334127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1335127178d2SJohan Hedberg 
1336a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
133730dc78e1SJohan Hedberg 		hci_resolve_next_name(hdev, &cp->bdaddr);
133830dc78e1SJohan Hedberg 
1339127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
134079c6c70cSJohan Hedberg 	if (!conn)
134179c6c70cSJohan Hedberg 		goto unlock;
134279c6c70cSJohan Hedberg 
134379c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
134479c6c70cSJohan Hedberg 		goto unlock;
134579c6c70cSJohan Hedberg 
134679c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1347127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1348127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1349127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1350127178d2SJohan Hedberg 	}
1351127178d2SJohan Hedberg 
135279c6c70cSJohan Hedberg unlock:
1353127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1354a9de9248SMarcel Holtmann }
13551da177e4SLinus Torvalds 
1356769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1357769be974SMarcel Holtmann {
1358769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1359769be974SMarcel Holtmann 	struct hci_conn *conn;
1360769be974SMarcel Holtmann 
1361769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1362769be974SMarcel Holtmann 
1363769be974SMarcel Holtmann 	if (!status)
1364769be974SMarcel Holtmann 		return;
1365769be974SMarcel Holtmann 
1366769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1367769be974SMarcel Holtmann 	if (!cp)
1368769be974SMarcel Holtmann 		return;
1369769be974SMarcel Holtmann 
1370769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1371769be974SMarcel Holtmann 
1372769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1373769be974SMarcel Holtmann 	if (conn) {
1374769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1375769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1376769be974SMarcel Holtmann 			hci_conn_put(conn);
1377769be974SMarcel Holtmann 		}
1378769be974SMarcel Holtmann 	}
1379769be974SMarcel Holtmann 
1380769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1381769be974SMarcel Holtmann }
1382769be974SMarcel Holtmann 
1383769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1384769be974SMarcel Holtmann {
1385769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1386769be974SMarcel Holtmann 	struct hci_conn *conn;
1387769be974SMarcel Holtmann 
1388769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1389769be974SMarcel Holtmann 
1390769be974SMarcel Holtmann 	if (!status)
1391769be974SMarcel Holtmann 		return;
1392769be974SMarcel Holtmann 
1393769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1394769be974SMarcel Holtmann 	if (!cp)
1395769be974SMarcel Holtmann 		return;
1396769be974SMarcel Holtmann 
1397769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1398769be974SMarcel Holtmann 
1399769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1400769be974SMarcel Holtmann 	if (conn) {
1401769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1402769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1403769be974SMarcel Holtmann 			hci_conn_put(conn);
1404769be974SMarcel Holtmann 		}
1405769be974SMarcel Holtmann 	}
1406769be974SMarcel Holtmann 
1407769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1408769be974SMarcel Holtmann }
1409769be974SMarcel Holtmann 
1410a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1411a9de9248SMarcel Holtmann {
1412b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1413b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1414b6a0dc82SMarcel Holtmann 	__u16 handle;
1415b6a0dc82SMarcel Holtmann 
1416a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1417b6a0dc82SMarcel Holtmann 
1418b6a0dc82SMarcel Holtmann 	if (!status)
1419b6a0dc82SMarcel Holtmann 		return;
1420b6a0dc82SMarcel Holtmann 
1421b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1422b6a0dc82SMarcel Holtmann 	if (!cp)
1423b6a0dc82SMarcel Holtmann 		return;
1424b6a0dc82SMarcel Holtmann 
1425b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1426b6a0dc82SMarcel Holtmann 
1427b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1428b6a0dc82SMarcel Holtmann 
1429b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1430b6a0dc82SMarcel Holtmann 
1431b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14325a08ecceSAndrei Emeltchenko 	if (acl) {
14335a08ecceSAndrei Emeltchenko 		sco = acl->link;
14345a08ecceSAndrei Emeltchenko 		if (sco) {
1435b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1436b6a0dc82SMarcel Holtmann 
1437b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1438b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1439b6a0dc82SMarcel Holtmann 		}
14405a08ecceSAndrei Emeltchenko 	}
1441b6a0dc82SMarcel Holtmann 
1442b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1443a9de9248SMarcel Holtmann }
1444a9de9248SMarcel Holtmann 
1445a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1446a9de9248SMarcel Holtmann {
1447a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
144804837f64SMarcel Holtmann 	struct hci_conn *conn;
144904837f64SMarcel Holtmann 
1450a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1451a9de9248SMarcel Holtmann 
1452a9de9248SMarcel Holtmann 	if (!status)
1453a9de9248SMarcel Holtmann 		return;
1454a9de9248SMarcel Holtmann 
1455a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
145604837f64SMarcel Holtmann 	if (!cp)
1457a9de9248SMarcel Holtmann 		return;
145804837f64SMarcel Holtmann 
145904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
146004837f64SMarcel Holtmann 
146104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1462e73439d8SMarcel Holtmann 	if (conn) {
146304837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
146404837f64SMarcel Holtmann 
1465e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1466e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1467e73439d8SMarcel Holtmann 	}
1468e73439d8SMarcel Holtmann 
146904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
147004837f64SMarcel Holtmann }
147104837f64SMarcel Holtmann 
1472a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1473a9de9248SMarcel Holtmann {
1474a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
147504837f64SMarcel Holtmann 	struct hci_conn *conn;
147604837f64SMarcel Holtmann 
1477a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1478a9de9248SMarcel Holtmann 
1479a9de9248SMarcel Holtmann 	if (!status)
1480a9de9248SMarcel Holtmann 		return;
1481a9de9248SMarcel Holtmann 
1482a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
148304837f64SMarcel Holtmann 	if (!cp)
1484a9de9248SMarcel Holtmann 		return;
148504837f64SMarcel Holtmann 
148604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
148704837f64SMarcel Holtmann 
148804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1489e73439d8SMarcel Holtmann 	if (conn) {
149004837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
149104837f64SMarcel Holtmann 
1492e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1493e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1494e73439d8SMarcel Holtmann 	}
1495e73439d8SMarcel Holtmann 
149604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
149704837f64SMarcel Holtmann }
149804837f64SMarcel Holtmann 
1499fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1500fcd89c09SVille Tervo {
1501fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1502fcd89c09SVille Tervo 	struct hci_conn *conn;
1503fcd89c09SVille Tervo 
1504fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1505fcd89c09SVille Tervo 
1506fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1507fcd89c09SVille Tervo 	if (!cp)
1508fcd89c09SVille Tervo 		return;
1509fcd89c09SVille Tervo 
1510fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1511fcd89c09SVille Tervo 
1512fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1513fcd89c09SVille Tervo 
1514fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1515fcd89c09SVille Tervo 		conn);
1516fcd89c09SVille Tervo 
1517fcd89c09SVille Tervo 	if (status) {
1518fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1519fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1520fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1521fcd89c09SVille Tervo 			hci_conn_del(conn);
1522fcd89c09SVille Tervo 		}
1523fcd89c09SVille Tervo 	} else {
1524fcd89c09SVille Tervo 		if (!conn) {
1525fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
152629b7988aSAndre Guedes 			if (conn) {
152729b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1528fcd89c09SVille Tervo 				conn->out = 1;
152929b7988aSAndre Guedes 			} else {
1530fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1531fcd89c09SVille Tervo 			}
1532fcd89c09SVille Tervo 		}
153329b7988aSAndre Guedes 	}
1534fcd89c09SVille Tervo 
1535fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1536fcd89c09SVille Tervo }
1537fcd89c09SVille Tervo 
1538a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1539a7a595f6SVinicius Costa Gomes {
1540a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1541a7a595f6SVinicius Costa Gomes }
1542a7a595f6SVinicius Costa Gomes 
15431da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15441da177e4SLinus Torvalds {
15451da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
154630dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
154730dc78e1SJohan Hedberg 	struct inquiry_entry *e;
15481da177e4SLinus Torvalds 
15491da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
15501da177e4SLinus Torvalds 
155123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
15526bd57416SMarcel Holtmann 
1553a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
155489352e7dSAndre Guedes 
155589352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
155689352e7dSAndre Guedes 		return;
155789352e7dSAndre Guedes 
1558a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
155930dc78e1SJohan Hedberg 		return;
156030dc78e1SJohan Hedberg 
156156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
156230dc78e1SJohan Hedberg 
156330dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_INQUIRY)
156430dc78e1SJohan Hedberg 		goto unlock;
156530dc78e1SJohan Hedberg 
156630dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1567ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
156830dc78e1SJohan Hedberg 		goto unlock;
156930dc78e1SJohan Hedberg 	}
157030dc78e1SJohan Hedberg 
157130dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
157230dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
157330dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
157430dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
157530dc78e1SJohan Hedberg 	} else {
157630dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
157730dc78e1SJohan Hedberg 	}
157830dc78e1SJohan Hedberg 
157930dc78e1SJohan Hedberg unlock:
158056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
15811da177e4SLinus Torvalds }
15821da177e4SLinus Torvalds 
15831da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
15841da177e4SLinus Torvalds {
158545bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1586a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
15871da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
15881da177e4SLinus Torvalds 
15891da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
15901da177e4SLinus Torvalds 
159145bb4bf0SMarcel Holtmann 	if (!num_rsp)
159245bb4bf0SMarcel Holtmann 		return;
159345bb4bf0SMarcel Holtmann 
15941da177e4SLinus Torvalds 	hci_dev_lock(hdev);
159545bb4bf0SMarcel Holtmann 
1596e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
15973175405bSJohan Hedberg 		bool name_known;
15983175405bSJohan Hedberg 
15991da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16001da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16011da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16021da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16031da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16041da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16051da177e4SLinus Torvalds 		data.rssi		= 0x00;
160641a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16073175405bSJohan Hedberg 
16083175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false);
160948264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
16103175405bSJohan Hedberg 					info->dev_class, 0, !name_known, NULL);
16111da177e4SLinus Torvalds 	}
161245bb4bf0SMarcel Holtmann 
16131da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16141da177e4SLinus Torvalds }
16151da177e4SLinus Torvalds 
1616a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16171da177e4SLinus Torvalds {
1618a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1619a9de9248SMarcel Holtmann 	struct hci_conn *conn;
16201da177e4SLinus Torvalds 
1621a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
162245bb4bf0SMarcel Holtmann 
16231da177e4SLinus Torvalds 	hci_dev_lock(hdev);
162445bb4bf0SMarcel Holtmann 
1625a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16269499237aSMarcel Holtmann 	if (!conn) {
16279499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16289499237aSMarcel Holtmann 			goto unlock;
16299499237aSMarcel Holtmann 
16309499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1631a9de9248SMarcel Holtmann 		if (!conn)
1632a9de9248SMarcel Holtmann 			goto unlock;
163345bb4bf0SMarcel Holtmann 
16349499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16359499237aSMarcel Holtmann 	}
16369499237aSMarcel Holtmann 
1637a9de9248SMarcel Holtmann 	if (!ev->status) {
1638a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1639769be974SMarcel Holtmann 
1640769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1641769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1642769be974SMarcel Holtmann 			hci_conn_hold(conn);
1643052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
164448264f06SJohan Hedberg 			mgmt_connected(hdev, &ev->bdaddr, conn->type,
164548264f06SJohan Hedberg 							conn->dst_type);
1646769be974SMarcel Holtmann 		} else
1647a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1648a9de9248SMarcel Holtmann 
16499eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
16507d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
16517d0db0a3SMarcel Holtmann 
1652a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1653a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1654a9de9248SMarcel Holtmann 
1655a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1656a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1657a9de9248SMarcel Holtmann 
1658a9de9248SMarcel Holtmann 		/* Get remote features */
1659a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1660a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1661a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1662769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1663769be974SMarcel Holtmann 							sizeof(cp), &cp);
166445bb4bf0SMarcel Holtmann 		}
1665a9de9248SMarcel Holtmann 
1666a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1667d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1668a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1669a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1670a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1671a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1672a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1673a9de9248SMarcel Holtmann 		}
167417d5c04cSJohan Hedberg 	} else {
1675a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
167617d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1677744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
167848264f06SJohan Hedberg 						conn->dst_type, ev->status);
167917d5c04cSJohan Hedberg 	}
168045bb4bf0SMarcel Holtmann 
1681e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1682e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
168345bb4bf0SMarcel Holtmann 
1684769be974SMarcel Holtmann 	if (ev->status) {
1685a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1686a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1687c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1688c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1689a9de9248SMarcel Holtmann 
1690a9de9248SMarcel Holtmann unlock:
16911da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1692a9de9248SMarcel Holtmann 
1693a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
16941da177e4SLinus Torvalds }
16951da177e4SLinus Torvalds 
16961da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
16971da177e4SLinus Torvalds {
1698a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
16991da177e4SLinus Torvalds 	int mask = hdev->link_mode;
17001da177e4SLinus Torvalds 
1701a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
17021da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
17031da177e4SLinus Torvalds 
17041da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
17051da177e4SLinus Torvalds 
1706138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1707138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
17081da177e4SLinus Torvalds 		/* Connection accepted */
1709c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17101da177e4SLinus Torvalds 		struct hci_conn *conn;
17111da177e4SLinus Torvalds 
17121da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1713b6a0dc82SMarcel Holtmann 
1714cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1715cc11b9c1SAndrei Emeltchenko 		if (ie)
1716c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1717c7bdd502SMarcel Holtmann 
17181da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17191da177e4SLinus Torvalds 		if (!conn) {
1720cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1721cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1722893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17231da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17241da177e4SLinus Torvalds 				return;
17251da177e4SLinus Torvalds 			}
17261da177e4SLinus Torvalds 		}
1727b6a0dc82SMarcel Holtmann 
17281da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
17291da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1730b6a0dc82SMarcel Holtmann 
17311da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17321da177e4SLinus Torvalds 
1733b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1734b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1735b6a0dc82SMarcel Holtmann 
17361da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17371da177e4SLinus Torvalds 
17381da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17391da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17401da177e4SLinus Torvalds 			else
17411da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17421da177e4SLinus Torvalds 
1743b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1744b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1745b6a0dc82SMarcel Holtmann 		} else {
1746b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1747b6a0dc82SMarcel Holtmann 
1748b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1749a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1750b6a0dc82SMarcel Holtmann 
1751b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1752b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1753b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1754b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1755b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1756b6a0dc82SMarcel Holtmann 
1757b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1758b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1759b6a0dc82SMarcel Holtmann 		}
17601da177e4SLinus Torvalds 	} else {
17611da177e4SLinus Torvalds 		/* Connection rejected */
17621da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
17631da177e4SLinus Torvalds 
17641da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
17659f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1766a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
17671da177e4SLinus Torvalds 	}
17681da177e4SLinus Torvalds }
17691da177e4SLinus Torvalds 
17701da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17711da177e4SLinus Torvalds {
1772a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
177304837f64SMarcel Holtmann 	struct hci_conn *conn;
17741da177e4SLinus Torvalds 
17751da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
17761da177e4SLinus Torvalds 
17771da177e4SLinus Torvalds 	hci_dev_lock(hdev);
17781da177e4SLinus Torvalds 
177904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1780f7520543SJohan Hedberg 	if (!conn)
1781f7520543SJohan Hedberg 		goto unlock;
1782f7520543SJohan Hedberg 
178337d9ef76SJohan Hedberg 	if (ev->status == 0)
17841da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
17857d0db0a3SMarcel Holtmann 
178637d9ef76SJohan Hedberg 	if (conn->type == ACL_LINK || conn->type == LE_LINK) {
178737d9ef76SJohan Hedberg 		if (ev->status != 0)
178837d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
178937d9ef76SJohan Hedberg 		else
179048264f06SJohan Hedberg 			mgmt_disconnected(hdev, &conn->dst, conn->type,
179148264f06SJohan Hedberg 							conn->dst_type);
179237d9ef76SJohan Hedberg 	}
1793f7520543SJohan Hedberg 
179437d9ef76SJohan Hedberg 	if (ev->status == 0) {
17952950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
17961da177e4SLinus Torvalds 		hci_conn_del(conn);
179737d9ef76SJohan Hedberg 	}
17981da177e4SLinus Torvalds 
1799f7520543SJohan Hedberg unlock:
18001da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18011da177e4SLinus Torvalds }
18021da177e4SLinus Torvalds 
1803a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1804a9de9248SMarcel Holtmann {
1805a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1806a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1807a9de9248SMarcel Holtmann 
1808a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1809a9de9248SMarcel Holtmann 
1810a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1811a9de9248SMarcel Holtmann 
1812a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1813d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1814d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1815d7556e20SWaldemar Rymarkiewicz 
1816765c2a96SJohan Hedberg 	if (!ev->status) {
181719f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1818d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1819d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
182019f8def0SWaldemar Rymarkiewicz 		} else {
1821a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1822765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
182319f8def0SWaldemar Rymarkiewicz 		}
18242a611692SJohan Hedberg 	} else {
1825744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
18262a611692SJohan Hedberg 	}
1827a9de9248SMarcel Holtmann 
1828a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
182919f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1830a9de9248SMarcel Holtmann 
1831f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1832d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1833f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1834f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1835f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1836d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1837d7556e20SWaldemar Rymarkiewicz 									&cp);
1838f8558555SMarcel Holtmann 		} else {
1839f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1840f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1841f8558555SMarcel Holtmann 			hci_conn_put(conn);
1842f8558555SMarcel Holtmann 		}
1843052b30b0SMarcel Holtmann 	} else {
1844a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1845a9de9248SMarcel Holtmann 
1846052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1847052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1848052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1849052b30b0SMarcel Holtmann 	}
1850052b30b0SMarcel Holtmann 
1851a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1852a9de9248SMarcel Holtmann 		if (!ev->status) {
1853a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1854f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1855f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1856d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1857d7556e20SWaldemar Rymarkiewicz 									&cp);
1858a9de9248SMarcel Holtmann 		} else {
1859a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1860a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1861a9de9248SMarcel Holtmann 		}
1862a9de9248SMarcel Holtmann 	}
1863a9de9248SMarcel Holtmann 
1864d7556e20SWaldemar Rymarkiewicz unlock:
1865a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1866a9de9248SMarcel Holtmann }
1867a9de9248SMarcel Holtmann 
1868a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1869a9de9248SMarcel Holtmann {
1870127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1871127178d2SJohan Hedberg 	struct hci_conn *conn;
1872127178d2SJohan Hedberg 
1873a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1874a9de9248SMarcel Holtmann 
1875a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1876127178d2SJohan Hedberg 
1877127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1878127178d2SJohan Hedberg 
1879a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
188030dc78e1SJohan Hedberg 		if (ev->status == 0)
1881744cf19eSJohan Hedberg 			mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
1882a88a9652SJohan Hedberg 
188330dc78e1SJohan Hedberg 		hci_resolve_next_name(hdev, &ev->bdaddr);
188430dc78e1SJohan Hedberg 	}
188530dc78e1SJohan Hedberg 
1886127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
188779c6c70cSJohan Hedberg 	if (!conn)
188879c6c70cSJohan Hedberg 		goto unlock;
188979c6c70cSJohan Hedberg 
189079c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
189179c6c70cSJohan Hedberg 		goto unlock;
189279c6c70cSJohan Hedberg 
189379c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1894127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1895127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1896127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1897127178d2SJohan Hedberg 	}
1898127178d2SJohan Hedberg 
189979c6c70cSJohan Hedberg unlock:
1900127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1901a9de9248SMarcel Holtmann }
1902a9de9248SMarcel Holtmann 
1903a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1904a9de9248SMarcel Holtmann {
1905a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1906a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1907a9de9248SMarcel Holtmann 
1908a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1909a9de9248SMarcel Holtmann 
1910a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1911a9de9248SMarcel Holtmann 
1912a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1913a9de9248SMarcel Holtmann 	if (conn) {
1914a9de9248SMarcel Holtmann 		if (!ev->status) {
1915ae293196SMarcel Holtmann 			if (ev->encrypt) {
1916ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1917ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1918a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1919da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1920ae293196SMarcel Holtmann 			} else
1921a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1922a9de9248SMarcel Holtmann 		}
1923a9de9248SMarcel Holtmann 
1924a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1925a9de9248SMarcel Holtmann 
1926f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1927f8558555SMarcel Holtmann 			if (!ev->status)
1928f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1929f8558555SMarcel Holtmann 
1930f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1931f8558555SMarcel Holtmann 			hci_conn_put(conn);
1932f8558555SMarcel Holtmann 		} else
1933a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1934a9de9248SMarcel Holtmann 	}
1935a9de9248SMarcel Holtmann 
1936a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1937a9de9248SMarcel Holtmann }
1938a9de9248SMarcel Holtmann 
1939a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1940a9de9248SMarcel Holtmann {
1941a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1942a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1943a9de9248SMarcel Holtmann 
1944a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1945a9de9248SMarcel Holtmann 
1946a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1947a9de9248SMarcel Holtmann 
1948a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1949a9de9248SMarcel Holtmann 	if (conn) {
1950a9de9248SMarcel Holtmann 		if (!ev->status)
1951a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1952a9de9248SMarcel Holtmann 
1953a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1954a9de9248SMarcel Holtmann 
1955a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1956a9de9248SMarcel Holtmann 	}
1957a9de9248SMarcel Holtmann 
1958a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1959a9de9248SMarcel Holtmann }
1960a9de9248SMarcel Holtmann 
1961a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1962a9de9248SMarcel Holtmann {
1963a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1964a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1965a9de9248SMarcel Holtmann 
1966a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1967a9de9248SMarcel Holtmann 
1968a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1969a9de9248SMarcel Holtmann 
1970a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1971ccd556feSJohan Hedberg 	if (!conn)
1972ccd556feSJohan Hedberg 		goto unlock;
1973ccd556feSJohan Hedberg 
1974769be974SMarcel Holtmann 	if (!ev->status)
1975a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1976a9de9248SMarcel Holtmann 
1977ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1978ccd556feSJohan Hedberg 		goto unlock;
1979ccd556feSJohan Hedberg 
1980ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1981769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1982769be974SMarcel Holtmann 		cp.handle = ev->handle;
1983769be974SMarcel Holtmann 		cp.page = 0x01;
1984ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1985769be974SMarcel Holtmann 							sizeof(cp), &cp);
1986392599b9SJohan Hedberg 		goto unlock;
1987392599b9SJohan Hedberg 	}
1988392599b9SJohan Hedberg 
1989127178d2SJohan Hedberg 	if (!ev->status) {
1990127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1991127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1992127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1993127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1994127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1995127178d2SJohan Hedberg 	}
1996392599b9SJohan Hedberg 
1997127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1998769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1999769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2000769be974SMarcel Holtmann 		hci_conn_put(conn);
2001769be974SMarcel Holtmann 	}
2002769be974SMarcel Holtmann 
2003ccd556feSJohan Hedberg unlock:
2004a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2005a9de9248SMarcel Holtmann }
2006a9de9248SMarcel Holtmann 
2007a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2008a9de9248SMarcel Holtmann {
2009a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2010a9de9248SMarcel Holtmann }
2011a9de9248SMarcel Holtmann 
2012a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2013a9de9248SMarcel Holtmann {
2014a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2015a9de9248SMarcel Holtmann }
2016a9de9248SMarcel Holtmann 
2017a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2018a9de9248SMarcel Holtmann {
2019a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2020a9de9248SMarcel Holtmann 	__u16 opcode;
2021a9de9248SMarcel Holtmann 
2022a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2023a9de9248SMarcel Holtmann 
2024a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2025a9de9248SMarcel Holtmann 
2026a9de9248SMarcel Holtmann 	switch (opcode) {
2027a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2028a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2029a9de9248SMarcel Holtmann 		break;
2030a9de9248SMarcel Holtmann 
2031a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2032a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2033a9de9248SMarcel Holtmann 		break;
2034a9de9248SMarcel Holtmann 
2035a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2036a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2037a9de9248SMarcel Holtmann 		break;
2038a9de9248SMarcel Holtmann 
2039a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2040a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2041a9de9248SMarcel Holtmann 		break;
2042a9de9248SMarcel Holtmann 
2043e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2044e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2045e4e8e37cSMarcel Holtmann 		break;
2046e4e8e37cSMarcel Holtmann 
2047a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2048a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2049a9de9248SMarcel Holtmann 		break;
2050a9de9248SMarcel Holtmann 
2051e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2052e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2053e4e8e37cSMarcel Holtmann 		break;
2054e4e8e37cSMarcel Holtmann 
2055e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2056e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2057e4e8e37cSMarcel Holtmann 		break;
2058e4e8e37cSMarcel Holtmann 
2059a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2060a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2061a9de9248SMarcel Holtmann 		break;
2062a9de9248SMarcel Holtmann 
2063a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2064a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2065a9de9248SMarcel Holtmann 		break;
2066a9de9248SMarcel Holtmann 
2067a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2068a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2069a9de9248SMarcel Holtmann 		break;
2070a9de9248SMarcel Holtmann 
2071a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2072a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2073a9de9248SMarcel Holtmann 		break;
2074a9de9248SMarcel Holtmann 
2075a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2076a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2077a9de9248SMarcel Holtmann 		break;
2078a9de9248SMarcel Holtmann 
2079a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2080a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2081a9de9248SMarcel Holtmann 		break;
2082a9de9248SMarcel Holtmann 
2083a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2084a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2085a9de9248SMarcel Holtmann 		break;
2086a9de9248SMarcel Holtmann 
2087a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2088a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2089a9de9248SMarcel Holtmann 		break;
2090a9de9248SMarcel Holtmann 
2091a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2092a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2093a9de9248SMarcel Holtmann 		break;
2094a9de9248SMarcel Holtmann 
2095a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2096a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2097a9de9248SMarcel Holtmann 		break;
2098a9de9248SMarcel Holtmann 
2099a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2100a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2101a9de9248SMarcel Holtmann 		break;
2102a9de9248SMarcel Holtmann 
2103333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
2104333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
2105333140b5SMarcel Holtmann 		break;
2106333140b5SMarcel Holtmann 
2107333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2108333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2109333140b5SMarcel Holtmann 		break;
2110333140b5SMarcel Holtmann 
2111a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2112a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2113a9de9248SMarcel Holtmann 		break;
2114a9de9248SMarcel Holtmann 
2115a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2116a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2117a9de9248SMarcel Holtmann 		break;
2118a9de9248SMarcel Holtmann 
2119a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2120a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2121a9de9248SMarcel Holtmann 		break;
2122a9de9248SMarcel Holtmann 
2123971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2124971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2125971e3a4bSAndre Guedes 		break;
2126971e3a4bSAndre Guedes 
2127a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2128a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2129a9de9248SMarcel Holtmann 		break;
2130a9de9248SMarcel Holtmann 
2131a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2132a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2133a9de9248SMarcel Holtmann 		break;
2134a9de9248SMarcel Holtmann 
2135350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2136350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2137350ee4cfSAndrei Emeltchenko 		break;
2138350ee4cfSAndrei Emeltchenko 
213923bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
214023bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
214123bb5763SJohan Hedberg 		break;
214223bb5763SJohan Hedberg 
21431e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
21441e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
21451e89cffbSAndrei Emeltchenko 		break;
21461e89cffbSAndrei Emeltchenko 
2147928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2148928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2149928abaa7SAndrei Emeltchenko 		break;
2150928abaa7SAndrei Emeltchenko 
2151b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2152b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2153b0916ea0SJohan Hedberg 		break;
2154b0916ea0SJohan Hedberg 
2155d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2156d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2157d5859e22SJohan Hedberg 		break;
2158d5859e22SJohan Hedberg 
2159d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2160d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2161d5859e22SJohan Hedberg 		break;
2162d5859e22SJohan Hedberg 
2163d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2164d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2165d5859e22SJohan Hedberg 		break;
2166d5859e22SJohan Hedberg 
2167d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2168d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2169d5859e22SJohan Hedberg 		break;
2170d5859e22SJohan Hedberg 
2171980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2172980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2173980e1a53SJohan Hedberg 		break;
2174980e1a53SJohan Hedberg 
2175980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2176980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2177980e1a53SJohan Hedberg 		break;
2178980e1a53SJohan Hedberg 
2179c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2180c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2181c35938b2SSzymon Janc 		break;
2182c35938b2SSzymon Janc 
21836ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
21846ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
21856ed58ec5SVille Tervo 		break;
21866ed58ec5SVille Tervo 
2187a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2188a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2189a5c29683SJohan Hedberg 		break;
2190a5c29683SJohan Hedberg 
2191a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2192a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2193a5c29683SJohan Hedberg 		break;
2194a5c29683SJohan Hedberg 
21951143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
21961143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
21971143d458SBrian Gix 		break;
21981143d458SBrian Gix 
21991143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
22001143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
220107f7fa5dSAndre Guedes 
220207f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
220307f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
22041143d458SBrian Gix 		break;
22051143d458SBrian Gix 
2206eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2207eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2208eb9d91f5SAndre Guedes 		break;
2209eb9d91f5SAndre Guedes 
2210a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2211a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2212a7a595f6SVinicius Costa Gomes 		break;
2213a7a595f6SVinicius Costa Gomes 
2214a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2215a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2216a7a595f6SVinicius Costa Gomes 		break;
2217a7a595f6SVinicius Costa Gomes 
2218f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2219f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2220f9b49306SAndre Guedes 		break;
2221f9b49306SAndre Guedes 
2222a9de9248SMarcel Holtmann 	default:
2223a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2224a9de9248SMarcel Holtmann 		break;
2225a9de9248SMarcel Holtmann 	}
2226a9de9248SMarcel Holtmann 
22276bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
22286bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
22296bd32326SVille Tervo 
2230a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2231a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2232a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2233c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2234a9de9248SMarcel Holtmann 	}
2235a9de9248SMarcel Holtmann }
2236a9de9248SMarcel Holtmann 
2237a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2238a9de9248SMarcel Holtmann {
2239a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2240a9de9248SMarcel Holtmann 	__u16 opcode;
2241a9de9248SMarcel Holtmann 
2242a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2243a9de9248SMarcel Holtmann 
2244a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2245a9de9248SMarcel Holtmann 
2246a9de9248SMarcel Holtmann 	switch (opcode) {
2247a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2248a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2249a9de9248SMarcel Holtmann 		break;
2250a9de9248SMarcel Holtmann 
2251a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2252a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2253a9de9248SMarcel Holtmann 		break;
2254a9de9248SMarcel Holtmann 
2255a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2256a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2257a9de9248SMarcel Holtmann 		break;
2258a9de9248SMarcel Holtmann 
2259f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2260f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2261f8558555SMarcel Holtmann 		break;
2262f8558555SMarcel Holtmann 
2263f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2264f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2265f8558555SMarcel Holtmann 		break;
2266f8558555SMarcel Holtmann 
2267a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2268a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2269a9de9248SMarcel Holtmann 		break;
2270a9de9248SMarcel Holtmann 
2271769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2272769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2273769be974SMarcel Holtmann 		break;
2274769be974SMarcel Holtmann 
2275769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2276769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2277769be974SMarcel Holtmann 		break;
2278769be974SMarcel Holtmann 
2279a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2280a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2281a9de9248SMarcel Holtmann 		break;
2282a9de9248SMarcel Holtmann 
2283a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2284a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2285a9de9248SMarcel Holtmann 		break;
2286a9de9248SMarcel Holtmann 
2287a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2288a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2289a9de9248SMarcel Holtmann 		break;
2290a9de9248SMarcel Holtmann 
22918962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
22928962ee74SJohan Hedberg 		if (ev->status != 0)
229337d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
22948962ee74SJohan Hedberg 		break;
22958962ee74SJohan Hedberg 
2296fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2297fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2298fcd89c09SVille Tervo 		break;
2299fcd89c09SVille Tervo 
2300a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2301a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2302a7a595f6SVinicius Costa Gomes 		break;
2303a7a595f6SVinicius Costa Gomes 
2304a9de9248SMarcel Holtmann 	default:
2305a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2306a9de9248SMarcel Holtmann 		break;
2307a9de9248SMarcel Holtmann 	}
2308a9de9248SMarcel Holtmann 
23096bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23106bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23116bd32326SVille Tervo 
231210572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2313a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2314a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2315c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2316a9de9248SMarcel Holtmann 	}
2317a9de9248SMarcel Holtmann }
2318a9de9248SMarcel Holtmann 
2319a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2320a9de9248SMarcel Holtmann {
2321a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2322a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2323a9de9248SMarcel Holtmann 
2324a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2325a9de9248SMarcel Holtmann 
2326a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2327a9de9248SMarcel Holtmann 
2328a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2329a9de9248SMarcel Holtmann 	if (conn) {
2330a9de9248SMarcel Holtmann 		if (!ev->status) {
2331a9de9248SMarcel Holtmann 			if (ev->role)
2332a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2333a9de9248SMarcel Holtmann 			else
2334a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2335a9de9248SMarcel Holtmann 		}
2336a9de9248SMarcel Holtmann 
2337a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2338a9de9248SMarcel Holtmann 
2339a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2340a9de9248SMarcel Holtmann 	}
2341a9de9248SMarcel Holtmann 
2342a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2343a9de9248SMarcel Holtmann }
2344a9de9248SMarcel Holtmann 
23451da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
23461da177e4SLinus Torvalds {
2347a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
23481da177e4SLinus Torvalds 	int i;
23491da177e4SLinus Torvalds 
235032ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
235132ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
235232ac5b9bSAndrei Emeltchenko 		return;
235332ac5b9bSAndrei Emeltchenko 	}
235432ac5b9bSAndrei Emeltchenko 
2355c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2356c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
23571da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
23581da177e4SLinus Torvalds 		return;
23591da177e4SLinus Torvalds 	}
23601da177e4SLinus Torvalds 
2361c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2362c5993de8SAndrei Emeltchenko 
2363613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2364613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
23651da177e4SLinus Torvalds 		struct hci_conn *conn;
23661da177e4SLinus Torvalds 		__u16  handle, count;
23671da177e4SLinus Torvalds 
2368613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2369613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
23701da177e4SLinus Torvalds 
23711da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2372f4280918SAndrei Emeltchenko 		if (!conn)
2373f4280918SAndrei Emeltchenko 			continue;
2374f4280918SAndrei Emeltchenko 
23751da177e4SLinus Torvalds 		conn->sent -= count;
23761da177e4SLinus Torvalds 
2377f4280918SAndrei Emeltchenko 		switch (conn->type) {
2378f4280918SAndrei Emeltchenko 		case ACL_LINK:
237970f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
238070f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
23811da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2382f4280918SAndrei Emeltchenko 			break;
2383f4280918SAndrei Emeltchenko 
2384f4280918SAndrei Emeltchenko 		case LE_LINK:
23856ed58ec5SVille Tervo 			if (hdev->le_pkts) {
23866ed58ec5SVille Tervo 				hdev->le_cnt += count;
23876ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
23886ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
23896ed58ec5SVille Tervo 			} else {
23906ed58ec5SVille Tervo 				hdev->acl_cnt += count;
23916ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
23926ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
23936ed58ec5SVille Tervo 			}
2394f4280918SAndrei Emeltchenko 			break;
2395f4280918SAndrei Emeltchenko 
2396f4280918SAndrei Emeltchenko 		case SCO_LINK:
239770f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
239870f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
23995b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2400f4280918SAndrei Emeltchenko 			break;
2401f4280918SAndrei Emeltchenko 
2402f4280918SAndrei Emeltchenko 		default:
2403f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2404f4280918SAndrei Emeltchenko 			break;
24051da177e4SLinus Torvalds 		}
24061da177e4SLinus Torvalds 	}
2407a9de9248SMarcel Holtmann 
24083eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
24091da177e4SLinus Torvalds }
24101da177e4SLinus Torvalds 
241125e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
241225e89e99SAndrei Emeltchenko 							struct sk_buff *skb)
241325e89e99SAndrei Emeltchenko {
241425e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
241525e89e99SAndrei Emeltchenko 	int i;
241625e89e99SAndrei Emeltchenko 
241725e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
241825e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
241925e89e99SAndrei Emeltchenko 		return;
242025e89e99SAndrei Emeltchenko 	}
242125e89e99SAndrei Emeltchenko 
242225e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
242325e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
242425e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
242525e89e99SAndrei Emeltchenko 		return;
242625e89e99SAndrei Emeltchenko 	}
242725e89e99SAndrei Emeltchenko 
242825e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
242925e89e99SAndrei Emeltchenko 								ev->num_hndl);
243025e89e99SAndrei Emeltchenko 
243125e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
243225e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
243325e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
243425e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
243525e89e99SAndrei Emeltchenko 
243625e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
243725e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
243825e89e99SAndrei Emeltchenko 
243925e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
244025e89e99SAndrei Emeltchenko 		if (!conn)
244125e89e99SAndrei Emeltchenko 			continue;
244225e89e99SAndrei Emeltchenko 
244325e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
244425e89e99SAndrei Emeltchenko 
244525e89e99SAndrei Emeltchenko 		switch (conn->type) {
244625e89e99SAndrei Emeltchenko 		case ACL_LINK:
244725e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
244825e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
244925e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
245025e89e99SAndrei Emeltchenko 			break;
245125e89e99SAndrei Emeltchenko 
245225e89e99SAndrei Emeltchenko 		default:
245325e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
245425e89e99SAndrei Emeltchenko 			break;
245525e89e99SAndrei Emeltchenko 		}
245625e89e99SAndrei Emeltchenko 	}
245725e89e99SAndrei Emeltchenko 
245825e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
245925e89e99SAndrei Emeltchenko }
246025e89e99SAndrei Emeltchenko 
246104837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
24621da177e4SLinus Torvalds {
2463a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
246404837f64SMarcel Holtmann 	struct hci_conn *conn;
24651da177e4SLinus Torvalds 
24661da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
24671da177e4SLinus Torvalds 
24681da177e4SLinus Torvalds 	hci_dev_lock(hdev);
24691da177e4SLinus Torvalds 
247004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
247104837f64SMarcel Holtmann 	if (conn) {
247204837f64SMarcel Holtmann 		conn->mode = ev->mode;
247304837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
247404837f64SMarcel Holtmann 
247504837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
247604837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
247704837f64SMarcel Holtmann 				conn->power_save = 1;
247804837f64SMarcel Holtmann 			else
247904837f64SMarcel Holtmann 				conn->power_save = 0;
248004837f64SMarcel Holtmann 		}
2481e73439d8SMarcel Holtmann 
2482e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2483e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
248404837f64SMarcel Holtmann 	}
248504837f64SMarcel Holtmann 
248604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
248704837f64SMarcel Holtmann }
248804837f64SMarcel Holtmann 
24891da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
24901da177e4SLinus Torvalds {
2491052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2492052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2493052b30b0SMarcel Holtmann 
2494a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2495052b30b0SMarcel Holtmann 
2496052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2497052b30b0SMarcel Holtmann 
2498052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2499b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2500b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2501b6f98044SWaldemar Rymarkiewicz 
2502b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2503052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2504052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2505052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2506052b30b0SMarcel Holtmann 	}
2507052b30b0SMarcel Holtmann 
2508a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
250903b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
251003b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2511a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2512a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2513a770bb5aSWaldemar Rymarkiewicz 
2514a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2515a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2516a770bb5aSWaldemar Rymarkiewicz 		else
2517a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2518a770bb5aSWaldemar Rymarkiewicz 
2519744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2520a770bb5aSWaldemar Rymarkiewicz 	}
2521980e1a53SJohan Hedberg 
2522b6f98044SWaldemar Rymarkiewicz unlock:
2523052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
25241da177e4SLinus Torvalds }
25251da177e4SLinus Torvalds 
25261da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25271da177e4SLinus Torvalds {
252855ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
252955ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
253055ed8ca1SJohan Hedberg 	struct hci_conn *conn;
253155ed8ca1SJohan Hedberg 	struct link_key *key;
253255ed8ca1SJohan Hedberg 
2533a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
253455ed8ca1SJohan Hedberg 
2535a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
253655ed8ca1SJohan Hedberg 		return;
253755ed8ca1SJohan Hedberg 
253855ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
253955ed8ca1SJohan Hedberg 
254055ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
254155ed8ca1SJohan Hedberg 	if (!key) {
254255ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
254355ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
254455ed8ca1SJohan Hedberg 		goto not_found;
254555ed8ca1SJohan Hedberg 	}
254655ed8ca1SJohan Hedberg 
254755ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
254855ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
254955ed8ca1SJohan Hedberg 
2550a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2551b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
255255ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
255355ed8ca1SJohan Hedberg 		goto not_found;
255455ed8ca1SJohan Hedberg 	}
255555ed8ca1SJohan Hedberg 
255655ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
255760b83f57SWaldemar Rymarkiewicz 	if (conn) {
255860b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
255960b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
256060b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
256155ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
256255ed8ca1SJohan Hedberg 			goto not_found;
256355ed8ca1SJohan Hedberg 		}
256455ed8ca1SJohan Hedberg 
256560b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
256660b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
256760b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
256860b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
256960b83f57SWaldemar Rymarkiewicz 			goto not_found;
257060b83f57SWaldemar Rymarkiewicz 		}
257160b83f57SWaldemar Rymarkiewicz 
257260b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
257360b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
257460b83f57SWaldemar Rymarkiewicz 	}
257560b83f57SWaldemar Rymarkiewicz 
257655ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
257755ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
257855ed8ca1SJohan Hedberg 
257955ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
258055ed8ca1SJohan Hedberg 
258155ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
258255ed8ca1SJohan Hedberg 
258355ed8ca1SJohan Hedberg 	return;
258455ed8ca1SJohan Hedberg 
258555ed8ca1SJohan Hedberg not_found:
258655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
258755ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
25881da177e4SLinus Torvalds }
25891da177e4SLinus Torvalds 
25901da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
25911da177e4SLinus Torvalds {
2592052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2593052b30b0SMarcel Holtmann 	struct hci_conn *conn;
259455ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2595052b30b0SMarcel Holtmann 
2596a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2597052b30b0SMarcel Holtmann 
2598052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2599052b30b0SMarcel Holtmann 
2600052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2601052b30b0SMarcel Holtmann 	if (conn) {
2602052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2603052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2604980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
260513d39315SWaldemar Rymarkiewicz 
260613d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
260713d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
260813d39315SWaldemar Rymarkiewicz 
2609052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2610052b30b0SMarcel Holtmann 	}
2611052b30b0SMarcel Holtmann 
2612a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2613d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
261455ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
261555ed8ca1SJohan Hedberg 
2616052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26171da177e4SLinus Torvalds }
26181da177e4SLinus Torvalds 
261904837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
262004837f64SMarcel Holtmann {
2621a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
262204837f64SMarcel Holtmann 	struct hci_conn *conn;
262304837f64SMarcel Holtmann 
262404837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
262504837f64SMarcel Holtmann 
262604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
262704837f64SMarcel Holtmann 
262804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
26291da177e4SLinus Torvalds 	if (conn && !ev->status) {
26301da177e4SLinus Torvalds 		struct inquiry_entry *ie;
26311da177e4SLinus Torvalds 
2632cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2633cc11b9c1SAndrei Emeltchenko 		if (ie) {
26341da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
26351da177e4SLinus Torvalds 			ie->timestamp = jiffies;
26361da177e4SLinus Torvalds 		}
26371da177e4SLinus Torvalds 	}
26381da177e4SLinus Torvalds 
26391da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
26401da177e4SLinus Torvalds }
26411da177e4SLinus Torvalds 
2642a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2643a8746417SMarcel Holtmann {
2644a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2645a8746417SMarcel Holtmann 	struct hci_conn *conn;
2646a8746417SMarcel Holtmann 
2647a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2648a8746417SMarcel Holtmann 
2649a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2650a8746417SMarcel Holtmann 
2651a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2652a8746417SMarcel Holtmann 	if (conn && !ev->status)
2653a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2654a8746417SMarcel Holtmann 
2655a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2656a8746417SMarcel Holtmann }
2657a8746417SMarcel Holtmann 
265885a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
265985a1e930SMarcel Holtmann {
2660a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
266185a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
266285a1e930SMarcel Holtmann 
266385a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
266485a1e930SMarcel Holtmann 
266585a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
266685a1e930SMarcel Holtmann 
2667cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2668cc11b9c1SAndrei Emeltchenko 	if (ie) {
266985a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
267085a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
267185a1e930SMarcel Holtmann 	}
267285a1e930SMarcel Holtmann 
267385a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
267485a1e930SMarcel Holtmann }
267585a1e930SMarcel Holtmann 
2676a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2677a9de9248SMarcel Holtmann {
2678a9de9248SMarcel Holtmann 	struct inquiry_data data;
2679a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
26803175405bSJohan Hedberg 	bool name_known;
2681a9de9248SMarcel Holtmann 
2682a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2683a9de9248SMarcel Holtmann 
2684a9de9248SMarcel Holtmann 	if (!num_rsp)
2685a9de9248SMarcel Holtmann 		return;
2686a9de9248SMarcel Holtmann 
2687a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2688a9de9248SMarcel Holtmann 
2689a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2690138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2691138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2692a9de9248SMarcel Holtmann 
2693e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2694a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2695a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2696a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2697a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2698a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2699a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2700a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
270141a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27023175405bSJohan Hedberg 
27033175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27043175405bSJohan Hedberg 								false);
270548264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2706e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27073175405bSJohan Hedberg 						!name_known, NULL);
2708a9de9248SMarcel Holtmann 		}
2709a9de9248SMarcel Holtmann 	} else {
2710a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2711a9de9248SMarcel Holtmann 
2712e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2713a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2714a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2715a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2716a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2717a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2718a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2719a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
272041a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27213175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27223175405bSJohan Hedberg 								false);
272348264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2724e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27253175405bSJohan Hedberg 						!name_known, NULL);
2726a9de9248SMarcel Holtmann 		}
2727a9de9248SMarcel Holtmann 	}
2728a9de9248SMarcel Holtmann 
2729a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2730a9de9248SMarcel Holtmann }
2731a9de9248SMarcel Holtmann 
2732a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2733a9de9248SMarcel Holtmann {
273441a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
273541a96212SMarcel Holtmann 	struct hci_conn *conn;
273641a96212SMarcel Holtmann 
2737a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
273841a96212SMarcel Holtmann 
273941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
274041a96212SMarcel Holtmann 
274141a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2742ccd556feSJohan Hedberg 	if (!conn)
2743ccd556feSJohan Hedberg 		goto unlock;
2744ccd556feSJohan Hedberg 
2745769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
274641a96212SMarcel Holtmann 		struct inquiry_entry *ie;
274741a96212SMarcel Holtmann 
2748cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2749cc11b9c1SAndrei Emeltchenko 		if (ie)
275041a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
275141a96212SMarcel Holtmann 
275241a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
275341a96212SMarcel Holtmann 	}
275441a96212SMarcel Holtmann 
2755ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2756ccd556feSJohan Hedberg 		goto unlock;
2757ccd556feSJohan Hedberg 
2758127178d2SJohan Hedberg 	if (!ev->status) {
2759127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2760127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2761127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2762127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2763127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2764127178d2SJohan Hedberg 	}
2765392599b9SJohan Hedberg 
2766127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2767769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2768769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2769769be974SMarcel Holtmann 		hci_conn_put(conn);
2770769be974SMarcel Holtmann 	}
2771769be974SMarcel Holtmann 
2772ccd556feSJohan Hedberg unlock:
277341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2774a9de9248SMarcel Holtmann }
2775a9de9248SMarcel Holtmann 
2776a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2777a9de9248SMarcel Holtmann {
2778b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2779b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2780b6a0dc82SMarcel Holtmann 
2781b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2782b6a0dc82SMarcel Holtmann 
2783b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2784b6a0dc82SMarcel Holtmann 
2785b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
27869dc0a3afSMarcel Holtmann 	if (!conn) {
27879dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
27889dc0a3afSMarcel Holtmann 			goto unlock;
27899dc0a3afSMarcel Holtmann 
27909dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2791b6a0dc82SMarcel Holtmann 		if (!conn)
2792b6a0dc82SMarcel Holtmann 			goto unlock;
2793b6a0dc82SMarcel Holtmann 
27949dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
27959dc0a3afSMarcel Holtmann 	}
27969dc0a3afSMarcel Holtmann 
2797732547f9SMarcel Holtmann 	switch (ev->status) {
2798732547f9SMarcel Holtmann 	case 0x00:
2799732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2800732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2801732547f9SMarcel Holtmann 
28029eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2803732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2804732547f9SMarcel Holtmann 		break;
2805732547f9SMarcel Holtmann 
2806705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2807732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
28081038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2809732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2810732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2811efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2812efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2813efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2814efc7688bSMarcel Holtmann 			goto unlock;
2815efc7688bSMarcel Holtmann 		}
2816732547f9SMarcel Holtmann 		/* fall through */
2817efc7688bSMarcel Holtmann 
2818732547f9SMarcel Holtmann 	default:
2819b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2820732547f9SMarcel Holtmann 		break;
2821732547f9SMarcel Holtmann 	}
2822b6a0dc82SMarcel Holtmann 
2823b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2824b6a0dc82SMarcel Holtmann 	if (ev->status)
2825b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2826b6a0dc82SMarcel Holtmann 
2827b6a0dc82SMarcel Holtmann unlock:
2828b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2829a9de9248SMarcel Holtmann }
2830a9de9248SMarcel Holtmann 
2831a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2832a9de9248SMarcel Holtmann {
2833a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2834a9de9248SMarcel Holtmann }
2835a9de9248SMarcel Holtmann 
283604837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
283704837f64SMarcel Holtmann {
2838a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
283904837f64SMarcel Holtmann 
284004837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
284104837f64SMarcel Holtmann }
284204837f64SMarcel Holtmann 
2843561aafbcSJohan Hedberg static inline bool eir_has_complete_name(u8 *data, size_t data_len)
2844561aafbcSJohan Hedberg {
2845561aafbcSJohan Hedberg 	u8 field_len;
2846561aafbcSJohan Hedberg 	size_t parsed;
2847561aafbcSJohan Hedberg 
2848561aafbcSJohan Hedberg 	for (parsed = 0; parsed < data_len - 1; parsed += field_len) {
2849561aafbcSJohan Hedberg 		field_len = data[0];
2850561aafbcSJohan Hedberg 
2851561aafbcSJohan Hedberg 		if (field_len == 0)
2852561aafbcSJohan Hedberg 			break;
2853561aafbcSJohan Hedberg 
2854561aafbcSJohan Hedberg 		parsed += field_len + 1;
2855561aafbcSJohan Hedberg 
2856561aafbcSJohan Hedberg 		if (parsed > data_len)
2857561aafbcSJohan Hedberg 			break;
2858561aafbcSJohan Hedberg 
2859561aafbcSJohan Hedberg 		if (data[1] == EIR_NAME_COMPLETE)
2860561aafbcSJohan Hedberg 			return true;
2861561aafbcSJohan Hedberg 
2862561aafbcSJohan Hedberg 		data += field_len + 1;
2863561aafbcSJohan Hedberg 	}
2864561aafbcSJohan Hedberg 
2865561aafbcSJohan Hedberg 	return false;
2866561aafbcSJohan Hedberg }
2867561aafbcSJohan Hedberg 
2868a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2869a9de9248SMarcel Holtmann {
2870a9de9248SMarcel Holtmann 	struct inquiry_data data;
2871a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2872a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2873a9de9248SMarcel Holtmann 
2874a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2875a9de9248SMarcel Holtmann 
2876a9de9248SMarcel Holtmann 	if (!num_rsp)
2877a9de9248SMarcel Holtmann 		return;
2878a9de9248SMarcel Holtmann 
2879a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2880a9de9248SMarcel Holtmann 
2881e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2882561aafbcSJohan Hedberg 		bool name_known;
2883561aafbcSJohan Hedberg 
2884a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2885a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2886a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2887a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2888a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2889a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2890a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
289141a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2892561aafbcSJohan Hedberg 
2893a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
2894561aafbcSJohan Hedberg 			name_known = eir_has_complete_name(info->data,
2895561aafbcSJohan Hedberg 							sizeof(info->data));
2896561aafbcSJohan Hedberg 		else
2897561aafbcSJohan Hedberg 			name_known = true;
2898561aafbcSJohan Hedberg 
28993175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known);
290048264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2901561aafbcSJohan Hedberg 						info->dev_class, info->rssi,
2902561aafbcSJohan Hedberg 						!name_known, info->data);
2903a9de9248SMarcel Holtmann 	}
2904a9de9248SMarcel Holtmann 
2905a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2906a9de9248SMarcel Holtmann }
2907a9de9248SMarcel Holtmann 
290817fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
290917fa4b9dSJohan Hedberg {
291017fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
291117fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
291217fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
291317fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
291417fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
291517fa4b9dSJohan Hedberg 			return 0x02;
291617fa4b9dSJohan Hedberg 		else
291717fa4b9dSJohan Hedberg 			return 0x03;
291817fa4b9dSJohan Hedberg 	}
291917fa4b9dSJohan Hedberg 
292017fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
292117fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
292258797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
292317fa4b9dSJohan Hedberg 
292417fa4b9dSJohan Hedberg 	return conn->auth_type;
292517fa4b9dSJohan Hedberg }
292617fa4b9dSJohan Hedberg 
29270493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29280493684eSMarcel Holtmann {
29290493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
29300493684eSMarcel Holtmann 	struct hci_conn *conn;
29310493684eSMarcel Holtmann 
29320493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
29330493684eSMarcel Holtmann 
29340493684eSMarcel Holtmann 	hci_dev_lock(hdev);
29350493684eSMarcel Holtmann 
29360493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
293703b555e1SJohan Hedberg 	if (!conn)
293803b555e1SJohan Hedberg 		goto unlock;
293903b555e1SJohan Hedberg 
29400493684eSMarcel Holtmann 	hci_conn_hold(conn);
29410493684eSMarcel Holtmann 
2942a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
294303b555e1SJohan Hedberg 		goto unlock;
294403b555e1SJohan Hedberg 
2945a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
294603b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
294717fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
294817fa4b9dSJohan Hedberg 
294917fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
295017fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
29517cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
29527cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
295317fa4b9dSJohan Hedberg 
2954ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2955ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2956ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2957ce85ee13SSzymon Janc 		else
2958ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2959ce85ee13SSzymon Janc 
296017fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
296117fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
296203b555e1SJohan Hedberg 	} else {
296303b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
296403b555e1SJohan Hedberg 
296503b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
29669f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
296703b555e1SJohan Hedberg 
296803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
296903b555e1SJohan Hedberg 							sizeof(cp), &cp);
297003b555e1SJohan Hedberg 	}
297103b555e1SJohan Hedberg 
297203b555e1SJohan Hedberg unlock:
297303b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
297403b555e1SJohan Hedberg }
297503b555e1SJohan Hedberg 
297603b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
297703b555e1SJohan Hedberg {
297803b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
297903b555e1SJohan Hedberg 	struct hci_conn *conn;
298003b555e1SJohan Hedberg 
298103b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
298203b555e1SJohan Hedberg 
298303b555e1SJohan Hedberg 	hci_dev_lock(hdev);
298403b555e1SJohan Hedberg 
298503b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
298603b555e1SJohan Hedberg 	if (!conn)
298703b555e1SJohan Hedberg 		goto unlock;
298803b555e1SJohan Hedberg 
298903b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
299003b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
299103b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
299203b555e1SJohan Hedberg 
299303b555e1SJohan Hedberg unlock:
29940493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
29950493684eSMarcel Holtmann }
29960493684eSMarcel Holtmann 
2997a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2998a5c29683SJohan Hedberg 							struct sk_buff *skb)
2999a5c29683SJohan Hedberg {
3000a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
300155bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
30027a828908SJohan Hedberg 	struct hci_conn *conn;
3003a5c29683SJohan Hedberg 
3004a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3005a5c29683SJohan Hedberg 
3006a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3007a5c29683SJohan Hedberg 
3008a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
30097a828908SJohan Hedberg 		goto unlock;
30107a828908SJohan Hedberg 
30117a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
30127a828908SJohan Hedberg 	if (!conn)
30137a828908SJohan Hedberg 		goto unlock;
30147a828908SJohan Hedberg 
30157a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
30167a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
30177a828908SJohan Hedberg 
30187a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
30197a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
30207a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
30217a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
30227a828908SJohan Hedberg 	 * bit set. */
30237a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
30247a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
30257a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
30267a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
30277a828908SJohan Hedberg 		goto unlock;
30287a828908SJohan Hedberg 	}
30297a828908SJohan Hedberg 
30307a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
30317a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
30327a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
303355bc1a37SJohan Hedberg 
303455bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
303555bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
303655bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
303755bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
303855bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
303955bc1a37SJohan Hedberg 			confirm_hint = 1;
304055bc1a37SJohan Hedberg 			goto confirm;
304155bc1a37SJohan Hedberg 		}
304255bc1a37SJohan Hedberg 
30439f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
30449f61656aSJohan Hedberg 						hdev->auto_accept_delay);
30459f61656aSJohan Hedberg 
30469f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
30479f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
30489f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
30499f61656aSJohan Hedberg 			goto unlock;
30509f61656aSJohan Hedberg 		}
30519f61656aSJohan Hedberg 
30527a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
30537a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
30547a828908SJohan Hedberg 		goto unlock;
30557a828908SJohan Hedberg 	}
30567a828908SJohan Hedberg 
305755bc1a37SJohan Hedberg confirm:
3058744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
305955bc1a37SJohan Hedberg 								confirm_hint);
3060a5c29683SJohan Hedberg 
30617a828908SJohan Hedberg unlock:
3062a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3063a5c29683SJohan Hedberg }
3064a5c29683SJohan Hedberg 
30651143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
30661143d458SBrian Gix 							struct sk_buff *skb)
30671143d458SBrian Gix {
30681143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
30691143d458SBrian Gix 
30701143d458SBrian Gix 	BT_DBG("%s", hdev->name);
30711143d458SBrian Gix 
30721143d458SBrian Gix 	hci_dev_lock(hdev);
30731143d458SBrian Gix 
3074a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
30751143d458SBrian Gix 		mgmt_user_passkey_request(hdev, &ev->bdaddr);
30761143d458SBrian Gix 
30771143d458SBrian Gix 	hci_dev_unlock(hdev);
30781143d458SBrian Gix }
30791143d458SBrian Gix 
30800493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
30810493684eSMarcel Holtmann {
30820493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
30830493684eSMarcel Holtmann 	struct hci_conn *conn;
30840493684eSMarcel Holtmann 
30850493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30860493684eSMarcel Holtmann 
30870493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30880493684eSMarcel Holtmann 
30890493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
30902a611692SJohan Hedberg 	if (!conn)
30912a611692SJohan Hedberg 		goto unlock;
30922a611692SJohan Hedberg 
30932a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
30942a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
30952a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
30962a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
30972a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
30982a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
3099744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
31002a611692SJohan Hedberg 
31010493684eSMarcel Holtmann 	hci_conn_put(conn);
31020493684eSMarcel Holtmann 
31032a611692SJohan Hedberg unlock:
31040493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31050493684eSMarcel Holtmann }
31060493684eSMarcel Holtmann 
310741a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
310841a96212SMarcel Holtmann {
310941a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
311041a96212SMarcel Holtmann 	struct inquiry_entry *ie;
311141a96212SMarcel Holtmann 
311241a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
311341a96212SMarcel Holtmann 
311441a96212SMarcel Holtmann 	hci_dev_lock(hdev);
311541a96212SMarcel Holtmann 
3116cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3117cc11b9c1SAndrei Emeltchenko 	if (ie)
311841a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
311941a96212SMarcel Holtmann 
312041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
312141a96212SMarcel Holtmann }
312241a96212SMarcel Holtmann 
31232763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
31242763eda6SSzymon Janc 							struct sk_buff *skb)
31252763eda6SSzymon Janc {
31262763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
31272763eda6SSzymon Janc 	struct oob_data *data;
31282763eda6SSzymon Janc 
31292763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
31302763eda6SSzymon Janc 
31312763eda6SSzymon Janc 	hci_dev_lock(hdev);
31322763eda6SSzymon Janc 
3133a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3134e1ba1f15SSzymon Janc 		goto unlock;
3135e1ba1f15SSzymon Janc 
31362763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
31372763eda6SSzymon Janc 	if (data) {
31382763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
31392763eda6SSzymon Janc 
31402763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31412763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
31422763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
31432763eda6SSzymon Janc 
31442763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
31452763eda6SSzymon Janc 									&cp);
31462763eda6SSzymon Janc 	} else {
31472763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
31482763eda6SSzymon Janc 
31492763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
31502763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
31512763eda6SSzymon Janc 									&cp);
31522763eda6SSzymon Janc 	}
31532763eda6SSzymon Janc 
3154e1ba1f15SSzymon Janc unlock:
31552763eda6SSzymon Janc 	hci_dev_unlock(hdev);
31562763eda6SSzymon Janc }
31572763eda6SSzymon Janc 
3158fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3159fcd89c09SVille Tervo {
3160fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3161fcd89c09SVille Tervo 	struct hci_conn *conn;
3162fcd89c09SVille Tervo 
3163fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3164fcd89c09SVille Tervo 
3165fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3166fcd89c09SVille Tervo 
3167fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3168b62f328bSVille Tervo 	if (!conn) {
3169b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3170b62f328bSVille Tervo 		if (!conn) {
3171b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3172b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3173b62f328bSVille Tervo 			return;
3174b62f328bSVille Tervo 		}
317529b7988aSAndre Guedes 
317629b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3177b62f328bSVille Tervo 	}
3178fcd89c09SVille Tervo 
3179fcd89c09SVille Tervo 	if (ev->status) {
318048264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
318148264f06SJohan Hedberg 						conn->dst_type, ev->status);
3182fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3183fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3184fcd89c09SVille Tervo 		hci_conn_del(conn);
3185fcd89c09SVille Tervo 		goto unlock;
3186fcd89c09SVille Tervo 	}
3187fcd89c09SVille Tervo 
318848264f06SJohan Hedberg 	mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
318983bc71b4SVinicius Costa Gomes 
31907b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3191fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3192fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3193fcd89c09SVille Tervo 
3194fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3195fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3196fcd89c09SVille Tervo 
3197fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3198fcd89c09SVille Tervo 
3199fcd89c09SVille Tervo unlock:
3200fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3201fcd89c09SVille Tervo }
3202fcd89c09SVille Tervo 
32039aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
32049aa04c91SAndre Guedes 						struct sk_buff *skb)
32059aa04c91SAndre Guedes {
3206e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3207e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
32089aa04c91SAndre Guedes 
32099aa04c91SAndre Guedes 	hci_dev_lock(hdev);
32109aa04c91SAndre Guedes 
3211e95beb41SAndre Guedes 	while (num_reports--) {
3212e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3213e95beb41SAndre Guedes 
32149aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
32159aa04c91SAndre Guedes 
3216e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
32179aa04c91SAndre Guedes 	}
32189aa04c91SAndre Guedes 
32199aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
32209aa04c91SAndre Guedes }
32219aa04c91SAndre Guedes 
3222a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3223a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3224a7a595f6SVinicius Costa Gomes {
3225a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3226a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3227bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3228a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3229bea710feSVinicius Costa Gomes 	struct link_key *ltk;
3230a7a595f6SVinicius Costa Gomes 
3231a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3232a7a595f6SVinicius Costa Gomes 
3233a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3234a7a595f6SVinicius Costa Gomes 
3235a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3236bea710feSVinicius Costa Gomes 	if (conn == NULL)
3237bea710feSVinicius Costa Gomes 		goto not_found;
3238a7a595f6SVinicius Costa Gomes 
3239bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3240bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3241bea710feSVinicius Costa Gomes 		goto not_found;
3242bea710feSVinicius Costa Gomes 
3243bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3244a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3245726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
3246a7a595f6SVinicius Costa Gomes 
3247a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3248a7a595f6SVinicius Costa Gomes 
3249a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3250bea710feSVinicius Costa Gomes 
3251bea710feSVinicius Costa Gomes 	return;
3252bea710feSVinicius Costa Gomes 
3253bea710feSVinicius Costa Gomes not_found:
3254bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3255bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3256bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3257a7a595f6SVinicius Costa Gomes }
3258a7a595f6SVinicius Costa Gomes 
3259fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3260fcd89c09SVille Tervo {
3261fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3262fcd89c09SVille Tervo 
3263fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3264fcd89c09SVille Tervo 
3265fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3266fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3267fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3268fcd89c09SVille Tervo 		break;
3269fcd89c09SVille Tervo 
32709aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
32719aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
32729aa04c91SAndre Guedes 		break;
32739aa04c91SAndre Guedes 
3274a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3275a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3276a7a595f6SVinicius Costa Gomes 		break;
3277a7a595f6SVinicius Costa Gomes 
3278fcd89c09SVille Tervo 	default:
3279fcd89c09SVille Tervo 		break;
3280fcd89c09SVille Tervo 	}
3281fcd89c09SVille Tervo }
3282fcd89c09SVille Tervo 
32831da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
32841da177e4SLinus Torvalds {
3285a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3286a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
32871da177e4SLinus Torvalds 
32881da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
32891da177e4SLinus Torvalds 
3290a9de9248SMarcel Holtmann 	switch (event) {
32911da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
32921da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
32931da177e4SLinus Torvalds 		break;
32941da177e4SLinus Torvalds 
32951da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
32961da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
32971da177e4SLinus Torvalds 		break;
32981da177e4SLinus Torvalds 
3299a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3300a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
330121d9e30eSMarcel Holtmann 		break;
330221d9e30eSMarcel Holtmann 
33031da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
33041da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
33051da177e4SLinus Torvalds 		break;
33061da177e4SLinus Torvalds 
33071da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
33081da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
33091da177e4SLinus Torvalds 		break;
33101da177e4SLinus Torvalds 
33111da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
33121da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
33131da177e4SLinus Torvalds 		break;
33141da177e4SLinus Torvalds 
3315a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3316a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3317a9de9248SMarcel Holtmann 		break;
3318a9de9248SMarcel Holtmann 
33191da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
33201da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
33211da177e4SLinus Torvalds 		break;
33221da177e4SLinus Torvalds 
3323a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3324a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3325a9de9248SMarcel Holtmann 		break;
3326a9de9248SMarcel Holtmann 
3327a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3328a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3329a9de9248SMarcel Holtmann 		break;
3330a9de9248SMarcel Holtmann 
3331a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3332a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3333a9de9248SMarcel Holtmann 		break;
3334a9de9248SMarcel Holtmann 
3335a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3336a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3337a9de9248SMarcel Holtmann 		break;
3338a9de9248SMarcel Holtmann 
3339a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3340a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3341a9de9248SMarcel Holtmann 		break;
3342a9de9248SMarcel Holtmann 
3343a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3344a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3345a9de9248SMarcel Holtmann 		break;
3346a9de9248SMarcel Holtmann 
3347a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3348a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3349a9de9248SMarcel Holtmann 		break;
3350a9de9248SMarcel Holtmann 
3351a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3352a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3353a9de9248SMarcel Holtmann 		break;
3354a9de9248SMarcel Holtmann 
3355a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3356a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
33571da177e4SLinus Torvalds 		break;
33581da177e4SLinus Torvalds 
33591da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
33601da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
33611da177e4SLinus Torvalds 		break;
33621da177e4SLinus Torvalds 
33631da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
33641da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
33651da177e4SLinus Torvalds 		break;
33661da177e4SLinus Torvalds 
33671da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
33681da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
33691da177e4SLinus Torvalds 		break;
33701da177e4SLinus Torvalds 
33711da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
33721da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
33731da177e4SLinus Torvalds 		break;
33741da177e4SLinus Torvalds 
3375a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3376a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3377a8746417SMarcel Holtmann 		break;
3378a8746417SMarcel Holtmann 
337985a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
338085a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
338185a1e930SMarcel Holtmann 		break;
338285a1e930SMarcel Holtmann 
3383a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3384a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3385a9de9248SMarcel Holtmann 		break;
3386a9de9248SMarcel Holtmann 
3387a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3388a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3389a9de9248SMarcel Holtmann 		break;
3390a9de9248SMarcel Holtmann 
3391a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3392a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3393a9de9248SMarcel Holtmann 		break;
3394a9de9248SMarcel Holtmann 
3395a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3396a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3397a9de9248SMarcel Holtmann 		break;
3398a9de9248SMarcel Holtmann 
339904837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
340004837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
340104837f64SMarcel Holtmann 		break;
340204837f64SMarcel Holtmann 
3403a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3404a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
34051da177e4SLinus Torvalds 		break;
34061da177e4SLinus Torvalds 
34070493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
34080493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
34090493684eSMarcel Holtmann 		break;
34100493684eSMarcel Holtmann 
341103b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
341203b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
341303b555e1SJohan Hedberg 		break;
341403b555e1SJohan Hedberg 
3415a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3416a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3417a5c29683SJohan Hedberg 		break;
3418a5c29683SJohan Hedberg 
34191143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
34201143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
34211143d458SBrian Gix 		break;
34221143d458SBrian Gix 
34230493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
34240493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
34250493684eSMarcel Holtmann 		break;
34260493684eSMarcel Holtmann 
342741a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
342841a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
342941a96212SMarcel Holtmann 		break;
343041a96212SMarcel Holtmann 
3431fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3432fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3433fcd89c09SVille Tervo 		break;
3434fcd89c09SVille Tervo 
34352763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
34362763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
34372763eda6SSzymon Janc 		break;
34382763eda6SSzymon Janc 
343925e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
344025e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
344125e89e99SAndrei Emeltchenko 		break;
344225e89e99SAndrei Emeltchenko 
34431da177e4SLinus Torvalds 	default:
3444a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
34451da177e4SLinus Torvalds 		break;
34461da177e4SLinus Torvalds 	}
34471da177e4SLinus Torvalds 
34481da177e4SLinus Torvalds 	kfree_skb(skb);
34491da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
34501da177e4SLinus Torvalds }
34511da177e4SLinus Torvalds 
34521da177e4SLinus Torvalds /* Generate internal stack event */
34531da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
34541da177e4SLinus Torvalds {
34551da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
34561da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
34571da177e4SLinus Torvalds 	struct sk_buff *skb;
34581da177e4SLinus Torvalds 
34591da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
34601da177e4SLinus Torvalds 	if (!skb)
34611da177e4SLinus Torvalds 		return;
34621da177e4SLinus Torvalds 
34631da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
34641da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
34651da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
34661da177e4SLinus Torvalds 
34671da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
34681da177e4SLinus Torvalds 	ev->type = type;
34691da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
34701da177e4SLinus Torvalds 
3471576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3472a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3473576c7d85SMarcel Holtmann 
34740d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
34751da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3476eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
34771da177e4SLinus Torvalds 	kfree_skb(skb);
34781da177e4SLinus Torvalds }
3479e6100a25SAndre Guedes 
3480669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3481e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3482