xref: /openbmc/linux/net/bluetooth/hci_event.c (revision db323f2f)
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 
48e6100a25SAndre Guedes static int 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);
68744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 0);
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 
214b312b161SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->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 
381a9de9248SMarcel Holtmann 	if (hdev->notify) {
382a9de9248SMarcel Holtmann 		tasklet_disable(&hdev->tx_task);
383a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
384a9de9248SMarcel Holtmann 		tasklet_enable(&hdev->tx_task);
385a9de9248SMarcel Holtmann 	}
386a9de9248SMarcel Holtmann }
387a9de9248SMarcel Holtmann 
388a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
389a9de9248SMarcel Holtmann {
390a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
391f383f275SMarcel Holtmann 	__u16 setting;
392a9de9248SMarcel Holtmann 	void *sent;
393a9de9248SMarcel Holtmann 
394a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
395a9de9248SMarcel Holtmann 
396f383f275SMarcel Holtmann 	if (status)
397f383f275SMarcel Holtmann 		return;
398f383f275SMarcel Holtmann 
399a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
400a9de9248SMarcel Holtmann 	if (!sent)
401a9de9248SMarcel Holtmann 		return;
402a9de9248SMarcel Holtmann 
403f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4041da177e4SLinus Torvalds 
405f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
406f383f275SMarcel Holtmann 		return;
407f383f275SMarcel Holtmann 
4081da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4091da177e4SLinus Torvalds 
410a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4111da177e4SLinus Torvalds 
4121da177e4SLinus Torvalds 	if (hdev->notify) {
4131da177e4SLinus Torvalds 		tasklet_disable(&hdev->tx_task);
4141da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4151da177e4SLinus Torvalds 		tasklet_enable(&hdev->tx_task);
4161da177e4SLinus Torvalds 	}
4171da177e4SLinus Torvalds }
4181da177e4SLinus Torvalds 
419a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4201da177e4SLinus Torvalds {
421a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4221da177e4SLinus Torvalds 
423a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4241da177e4SLinus Torvalds 
42523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4261143e5a6SMarcel Holtmann }
4271143e5a6SMarcel Holtmann 
428333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
429333140b5SMarcel Holtmann {
430333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
431333140b5SMarcel Holtmann 
432333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
433333140b5SMarcel Holtmann 
434333140b5SMarcel Holtmann 	if (rp->status)
435333140b5SMarcel Holtmann 		return;
436333140b5SMarcel Holtmann 
437333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
438333140b5SMarcel Holtmann }
439333140b5SMarcel Holtmann 
440333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
441333140b5SMarcel Holtmann {
442333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
443333140b5SMarcel Holtmann 	void *sent;
444333140b5SMarcel Holtmann 
445333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
446333140b5SMarcel Holtmann 
447333140b5SMarcel Holtmann 	if (status)
448333140b5SMarcel Holtmann 		return;
449333140b5SMarcel Holtmann 
450333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
451333140b5SMarcel Holtmann 	if (!sent)
452333140b5SMarcel Holtmann 		return;
453333140b5SMarcel Holtmann 
454333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
455333140b5SMarcel Holtmann }
456333140b5SMarcel Holtmann 
457d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
458d5859e22SJohan Hedberg {
459d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
460d5859e22SJohan Hedberg 		return 2;
461d5859e22SJohan Hedberg 
462d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
463d5859e22SJohan Hedberg 		return 1;
464d5859e22SJohan Hedberg 
465d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
466d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
467d5859e22SJohan Hedberg 		return 1;
468d5859e22SJohan Hedberg 
469d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
470d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
471d5859e22SJohan Hedberg 			return 1;
472d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
473d5859e22SJohan Hedberg 			return 1;
474d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
475d5859e22SJohan Hedberg 			return 1;
476d5859e22SJohan Hedberg 	}
477d5859e22SJohan Hedberg 
478d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
479d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
480d5859e22SJohan Hedberg 		return 1;
481d5859e22SJohan Hedberg 
482d5859e22SJohan Hedberg 	return 0;
483d5859e22SJohan Hedberg }
484d5859e22SJohan Hedberg 
485d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
486d5859e22SJohan Hedberg {
487d5859e22SJohan Hedberg 	u8 mode;
488d5859e22SJohan Hedberg 
489d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
490d5859e22SJohan Hedberg 
491d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
492d5859e22SJohan Hedberg }
493d5859e22SJohan Hedberg 
494d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
495d5859e22SJohan Hedberg {
496d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
497d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
498d5859e22SJohan Hedberg 	 * command otherwise */
499d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
500d5859e22SJohan Hedberg 
5016de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5026de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5035a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
5046de6c18dSVille Tervo 		return;
5056de6c18dSVille Tervo 
506d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
507d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
508d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
509d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
510d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
511d5859e22SJohan Hedberg 
512d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
513d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
514d5859e22SJohan Hedberg 
515d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
516d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
517d5859e22SJohan Hedberg 
518d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
519d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
520d5859e22SJohan Hedberg 
521d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
522d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
523d5859e22SJohan Hedberg 
524d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
525d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
526d5859e22SJohan Hedberg 
527d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
528d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
529d5859e22SJohan Hedberg 
530d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
531d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
532d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
533d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
534d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
535d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
536d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
537d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
538d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
539d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
540d5859e22SJohan Hedberg 					 * Features Notification */
541d5859e22SJohan Hedberg 	}
542d5859e22SJohan Hedberg 
543d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
544d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
545d5859e22SJohan Hedberg 
546d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
547d5859e22SJohan Hedberg }
548d5859e22SJohan Hedberg 
549e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
550e6100a25SAndre Guedes {
551e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
552e6100a25SAndre Guedes 
553e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
554e6100a25SAndre Guedes 
555e6100a25SAndre Guedes 	if (enable_le) {
556e6100a25SAndre Guedes 		cp.le = 1;
557e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
558e6100a25SAndre Guedes 	}
559e6100a25SAndre Guedes 
560e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
561e6100a25SAndre Guedes }
562e6100a25SAndre Guedes 
563d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
564d5859e22SJohan Hedberg {
565d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
566d5859e22SJohan Hedberg 
567d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
568d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
569d5859e22SJohan Hedberg 
570d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
571d5859e22SJohan Hedberg 		u8 mode = 0x01;
572d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
573d5859e22SJohan Hedberg 	}
574d5859e22SJohan Hedberg 
575d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
576d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
577d5859e22SJohan Hedberg 
578d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
579d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
580971e3a4bSAndre Guedes 
581971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
582971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
583971e3a4bSAndre Guedes 
584971e3a4bSAndre Guedes 		cp.page = 0x01;
585971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
586971e3a4bSAndre Guedes 							sizeof(cp), &cp);
587971e3a4bSAndre Guedes 	}
588e6100a25SAndre Guedes 
589e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
590e6100a25SAndre Guedes 		hci_set_le_support(hdev);
591d5859e22SJohan Hedberg }
592d5859e22SJohan Hedberg 
593a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
594a9de9248SMarcel Holtmann {
595a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5961143e5a6SMarcel Holtmann 
597a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5981143e5a6SMarcel Holtmann 
599a9de9248SMarcel Holtmann 	if (rp->status)
600a9de9248SMarcel Holtmann 		return;
6011143e5a6SMarcel Holtmann 
602a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
603e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
604d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
605e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
606d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6071da177e4SLinus Torvalds 
608a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
609a9de9248SMarcel Holtmann 					hdev->manufacturer,
610a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
611d5859e22SJohan Hedberg 
612d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
613d5859e22SJohan Hedberg 		hci_setup(hdev);
614d5859e22SJohan Hedberg }
615d5859e22SJohan Hedberg 
616d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
617d5859e22SJohan Hedberg {
618d5859e22SJohan Hedberg 	u16 link_policy = 0;
619d5859e22SJohan Hedberg 
620d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
621d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
622d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
623d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
624d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
625d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
626d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
627d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
628d5859e22SJohan Hedberg 
629d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
630d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
631d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6321da177e4SLinus Torvalds }
6331da177e4SLinus Torvalds 
634a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
635a9de9248SMarcel Holtmann {
636a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
637a9de9248SMarcel Holtmann 
638a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
639a9de9248SMarcel Holtmann 
640a9de9248SMarcel Holtmann 	if (rp->status)
641d5859e22SJohan Hedberg 		goto done;
642a9de9248SMarcel Holtmann 
643a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
644d5859e22SJohan Hedberg 
645d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
646d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
647d5859e22SJohan Hedberg 
648d5859e22SJohan Hedberg done:
649d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
650a9de9248SMarcel Holtmann }
651a9de9248SMarcel Holtmann 
652a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
653a9de9248SMarcel Holtmann {
654a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
655a9de9248SMarcel Holtmann 
656a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
657a9de9248SMarcel Holtmann 
658a9de9248SMarcel Holtmann 	if (rp->status)
659a9de9248SMarcel Holtmann 		return;
660a9de9248SMarcel Holtmann 
661a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds 	/* Adjust default settings according to features
6641da177e4SLinus Torvalds 	 * supported by device. */
665a9de9248SMarcel Holtmann 
6661da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6671da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6681da177e4SLinus Torvalds 
6691da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6701da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6711da177e4SLinus Torvalds 
6725b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6731da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6745b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6755b7f9909SMarcel Holtmann 	}
6761da177e4SLinus Torvalds 
6775b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6781da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6795b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6805b7f9909SMarcel Holtmann 	}
6815b7f9909SMarcel Holtmann 
6825b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6835b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6845b7f9909SMarcel Holtmann 
6855b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6865b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6875b7f9909SMarcel Holtmann 
6885b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6895b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6901da177e4SLinus Torvalds 
691efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
692efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
693efc7688bSMarcel Holtmann 
694efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
695efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
696efc7688bSMarcel Holtmann 
697efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
698efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
699efc7688bSMarcel Holtmann 
700a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
701a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
702a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
703a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
704a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7051da177e4SLinus Torvalds }
7061da177e4SLinus Torvalds 
707971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
708971e3a4bSAndre Guedes 							struct sk_buff *skb)
709971e3a4bSAndre Guedes {
710971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
711971e3a4bSAndre Guedes 
712971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
713971e3a4bSAndre Guedes 
714971e3a4bSAndre Guedes 	if (rp->status)
715971e3a4bSAndre Guedes 		return;
716971e3a4bSAndre Guedes 
717971e3a4bSAndre Guedes 	memcpy(hdev->extfeatures, rp->features, 8);
718971e3a4bSAndre Guedes 
719971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
720971e3a4bSAndre Guedes }
721971e3a4bSAndre Guedes 
7221e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7231e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7241e89cffbSAndrei Emeltchenko {
7251e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7261e89cffbSAndrei Emeltchenko 
7271e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7281e89cffbSAndrei Emeltchenko 
7291e89cffbSAndrei Emeltchenko 	if (rp->status)
7301e89cffbSAndrei Emeltchenko 		return;
7311e89cffbSAndrei Emeltchenko 
7321e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7331e89cffbSAndrei Emeltchenko 
7341e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7351e89cffbSAndrei Emeltchenko }
7361e89cffbSAndrei Emeltchenko 
737a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
738a9de9248SMarcel Holtmann {
739a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
740a9de9248SMarcel Holtmann 
741a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
742a9de9248SMarcel Holtmann 
743a9de9248SMarcel Holtmann 	if (rp->status)
744a9de9248SMarcel Holtmann 		return;
745a9de9248SMarcel Holtmann 
746a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
747a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
748a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
749a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
750da1f5198SMarcel Holtmann 
751da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
752da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
753da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
754da1f5198SMarcel Holtmann 	}
755da1f5198SMarcel Holtmann 
756da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
757da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7581da177e4SLinus Torvalds 
759a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
760a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
761a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7621da177e4SLinus Torvalds }
7631da177e4SLinus Torvalds 
764a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
765a9de9248SMarcel Holtmann {
766a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7671da177e4SLinus Torvalds 
768a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
769a9de9248SMarcel Holtmann 
770a9de9248SMarcel Holtmann 	if (!rp->status)
771a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
772a9de9248SMarcel Holtmann 
77323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
77423bb5763SJohan Hedberg }
77523bb5763SJohan Hedberg 
77623bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
77723bb5763SJohan Hedberg {
77823bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
77923bb5763SJohan Hedberg 
78023bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
78123bb5763SJohan Hedberg 
78223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
7831da177e4SLinus Torvalds }
7841da177e4SLinus Torvalds 
785928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
786928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
787928abaa7SAndrei Emeltchenko {
788928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
789928abaa7SAndrei Emeltchenko 
790928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
791928abaa7SAndrei Emeltchenko 
792928abaa7SAndrei Emeltchenko 	if (rp->status)
793928abaa7SAndrei Emeltchenko 		return;
794928abaa7SAndrei Emeltchenko 
795928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
796928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
797928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
798928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
799928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
800928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
801928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
802928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
803928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
804928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
805928abaa7SAndrei Emeltchenko 
806928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
807928abaa7SAndrei Emeltchenko }
808928abaa7SAndrei Emeltchenko 
809b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
810b0916ea0SJohan Hedberg 							struct sk_buff *skb)
811b0916ea0SJohan Hedberg {
812b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
813b0916ea0SJohan Hedberg 
814b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
815b0916ea0SJohan Hedberg 
816b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
817b0916ea0SJohan Hedberg }
818b0916ea0SJohan Hedberg 
819d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
820d5859e22SJohan Hedberg {
821d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
822d5859e22SJohan Hedberg 
823d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
824d5859e22SJohan Hedberg 
825d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
826d5859e22SJohan Hedberg }
827d5859e22SJohan Hedberg 
828d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
829d5859e22SJohan Hedberg 							struct sk_buff *skb)
830d5859e22SJohan Hedberg {
831d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
832d5859e22SJohan Hedberg 
833d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
834d5859e22SJohan Hedberg 
835d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
836d5859e22SJohan Hedberg }
837d5859e22SJohan Hedberg 
838d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
839d5859e22SJohan Hedberg 							struct sk_buff *skb)
840d5859e22SJohan Hedberg {
841d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
842d5859e22SJohan Hedberg 
843d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
844d5859e22SJohan Hedberg 
845d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
846d5859e22SJohan Hedberg }
847d5859e22SJohan Hedberg 
848d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
849d5859e22SJohan Hedberg {
850d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
851d5859e22SJohan Hedberg 
852d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
853d5859e22SJohan Hedberg 
854d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
855d5859e22SJohan Hedberg }
856d5859e22SJohan Hedberg 
857980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
858980e1a53SJohan Hedberg {
859980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
860980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
861980e1a53SJohan Hedberg 	struct hci_conn *conn;
862980e1a53SJohan Hedberg 
863980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
864980e1a53SJohan Hedberg 
86556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
86656e5cb86SJohan Hedberg 
867980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
868744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
869980e1a53SJohan Hedberg 
870980e1a53SJohan Hedberg 	if (rp->status != 0)
87156e5cb86SJohan Hedberg 		goto unlock;
872980e1a53SJohan Hedberg 
873980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
874980e1a53SJohan Hedberg 	if (!cp)
87556e5cb86SJohan Hedberg 		goto unlock;
876980e1a53SJohan Hedberg 
877980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
878980e1a53SJohan Hedberg 	if (conn)
879980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
88056e5cb86SJohan Hedberg 
88156e5cb86SJohan Hedberg unlock:
88256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
883980e1a53SJohan Hedberg }
884980e1a53SJohan Hedberg 
885980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
886980e1a53SJohan Hedberg {
887980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
888980e1a53SJohan Hedberg 
889980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
890980e1a53SJohan Hedberg 
89156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
89256e5cb86SJohan Hedberg 
893980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
894744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
895980e1a53SJohan Hedberg 								rp->status);
89656e5cb86SJohan Hedberg 
89756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
898980e1a53SJohan Hedberg }
89956e5cb86SJohan Hedberg 
9006ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9016ed58ec5SVille Tervo 				       struct sk_buff *skb)
9026ed58ec5SVille Tervo {
9036ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9046ed58ec5SVille Tervo 
9056ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9066ed58ec5SVille Tervo 
9076ed58ec5SVille Tervo 	if (rp->status)
9086ed58ec5SVille Tervo 		return;
9096ed58ec5SVille Tervo 
9106ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9116ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9126ed58ec5SVille Tervo 
9136ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9146ed58ec5SVille Tervo 
9156ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9166ed58ec5SVille Tervo 
9176ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9186ed58ec5SVille Tervo }
919980e1a53SJohan Hedberg 
920a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
921a5c29683SJohan Hedberg {
922a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
923a5c29683SJohan Hedberg 
924a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
925a5c29683SJohan Hedberg 
92656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92756e5cb86SJohan Hedberg 
928a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
929744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
930a5c29683SJohan Hedberg 								rp->status);
93156e5cb86SJohan Hedberg 
93256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
933a5c29683SJohan Hedberg }
934a5c29683SJohan Hedberg 
935a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
936a5c29683SJohan Hedberg 							struct sk_buff *skb)
937a5c29683SJohan Hedberg {
938a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
939a5c29683SJohan Hedberg 
940a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
941a5c29683SJohan Hedberg 
94256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
94356e5cb86SJohan Hedberg 
944a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
945744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
946a5c29683SJohan Hedberg 								rp->status);
94756e5cb86SJohan Hedberg 
94856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
949a5c29683SJohan Hedberg }
950a5c29683SJohan Hedberg 
9511143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9521143d458SBrian Gix {
9531143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9541143d458SBrian Gix 
9551143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9561143d458SBrian Gix 
9571143d458SBrian Gix 	hci_dev_lock(hdev);
9581143d458SBrian Gix 
9591143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
9601143d458SBrian Gix 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
9611143d458SBrian Gix 								rp->status);
9621143d458SBrian Gix 
9631143d458SBrian Gix 	hci_dev_unlock(hdev);
9641143d458SBrian Gix }
9651143d458SBrian Gix 
9661143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9671143d458SBrian Gix 							struct sk_buff *skb)
9681143d458SBrian Gix {
9691143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9701143d458SBrian Gix 
9711143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9721143d458SBrian Gix 
9731143d458SBrian Gix 	hci_dev_lock(hdev);
9741143d458SBrian Gix 
9751143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
9761143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
9771143d458SBrian Gix 								rp->status);
9781143d458SBrian Gix 
9791143d458SBrian Gix 	hci_dev_unlock(hdev);
9801143d458SBrian Gix }
9811143d458SBrian Gix 
982c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
983c35938b2SSzymon Janc 							struct sk_buff *skb)
984c35938b2SSzymon Janc {
985c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
986c35938b2SSzymon Janc 
987c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
988c35938b2SSzymon Janc 
98956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
990744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
991c35938b2SSzymon Janc 						rp->randomizer, rp->status);
99256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
993c35938b2SSzymon Janc }
994c35938b2SSzymon Janc 
99507f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
99607f7fa5dSAndre Guedes {
99707f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
99807f7fa5dSAndre Guedes 
99907f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
100007f7fa5dSAndre Guedes }
100107f7fa5dSAndre Guedes 
1002eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1003eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1004eb9d91f5SAndre Guedes {
1005eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1006eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1007eb9d91f5SAndre Guedes 
1008eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1009eb9d91f5SAndre Guedes 
1010eb9d91f5SAndre Guedes 	if (status)
1011eb9d91f5SAndre Guedes 		return;
1012eb9d91f5SAndre Guedes 
1013eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1014eb9d91f5SAndre Guedes 	if (!cp)
1015eb9d91f5SAndre Guedes 		return;
1016eb9d91f5SAndre Guedes 
101735815085SAndre Guedes 	if (cp->enable == 0x01) {
1018d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1019d23264a8SAndre Guedes 
1020db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1021a8f13c8cSAndre Guedes 
1022a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1023eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1024a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
102535815085SAndre Guedes 	} else if (cp->enable == 0x00) {
1026d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1027d23264a8SAndre Guedes 
1028db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1029db323f2fSGustavo F. Padovan 		queue_delayed_work(hdev->workqueue, &hdev->adv_work,
1030db323f2fSGustavo F. Padovan 						 jiffies + ADV_CLEAR_TIMEOUT);
103135815085SAndre Guedes 	}
1032eb9d91f5SAndre Guedes }
1033eb9d91f5SAndre Guedes 
1034a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1035a7a595f6SVinicius Costa Gomes {
1036a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1037a7a595f6SVinicius Costa Gomes 
1038a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1039a7a595f6SVinicius Costa Gomes 
1040a7a595f6SVinicius Costa Gomes 	if (rp->status)
1041a7a595f6SVinicius Costa Gomes 		return;
1042a7a595f6SVinicius Costa Gomes 
1043a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1044a7a595f6SVinicius Costa Gomes }
1045a7a595f6SVinicius Costa Gomes 
1046a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1047a7a595f6SVinicius Costa Gomes {
1048a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1049a7a595f6SVinicius Costa Gomes 
1050a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1051a7a595f6SVinicius Costa Gomes 
1052a7a595f6SVinicius Costa Gomes 	if (rp->status)
1053a7a595f6SVinicius Costa Gomes 		return;
1054a7a595f6SVinicius Costa Gomes 
1055a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1056a7a595f6SVinicius Costa Gomes }
1057a7a595f6SVinicius Costa Gomes 
1058f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1059f9b49306SAndre Guedes 							struct sk_buff *skb)
1060f9b49306SAndre Guedes {
1061f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1062f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1063f9b49306SAndre Guedes 
1064f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1065f9b49306SAndre Guedes 
1066f9b49306SAndre Guedes 	if (status)
1067f9b49306SAndre Guedes 		return;
1068f9b49306SAndre Guedes 
1069f9b49306SAndre Guedes 	cp.page = 0x01;
1070f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1071f9b49306SAndre Guedes }
1072f9b49306SAndre Guedes 
1073a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1074a9de9248SMarcel Holtmann {
1075a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1076a9de9248SMarcel Holtmann 
1077a9de9248SMarcel Holtmann 	if (status) {
107823bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1079a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
108056e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1081164a6e78SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
10827a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
108356e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1084314b2381SJohan Hedberg 		return;
1085314b2381SJohan Hedberg 	}
1086314b2381SJohan Hedberg 
108789352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
108889352e7dSAndre Guedes 
108956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1090744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 1);
109156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1092a9de9248SMarcel Holtmann }
1093a9de9248SMarcel Holtmann 
10941da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
10951da177e4SLinus Torvalds {
1096a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
10971da177e4SLinus Torvalds 	struct hci_conn *conn;
10981da177e4SLinus Torvalds 
1099a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1100a9de9248SMarcel Holtmann 
1101a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11021da177e4SLinus Torvalds 	if (!cp)
11031da177e4SLinus Torvalds 		return;
11041da177e4SLinus Torvalds 
11051da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11061da177e4SLinus Torvalds 
11071da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11081da177e4SLinus Torvalds 
1109a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11101da177e4SLinus Torvalds 
11111da177e4SLinus Torvalds 	if (status) {
11121da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11134c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11141da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11151da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11161da177e4SLinus Torvalds 				hci_conn_del(conn);
11174c67bc74SMarcel Holtmann 			} else
11184c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11191da177e4SLinus Torvalds 		}
11201da177e4SLinus Torvalds 	} else {
11211da177e4SLinus Torvalds 		if (!conn) {
11221da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11231da177e4SLinus Torvalds 			if (conn) {
11241da177e4SLinus Torvalds 				conn->out = 1;
11251da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11261da177e4SLinus Torvalds 			} else
1127893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11281da177e4SLinus Torvalds 		}
11291da177e4SLinus Torvalds 	}
11301da177e4SLinus Torvalds 
11311da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11321da177e4SLinus Torvalds }
11331da177e4SLinus Torvalds 
1134a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11351da177e4SLinus Torvalds {
1136a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11371da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11381da177e4SLinus Torvalds 	__u16 handle;
11391da177e4SLinus Torvalds 
1140b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1141b6a0dc82SMarcel Holtmann 
1142a9de9248SMarcel Holtmann 	if (!status)
1143a9de9248SMarcel Holtmann 		return;
1144a9de9248SMarcel Holtmann 
1145a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11461da177e4SLinus Torvalds 	if (!cp)
1147a9de9248SMarcel Holtmann 		return;
11481da177e4SLinus Torvalds 
11491da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11501da177e4SLinus Torvalds 
1151a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
11521da177e4SLinus Torvalds 
11531da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11541da177e4SLinus Torvalds 
11551da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11565a08ecceSAndrei Emeltchenko 	if (acl) {
11575a08ecceSAndrei Emeltchenko 		sco = acl->link;
11585a08ecceSAndrei Emeltchenko 		if (sco) {
11591da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11601da177e4SLinus Torvalds 
11611da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11621da177e4SLinus Torvalds 			hci_conn_del(sco);
11631da177e4SLinus Torvalds 		}
11645a08ecceSAndrei Emeltchenko 	}
11651da177e4SLinus Torvalds 
11661da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11671da177e4SLinus Torvalds }
11681da177e4SLinus Torvalds 
1169f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1170f8558555SMarcel Holtmann {
1171f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1172f8558555SMarcel Holtmann 	struct hci_conn *conn;
1173f8558555SMarcel Holtmann 
1174f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1175f8558555SMarcel Holtmann 
1176f8558555SMarcel Holtmann 	if (!status)
1177f8558555SMarcel Holtmann 		return;
1178f8558555SMarcel Holtmann 
1179f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1180f8558555SMarcel Holtmann 	if (!cp)
1181f8558555SMarcel Holtmann 		return;
1182f8558555SMarcel Holtmann 
1183f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1184f8558555SMarcel Holtmann 
1185f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1186f8558555SMarcel Holtmann 	if (conn) {
1187f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1188f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1189f8558555SMarcel Holtmann 			hci_conn_put(conn);
1190f8558555SMarcel Holtmann 		}
1191f8558555SMarcel Holtmann 	}
1192f8558555SMarcel Holtmann 
1193f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1194f8558555SMarcel Holtmann }
1195f8558555SMarcel Holtmann 
1196f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1197f8558555SMarcel Holtmann {
1198f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1199f8558555SMarcel Holtmann 	struct hci_conn *conn;
1200f8558555SMarcel Holtmann 
1201f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1202f8558555SMarcel Holtmann 
1203f8558555SMarcel Holtmann 	if (!status)
1204f8558555SMarcel Holtmann 		return;
1205f8558555SMarcel Holtmann 
1206f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1207f8558555SMarcel Holtmann 	if (!cp)
1208f8558555SMarcel Holtmann 		return;
1209f8558555SMarcel Holtmann 
1210f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1211f8558555SMarcel Holtmann 
1212f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1213f8558555SMarcel Holtmann 	if (conn) {
1214f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1215f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1216f8558555SMarcel Holtmann 			hci_conn_put(conn);
1217f8558555SMarcel Holtmann 		}
1218f8558555SMarcel Holtmann 	}
1219f8558555SMarcel Holtmann 
1220f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1221f8558555SMarcel Holtmann }
1222f8558555SMarcel Holtmann 
1223127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1224392599b9SJohan Hedberg 							struct hci_conn *conn)
1225392599b9SJohan Hedberg {
1226392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1227392599b9SJohan Hedberg 		return 0;
1228392599b9SJohan Hedberg 
1229765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1230392599b9SJohan Hedberg 		return 0;
1231392599b9SJohan Hedberg 
1232392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1233e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1234392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1235e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1236e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1237392599b9SJohan Hedberg 		return 0;
1238392599b9SJohan Hedberg 
1239392599b9SJohan Hedberg 	return 1;
1240392599b9SJohan Hedberg }
1241392599b9SJohan Hedberg 
1242a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
12431da177e4SLinus Torvalds {
1244127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1245127178d2SJohan Hedberg 	struct hci_conn *conn;
1246127178d2SJohan Hedberg 
1247a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1248127178d2SJohan Hedberg 
1249127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1250127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1251127178d2SJohan Hedberg 	if (!status)
1252127178d2SJohan Hedberg 		return;
1253127178d2SJohan Hedberg 
1254127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1255127178d2SJohan Hedberg 	if (!cp)
1256127178d2SJohan Hedberg 		return;
1257127178d2SJohan Hedberg 
1258127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1259127178d2SJohan Hedberg 
1260127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
126179c6c70cSJohan Hedberg 	if (!conn)
126279c6c70cSJohan Hedberg 		goto unlock;
126379c6c70cSJohan Hedberg 
126479c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
126579c6c70cSJohan Hedberg 		goto unlock;
126679c6c70cSJohan Hedberg 
126779c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1268127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1269127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1270127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1271127178d2SJohan Hedberg 	}
1272127178d2SJohan Hedberg 
127379c6c70cSJohan Hedberg unlock:
1274127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1275a9de9248SMarcel Holtmann }
12761da177e4SLinus Torvalds 
1277769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1278769be974SMarcel Holtmann {
1279769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1280769be974SMarcel Holtmann 	struct hci_conn *conn;
1281769be974SMarcel Holtmann 
1282769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1283769be974SMarcel Holtmann 
1284769be974SMarcel Holtmann 	if (!status)
1285769be974SMarcel Holtmann 		return;
1286769be974SMarcel Holtmann 
1287769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1288769be974SMarcel Holtmann 	if (!cp)
1289769be974SMarcel Holtmann 		return;
1290769be974SMarcel Holtmann 
1291769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1292769be974SMarcel Holtmann 
1293769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1294769be974SMarcel Holtmann 	if (conn) {
1295769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1296769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1297769be974SMarcel Holtmann 			hci_conn_put(conn);
1298769be974SMarcel Holtmann 		}
1299769be974SMarcel Holtmann 	}
1300769be974SMarcel Holtmann 
1301769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1302769be974SMarcel Holtmann }
1303769be974SMarcel Holtmann 
1304769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1305769be974SMarcel Holtmann {
1306769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1307769be974SMarcel Holtmann 	struct hci_conn *conn;
1308769be974SMarcel Holtmann 
1309769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1310769be974SMarcel Holtmann 
1311769be974SMarcel Holtmann 	if (!status)
1312769be974SMarcel Holtmann 		return;
1313769be974SMarcel Holtmann 
1314769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1315769be974SMarcel Holtmann 	if (!cp)
1316769be974SMarcel Holtmann 		return;
1317769be974SMarcel Holtmann 
1318769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1319769be974SMarcel Holtmann 
1320769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1321769be974SMarcel Holtmann 	if (conn) {
1322769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1323769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1324769be974SMarcel Holtmann 			hci_conn_put(conn);
1325769be974SMarcel Holtmann 		}
1326769be974SMarcel Holtmann 	}
1327769be974SMarcel Holtmann 
1328769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1329769be974SMarcel Holtmann }
1330769be974SMarcel Holtmann 
1331a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1332a9de9248SMarcel Holtmann {
1333b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1334b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1335b6a0dc82SMarcel Holtmann 	__u16 handle;
1336b6a0dc82SMarcel Holtmann 
1337a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1338b6a0dc82SMarcel Holtmann 
1339b6a0dc82SMarcel Holtmann 	if (!status)
1340b6a0dc82SMarcel Holtmann 		return;
1341b6a0dc82SMarcel Holtmann 
1342b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1343b6a0dc82SMarcel Holtmann 	if (!cp)
1344b6a0dc82SMarcel Holtmann 		return;
1345b6a0dc82SMarcel Holtmann 
1346b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1347b6a0dc82SMarcel Holtmann 
1348b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1349b6a0dc82SMarcel Holtmann 
1350b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1351b6a0dc82SMarcel Holtmann 
1352b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
13535a08ecceSAndrei Emeltchenko 	if (acl) {
13545a08ecceSAndrei Emeltchenko 		sco = acl->link;
13555a08ecceSAndrei Emeltchenko 		if (sco) {
1356b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1357b6a0dc82SMarcel Holtmann 
1358b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1359b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1360b6a0dc82SMarcel Holtmann 		}
13615a08ecceSAndrei Emeltchenko 	}
1362b6a0dc82SMarcel Holtmann 
1363b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1364a9de9248SMarcel Holtmann }
1365a9de9248SMarcel Holtmann 
1366a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1367a9de9248SMarcel Holtmann {
1368a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
136904837f64SMarcel Holtmann 	struct hci_conn *conn;
137004837f64SMarcel Holtmann 
1371a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1372a9de9248SMarcel Holtmann 
1373a9de9248SMarcel Holtmann 	if (!status)
1374a9de9248SMarcel Holtmann 		return;
1375a9de9248SMarcel Holtmann 
1376a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
137704837f64SMarcel Holtmann 	if (!cp)
1378a9de9248SMarcel Holtmann 		return;
137904837f64SMarcel Holtmann 
138004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
138104837f64SMarcel Holtmann 
138204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1383e73439d8SMarcel Holtmann 	if (conn) {
138404837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
138504837f64SMarcel Holtmann 
1386e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1387e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1388e73439d8SMarcel Holtmann 	}
1389e73439d8SMarcel Holtmann 
139004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
139104837f64SMarcel Holtmann }
139204837f64SMarcel Holtmann 
1393a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1394a9de9248SMarcel Holtmann {
1395a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
139604837f64SMarcel Holtmann 	struct hci_conn *conn;
139704837f64SMarcel Holtmann 
1398a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1399a9de9248SMarcel Holtmann 
1400a9de9248SMarcel Holtmann 	if (!status)
1401a9de9248SMarcel Holtmann 		return;
1402a9de9248SMarcel Holtmann 
1403a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
140404837f64SMarcel Holtmann 	if (!cp)
1405a9de9248SMarcel Holtmann 		return;
140604837f64SMarcel Holtmann 
140704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
140804837f64SMarcel Holtmann 
140904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1410e73439d8SMarcel Holtmann 	if (conn) {
141104837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
141204837f64SMarcel Holtmann 
1413e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1414e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1415e73439d8SMarcel Holtmann 	}
1416e73439d8SMarcel Holtmann 
141704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
141804837f64SMarcel Holtmann }
141904837f64SMarcel Holtmann 
1420fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1421fcd89c09SVille Tervo {
1422fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1423fcd89c09SVille Tervo 	struct hci_conn *conn;
1424fcd89c09SVille Tervo 
1425fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1426fcd89c09SVille Tervo 
1427fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1428fcd89c09SVille Tervo 	if (!cp)
1429fcd89c09SVille Tervo 		return;
1430fcd89c09SVille Tervo 
1431fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1432fcd89c09SVille Tervo 
1433fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1434fcd89c09SVille Tervo 
1435fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1436fcd89c09SVille Tervo 		conn);
1437fcd89c09SVille Tervo 
1438fcd89c09SVille Tervo 	if (status) {
1439fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1440fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1441fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1442fcd89c09SVille Tervo 			hci_conn_del(conn);
1443fcd89c09SVille Tervo 		}
1444fcd89c09SVille Tervo 	} else {
1445fcd89c09SVille Tervo 		if (!conn) {
1446fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
144729b7988aSAndre Guedes 			if (conn) {
144829b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1449fcd89c09SVille Tervo 				conn->out = 1;
145029b7988aSAndre Guedes 			} else {
1451fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1452fcd89c09SVille Tervo 			}
1453fcd89c09SVille Tervo 		}
145429b7988aSAndre Guedes 	}
1455fcd89c09SVille Tervo 
1456fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1457fcd89c09SVille Tervo }
1458fcd89c09SVille Tervo 
1459a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1460a7a595f6SVinicius Costa Gomes {
1461a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1462a7a595f6SVinicius Costa Gomes }
1463a7a595f6SVinicius Costa Gomes 
14641da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14651da177e4SLinus Torvalds {
14661da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
14671da177e4SLinus Torvalds 
14681da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
14691da177e4SLinus Torvalds 
147023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
14716bd57416SMarcel Holtmann 
1472a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
147389352e7dSAndre Guedes 
147489352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
147589352e7dSAndre Guedes 		return;
147689352e7dSAndre Guedes 
147756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1478744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 0);
147956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
14801da177e4SLinus Torvalds }
14811da177e4SLinus Torvalds 
14821da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
14831da177e4SLinus Torvalds {
148445bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1485a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
14861da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
14871da177e4SLinus Torvalds 
14881da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
14891da177e4SLinus Torvalds 
149045bb4bf0SMarcel Holtmann 	if (!num_rsp)
149145bb4bf0SMarcel Holtmann 		return;
149245bb4bf0SMarcel Holtmann 
14931da177e4SLinus Torvalds 	hci_dev_lock(hdev);
149445bb4bf0SMarcel Holtmann 
1495e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
14961da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
14971da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
14981da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
14991da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
15001da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
15011da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
15021da177e4SLinus Torvalds 		data.rssi		= 0x00;
150341a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
15041da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
150548264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
15064c659c39SJohan Hedberg 						info->dev_class, 0, NULL);
15071da177e4SLinus Torvalds 	}
150845bb4bf0SMarcel Holtmann 
15091da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15101da177e4SLinus Torvalds }
15111da177e4SLinus Torvalds 
1512a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15131da177e4SLinus Torvalds {
1514a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1515a9de9248SMarcel Holtmann 	struct hci_conn *conn;
15161da177e4SLinus Torvalds 
1517a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
151845bb4bf0SMarcel Holtmann 
15191da177e4SLinus Torvalds 	hci_dev_lock(hdev);
152045bb4bf0SMarcel Holtmann 
1521a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
15229499237aSMarcel Holtmann 	if (!conn) {
15239499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
15249499237aSMarcel Holtmann 			goto unlock;
15259499237aSMarcel Holtmann 
15269499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1527a9de9248SMarcel Holtmann 		if (!conn)
1528a9de9248SMarcel Holtmann 			goto unlock;
152945bb4bf0SMarcel Holtmann 
15309499237aSMarcel Holtmann 		conn->type = SCO_LINK;
15319499237aSMarcel Holtmann 	}
15329499237aSMarcel Holtmann 
1533a9de9248SMarcel Holtmann 	if (!ev->status) {
1534a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1535769be974SMarcel Holtmann 
1536769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1537769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1538769be974SMarcel Holtmann 			hci_conn_hold(conn);
1539052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
154048264f06SJohan Hedberg 			mgmt_connected(hdev, &ev->bdaddr, conn->type,
154148264f06SJohan Hedberg 							conn->dst_type);
1542769be974SMarcel Holtmann 		} else
1543a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1544a9de9248SMarcel Holtmann 
15459eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
15467d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
15477d0db0a3SMarcel Holtmann 
1548a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1549a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1550a9de9248SMarcel Holtmann 
1551a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1552a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1553a9de9248SMarcel Holtmann 
1554a9de9248SMarcel Holtmann 		/* Get remote features */
1555a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1556a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1557a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1558769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1559769be974SMarcel Holtmann 							sizeof(cp), &cp);
156045bb4bf0SMarcel Holtmann 		}
1561a9de9248SMarcel Holtmann 
1562a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1563d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1564a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1565a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1566a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1567a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1568a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1569a9de9248SMarcel Holtmann 		}
157017d5c04cSJohan Hedberg 	} else {
1571a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
157217d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1573744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
157448264f06SJohan Hedberg 						conn->dst_type, ev->status);
157517d5c04cSJohan Hedberg 	}
157645bb4bf0SMarcel Holtmann 
1577e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1578e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
157945bb4bf0SMarcel Holtmann 
1580769be974SMarcel Holtmann 	if (ev->status) {
1581a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1582a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1583c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1584c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1585a9de9248SMarcel Holtmann 
1586a9de9248SMarcel Holtmann unlock:
15871da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1588a9de9248SMarcel Holtmann 
1589a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
15901da177e4SLinus Torvalds }
15911da177e4SLinus Torvalds 
15921da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
15931da177e4SLinus Torvalds {
1594a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
15951da177e4SLinus Torvalds 	int mask = hdev->link_mode;
15961da177e4SLinus Torvalds 
1597a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
15981da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
15991da177e4SLinus Torvalds 
16001da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
16011da177e4SLinus Torvalds 
1602138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1603138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
16041da177e4SLinus Torvalds 		/* Connection accepted */
1605c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
16061da177e4SLinus Torvalds 		struct hci_conn *conn;
16071da177e4SLinus Torvalds 
16081da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1609b6a0dc82SMarcel Holtmann 
1610cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1611cc11b9c1SAndrei Emeltchenko 		if (ie)
1612c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1613c7bdd502SMarcel Holtmann 
16141da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16151da177e4SLinus Torvalds 		if (!conn) {
1616cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1617cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1618893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
16191da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
16201da177e4SLinus Torvalds 				return;
16211da177e4SLinus Torvalds 			}
16221da177e4SLinus Torvalds 		}
1623b6a0dc82SMarcel Holtmann 
16241da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
16251da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1626b6a0dc82SMarcel Holtmann 
16271da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
16281da177e4SLinus Torvalds 
1629b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1630b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1631b6a0dc82SMarcel Holtmann 
16321da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
16331da177e4SLinus Torvalds 
16341da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
16351da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
16361da177e4SLinus Torvalds 			else
16371da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
16381da177e4SLinus Torvalds 
1639b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1640b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1641b6a0dc82SMarcel Holtmann 		} else {
1642b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1643b6a0dc82SMarcel Holtmann 
1644b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1645a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1646b6a0dc82SMarcel Holtmann 
1647b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1648b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1649b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1650b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1651b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1652b6a0dc82SMarcel Holtmann 
1653b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1654b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1655b6a0dc82SMarcel Holtmann 		}
16561da177e4SLinus Torvalds 	} else {
16571da177e4SLinus Torvalds 		/* Connection rejected */
16581da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
16591da177e4SLinus Torvalds 
16601da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
16619f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1662a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
16631da177e4SLinus Torvalds 	}
16641da177e4SLinus Torvalds }
16651da177e4SLinus Torvalds 
16661da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16671da177e4SLinus Torvalds {
1668a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
166904837f64SMarcel Holtmann 	struct hci_conn *conn;
16701da177e4SLinus Torvalds 
16711da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
16721da177e4SLinus Torvalds 
16731da177e4SLinus Torvalds 	hci_dev_lock(hdev);
16741da177e4SLinus Torvalds 
167504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1676f7520543SJohan Hedberg 	if (!conn)
1677f7520543SJohan Hedberg 		goto unlock;
1678f7520543SJohan Hedberg 
167937d9ef76SJohan Hedberg 	if (ev->status == 0)
16801da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
16817d0db0a3SMarcel Holtmann 
168237d9ef76SJohan Hedberg 	if (conn->type == ACL_LINK || conn->type == LE_LINK) {
168337d9ef76SJohan Hedberg 		if (ev->status != 0)
168437d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
168537d9ef76SJohan Hedberg 		else
168648264f06SJohan Hedberg 			mgmt_disconnected(hdev, &conn->dst, conn->type,
168748264f06SJohan Hedberg 							conn->dst_type);
168837d9ef76SJohan Hedberg 	}
1689f7520543SJohan Hedberg 
169037d9ef76SJohan Hedberg 	if (ev->status == 0) {
16912950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
16921da177e4SLinus Torvalds 		hci_conn_del(conn);
169337d9ef76SJohan Hedberg 	}
16941da177e4SLinus Torvalds 
1695f7520543SJohan Hedberg unlock:
16961da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16971da177e4SLinus Torvalds }
16981da177e4SLinus Torvalds 
1699a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1700a9de9248SMarcel Holtmann {
1701a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1702a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1703a9de9248SMarcel Holtmann 
1704a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1705a9de9248SMarcel Holtmann 
1706a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1707a9de9248SMarcel Holtmann 
1708a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1709d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1710d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1711d7556e20SWaldemar Rymarkiewicz 
1712765c2a96SJohan Hedberg 	if (!ev->status) {
171319f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1714d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1715d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
171619f8def0SWaldemar Rymarkiewicz 		} else {
1717a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1718765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
171919f8def0SWaldemar Rymarkiewicz 		}
17202a611692SJohan Hedberg 	} else {
1721744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
17222a611692SJohan Hedberg 	}
1723a9de9248SMarcel Holtmann 
1724a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
172519f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1726a9de9248SMarcel Holtmann 
1727f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1728d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1729f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1730f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1731f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1732d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1733d7556e20SWaldemar Rymarkiewicz 									&cp);
1734f8558555SMarcel Holtmann 		} else {
1735f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1736f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1737f8558555SMarcel Holtmann 			hci_conn_put(conn);
1738f8558555SMarcel Holtmann 		}
1739052b30b0SMarcel Holtmann 	} else {
1740a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1741a9de9248SMarcel Holtmann 
1742052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1743052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1744052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1745052b30b0SMarcel Holtmann 	}
1746052b30b0SMarcel Holtmann 
1747a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1748a9de9248SMarcel Holtmann 		if (!ev->status) {
1749a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1750f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1751f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1752d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1753d7556e20SWaldemar Rymarkiewicz 									&cp);
1754a9de9248SMarcel Holtmann 		} else {
1755a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1756a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1757a9de9248SMarcel Holtmann 		}
1758a9de9248SMarcel Holtmann 	}
1759a9de9248SMarcel Holtmann 
1760d7556e20SWaldemar Rymarkiewicz unlock:
1761a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1762a9de9248SMarcel Holtmann }
1763a9de9248SMarcel Holtmann 
1764a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1765a9de9248SMarcel Holtmann {
1766127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1767127178d2SJohan Hedberg 	struct hci_conn *conn;
1768127178d2SJohan Hedberg 
1769a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1770a9de9248SMarcel Holtmann 
1771a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1772127178d2SJohan Hedberg 
1773127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1774127178d2SJohan Hedberg 
1775a88a9652SJohan Hedberg 	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
1776744cf19eSJohan Hedberg 		mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
1777a88a9652SJohan Hedberg 
1778127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
177979c6c70cSJohan Hedberg 	if (!conn)
178079c6c70cSJohan Hedberg 		goto unlock;
178179c6c70cSJohan Hedberg 
178279c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
178379c6c70cSJohan Hedberg 		goto unlock;
178479c6c70cSJohan Hedberg 
178579c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1786127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1787127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1788127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1789127178d2SJohan Hedberg 	}
1790127178d2SJohan Hedberg 
179179c6c70cSJohan Hedberg unlock:
1792127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1793a9de9248SMarcel Holtmann }
1794a9de9248SMarcel Holtmann 
1795a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1796a9de9248SMarcel Holtmann {
1797a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1798a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1799a9de9248SMarcel Holtmann 
1800a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1801a9de9248SMarcel Holtmann 
1802a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1803a9de9248SMarcel Holtmann 
1804a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1805a9de9248SMarcel Holtmann 	if (conn) {
1806a9de9248SMarcel Holtmann 		if (!ev->status) {
1807ae293196SMarcel Holtmann 			if (ev->encrypt) {
1808ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1809ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1810a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1811da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1812ae293196SMarcel Holtmann 			} else
1813a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1814a9de9248SMarcel Holtmann 		}
1815a9de9248SMarcel Holtmann 
1816a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1817a9de9248SMarcel Holtmann 
1818f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1819f8558555SMarcel Holtmann 			if (!ev->status)
1820f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1821f8558555SMarcel Holtmann 
1822f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1823f8558555SMarcel Holtmann 			hci_conn_put(conn);
1824f8558555SMarcel Holtmann 		} else
1825a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1826a9de9248SMarcel Holtmann 	}
1827a9de9248SMarcel Holtmann 
1828a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1829a9de9248SMarcel Holtmann }
1830a9de9248SMarcel Holtmann 
1831a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1832a9de9248SMarcel Holtmann {
1833a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1834a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1835a9de9248SMarcel Holtmann 
1836a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1837a9de9248SMarcel Holtmann 
1838a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1839a9de9248SMarcel Holtmann 
1840a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1841a9de9248SMarcel Holtmann 	if (conn) {
1842a9de9248SMarcel Holtmann 		if (!ev->status)
1843a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1844a9de9248SMarcel Holtmann 
1845a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1846a9de9248SMarcel Holtmann 
1847a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1848a9de9248SMarcel Holtmann 	}
1849a9de9248SMarcel Holtmann 
1850a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1851a9de9248SMarcel Holtmann }
1852a9de9248SMarcel Holtmann 
1853a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1854a9de9248SMarcel Holtmann {
1855a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1856a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1857a9de9248SMarcel Holtmann 
1858a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1859a9de9248SMarcel Holtmann 
1860a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1861a9de9248SMarcel Holtmann 
1862a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1863ccd556feSJohan Hedberg 	if (!conn)
1864ccd556feSJohan Hedberg 		goto unlock;
1865ccd556feSJohan Hedberg 
1866769be974SMarcel Holtmann 	if (!ev->status)
1867a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1868a9de9248SMarcel Holtmann 
1869ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1870ccd556feSJohan Hedberg 		goto unlock;
1871ccd556feSJohan Hedberg 
1872ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1873769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1874769be974SMarcel Holtmann 		cp.handle = ev->handle;
1875769be974SMarcel Holtmann 		cp.page = 0x01;
1876ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1877769be974SMarcel Holtmann 							sizeof(cp), &cp);
1878392599b9SJohan Hedberg 		goto unlock;
1879392599b9SJohan Hedberg 	}
1880392599b9SJohan Hedberg 
1881127178d2SJohan Hedberg 	if (!ev->status) {
1882127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1883127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1884127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1885127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1886127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1887127178d2SJohan Hedberg 	}
1888392599b9SJohan Hedberg 
1889127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1890769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1891769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1892769be974SMarcel Holtmann 		hci_conn_put(conn);
1893769be974SMarcel Holtmann 	}
1894769be974SMarcel Holtmann 
1895ccd556feSJohan Hedberg unlock:
1896a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1897a9de9248SMarcel Holtmann }
1898a9de9248SMarcel Holtmann 
1899a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1900a9de9248SMarcel Holtmann {
1901a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1902a9de9248SMarcel Holtmann }
1903a9de9248SMarcel Holtmann 
1904a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1905a9de9248SMarcel Holtmann {
1906a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1907a9de9248SMarcel Holtmann }
1908a9de9248SMarcel Holtmann 
1909a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1910a9de9248SMarcel Holtmann {
1911a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1912a9de9248SMarcel Holtmann 	__u16 opcode;
1913a9de9248SMarcel Holtmann 
1914a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1915a9de9248SMarcel Holtmann 
1916a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1917a9de9248SMarcel Holtmann 
1918a9de9248SMarcel Holtmann 	switch (opcode) {
1919a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1920a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1921a9de9248SMarcel Holtmann 		break;
1922a9de9248SMarcel Holtmann 
1923a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1924a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1925a9de9248SMarcel Holtmann 		break;
1926a9de9248SMarcel Holtmann 
1927a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1928a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1929a9de9248SMarcel Holtmann 		break;
1930a9de9248SMarcel Holtmann 
1931a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1932a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1933a9de9248SMarcel Holtmann 		break;
1934a9de9248SMarcel Holtmann 
1935e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1936e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1937e4e8e37cSMarcel Holtmann 		break;
1938e4e8e37cSMarcel Holtmann 
1939a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1940a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1941a9de9248SMarcel Holtmann 		break;
1942a9de9248SMarcel Holtmann 
1943e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1944e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1945e4e8e37cSMarcel Holtmann 		break;
1946e4e8e37cSMarcel Holtmann 
1947e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1948e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1949e4e8e37cSMarcel Holtmann 		break;
1950e4e8e37cSMarcel Holtmann 
1951a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1952a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1953a9de9248SMarcel Holtmann 		break;
1954a9de9248SMarcel Holtmann 
1955a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1956a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1957a9de9248SMarcel Holtmann 		break;
1958a9de9248SMarcel Holtmann 
1959a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1960a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1961a9de9248SMarcel Holtmann 		break;
1962a9de9248SMarcel Holtmann 
1963a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1964a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1965a9de9248SMarcel Holtmann 		break;
1966a9de9248SMarcel Holtmann 
1967a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1968a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1969a9de9248SMarcel Holtmann 		break;
1970a9de9248SMarcel Holtmann 
1971a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1972a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1973a9de9248SMarcel Holtmann 		break;
1974a9de9248SMarcel Holtmann 
1975a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1976a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1977a9de9248SMarcel Holtmann 		break;
1978a9de9248SMarcel Holtmann 
1979a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1980a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1981a9de9248SMarcel Holtmann 		break;
1982a9de9248SMarcel Holtmann 
1983a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1984a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1985a9de9248SMarcel Holtmann 		break;
1986a9de9248SMarcel Holtmann 
1987a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1988a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1989a9de9248SMarcel Holtmann 		break;
1990a9de9248SMarcel Holtmann 
1991a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1992a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1993a9de9248SMarcel Holtmann 		break;
1994a9de9248SMarcel Holtmann 
1995333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1996333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1997333140b5SMarcel Holtmann 		break;
1998333140b5SMarcel Holtmann 
1999333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2000333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2001333140b5SMarcel Holtmann 		break;
2002333140b5SMarcel Holtmann 
2003a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2004a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2005a9de9248SMarcel Holtmann 		break;
2006a9de9248SMarcel Holtmann 
2007a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2008a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2009a9de9248SMarcel Holtmann 		break;
2010a9de9248SMarcel Holtmann 
2011a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2012a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2013a9de9248SMarcel Holtmann 		break;
2014a9de9248SMarcel Holtmann 
2015971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2016971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2017971e3a4bSAndre Guedes 		break;
2018971e3a4bSAndre Guedes 
2019a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2020a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2021a9de9248SMarcel Holtmann 		break;
2022a9de9248SMarcel Holtmann 
2023a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2024a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2025a9de9248SMarcel Holtmann 		break;
2026a9de9248SMarcel Holtmann 
202723bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
202823bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
202923bb5763SJohan Hedberg 		break;
203023bb5763SJohan Hedberg 
20311e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
20321e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
20331e89cffbSAndrei Emeltchenko 		break;
20341e89cffbSAndrei Emeltchenko 
2035928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2036928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2037928abaa7SAndrei Emeltchenko 		break;
2038928abaa7SAndrei Emeltchenko 
2039b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2040b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2041b0916ea0SJohan Hedberg 		break;
2042b0916ea0SJohan Hedberg 
2043d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2044d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2045d5859e22SJohan Hedberg 		break;
2046d5859e22SJohan Hedberg 
2047d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2048d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2049d5859e22SJohan Hedberg 		break;
2050d5859e22SJohan Hedberg 
2051d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2052d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2053d5859e22SJohan Hedberg 		break;
2054d5859e22SJohan Hedberg 
2055d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2056d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2057d5859e22SJohan Hedberg 		break;
2058d5859e22SJohan Hedberg 
2059980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2060980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2061980e1a53SJohan Hedberg 		break;
2062980e1a53SJohan Hedberg 
2063980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2064980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2065980e1a53SJohan Hedberg 		break;
2066980e1a53SJohan Hedberg 
2067c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2068c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2069c35938b2SSzymon Janc 		break;
2070c35938b2SSzymon Janc 
20716ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
20726ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
20736ed58ec5SVille Tervo 		break;
20746ed58ec5SVille Tervo 
2075a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2076a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2077a5c29683SJohan Hedberg 		break;
2078a5c29683SJohan Hedberg 
2079a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2080a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2081a5c29683SJohan Hedberg 		break;
2082a5c29683SJohan Hedberg 
20831143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
20841143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
20851143d458SBrian Gix 		break;
20861143d458SBrian Gix 
20871143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
20881143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
208907f7fa5dSAndre Guedes 
209007f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
209107f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
20921143d458SBrian Gix 		break;
20931143d458SBrian Gix 
2094eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2095eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2096eb9d91f5SAndre Guedes 		break;
2097eb9d91f5SAndre Guedes 
2098a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2099a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2100a7a595f6SVinicius Costa Gomes 		break;
2101a7a595f6SVinicius Costa Gomes 
2102a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2103a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2104a7a595f6SVinicius Costa Gomes 		break;
2105a7a595f6SVinicius Costa Gomes 
2106f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2107f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2108f9b49306SAndre Guedes 		break;
2109f9b49306SAndre Guedes 
2110a9de9248SMarcel Holtmann 	default:
2111a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2112a9de9248SMarcel Holtmann 		break;
2113a9de9248SMarcel Holtmann 	}
2114a9de9248SMarcel Holtmann 
21156bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
21166bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
21176bd32326SVille Tervo 
2118a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2119a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2120a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2121c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2122a9de9248SMarcel Holtmann 	}
2123a9de9248SMarcel Holtmann }
2124a9de9248SMarcel Holtmann 
2125a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2126a9de9248SMarcel Holtmann {
2127a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2128a9de9248SMarcel Holtmann 	__u16 opcode;
2129a9de9248SMarcel Holtmann 
2130a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2131a9de9248SMarcel Holtmann 
2132a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2133a9de9248SMarcel Holtmann 
2134a9de9248SMarcel Holtmann 	switch (opcode) {
2135a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2136a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2137a9de9248SMarcel Holtmann 		break;
2138a9de9248SMarcel Holtmann 
2139a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2140a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2141a9de9248SMarcel Holtmann 		break;
2142a9de9248SMarcel Holtmann 
2143a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2144a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2145a9de9248SMarcel Holtmann 		break;
2146a9de9248SMarcel Holtmann 
2147f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2148f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2149f8558555SMarcel Holtmann 		break;
2150f8558555SMarcel Holtmann 
2151f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2152f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2153f8558555SMarcel Holtmann 		break;
2154f8558555SMarcel Holtmann 
2155a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2156a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2157a9de9248SMarcel Holtmann 		break;
2158a9de9248SMarcel Holtmann 
2159769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2160769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2161769be974SMarcel Holtmann 		break;
2162769be974SMarcel Holtmann 
2163769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2164769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2165769be974SMarcel Holtmann 		break;
2166769be974SMarcel Holtmann 
2167a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2168a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2169a9de9248SMarcel Holtmann 		break;
2170a9de9248SMarcel Holtmann 
2171a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2172a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2173a9de9248SMarcel Holtmann 		break;
2174a9de9248SMarcel Holtmann 
2175a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2176a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2177a9de9248SMarcel Holtmann 		break;
2178a9de9248SMarcel Holtmann 
21798962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
21808962ee74SJohan Hedberg 		if (ev->status != 0)
218137d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
21828962ee74SJohan Hedberg 		break;
21838962ee74SJohan Hedberg 
2184fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2185fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2186fcd89c09SVille Tervo 		break;
2187fcd89c09SVille Tervo 
2188a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2189a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2190a7a595f6SVinicius Costa Gomes 		break;
2191a7a595f6SVinicius Costa Gomes 
2192a9de9248SMarcel Holtmann 	default:
2193a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2194a9de9248SMarcel Holtmann 		break;
2195a9de9248SMarcel Holtmann 	}
2196a9de9248SMarcel Holtmann 
21976bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
21986bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
21996bd32326SVille Tervo 
220010572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2201a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2202a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2203c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2204a9de9248SMarcel Holtmann 	}
2205a9de9248SMarcel Holtmann }
2206a9de9248SMarcel Holtmann 
2207a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2208a9de9248SMarcel Holtmann {
2209a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2210a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2211a9de9248SMarcel Holtmann 
2212a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2213a9de9248SMarcel Holtmann 
2214a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2215a9de9248SMarcel Holtmann 
2216a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2217a9de9248SMarcel Holtmann 	if (conn) {
2218a9de9248SMarcel Holtmann 		if (!ev->status) {
2219a9de9248SMarcel Holtmann 			if (ev->role)
2220a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2221a9de9248SMarcel Holtmann 			else
2222a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2223a9de9248SMarcel Holtmann 		}
2224a9de9248SMarcel Holtmann 
2225a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2226a9de9248SMarcel Holtmann 
2227a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2228a9de9248SMarcel Holtmann 	}
2229a9de9248SMarcel Holtmann 
2230a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2231a9de9248SMarcel Holtmann }
2232a9de9248SMarcel Holtmann 
22331da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
22341da177e4SLinus Torvalds {
2235a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
22361ebb9252SMarcel Holtmann 	__le16 *ptr;
22371da177e4SLinus Torvalds 	int i;
22381da177e4SLinus Torvalds 
22391da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
22401da177e4SLinus Torvalds 
22411da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
22421da177e4SLinus Torvalds 
22431da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
22441da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
22451da177e4SLinus Torvalds 		return;
22461da177e4SLinus Torvalds 	}
22471da177e4SLinus Torvalds 
22481da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
22491da177e4SLinus Torvalds 
22501ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
22511da177e4SLinus Torvalds 		struct hci_conn *conn;
22521da177e4SLinus Torvalds 		__u16  handle, count;
22531da177e4SLinus Torvalds 
225483985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
225583985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
22561da177e4SLinus Torvalds 
22571da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
22581da177e4SLinus Torvalds 		if (conn) {
22591da177e4SLinus Torvalds 			conn->sent -= count;
22601da177e4SLinus Torvalds 
22615b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
226270f23020SAndrei Emeltchenko 				hdev->acl_cnt += count;
226370f23020SAndrei Emeltchenko 				if (hdev->acl_cnt > hdev->acl_pkts)
22641da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
22656ed58ec5SVille Tervo 			} else if (conn->type == LE_LINK) {
22666ed58ec5SVille Tervo 				if (hdev->le_pkts) {
22676ed58ec5SVille Tervo 					hdev->le_cnt += count;
22686ed58ec5SVille Tervo 					if (hdev->le_cnt > hdev->le_pkts)
22696ed58ec5SVille Tervo 						hdev->le_cnt = hdev->le_pkts;
22706ed58ec5SVille Tervo 				} else {
22716ed58ec5SVille Tervo 					hdev->acl_cnt += count;
22726ed58ec5SVille Tervo 					if (hdev->acl_cnt > hdev->acl_pkts)
22736ed58ec5SVille Tervo 						hdev->acl_cnt = hdev->acl_pkts;
22746ed58ec5SVille Tervo 				}
22755b7f9909SMarcel Holtmann 			} else {
227670f23020SAndrei Emeltchenko 				hdev->sco_cnt += count;
227770f23020SAndrei Emeltchenko 				if (hdev->sco_cnt > hdev->sco_pkts)
22785b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
22791da177e4SLinus Torvalds 			}
22801da177e4SLinus Torvalds 		}
22811da177e4SLinus Torvalds 	}
2282a9de9248SMarcel Holtmann 
2283c78ae283SMarcel Holtmann 	tasklet_schedule(&hdev->tx_task);
22841da177e4SLinus Torvalds 
22851da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
22861da177e4SLinus Torvalds }
22871da177e4SLinus Torvalds 
228804837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
22891da177e4SLinus Torvalds {
2290a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
229104837f64SMarcel Holtmann 	struct hci_conn *conn;
22921da177e4SLinus Torvalds 
22931da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
22941da177e4SLinus Torvalds 
22951da177e4SLinus Torvalds 	hci_dev_lock(hdev);
22961da177e4SLinus Torvalds 
229704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
229804837f64SMarcel Holtmann 	if (conn) {
229904837f64SMarcel Holtmann 		conn->mode = ev->mode;
230004837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
230104837f64SMarcel Holtmann 
230204837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
230304837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
230404837f64SMarcel Holtmann 				conn->power_save = 1;
230504837f64SMarcel Holtmann 			else
230604837f64SMarcel Holtmann 				conn->power_save = 0;
230704837f64SMarcel Holtmann 		}
2308e73439d8SMarcel Holtmann 
2309e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2310e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
231104837f64SMarcel Holtmann 	}
231204837f64SMarcel Holtmann 
231304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
231404837f64SMarcel Holtmann }
231504837f64SMarcel Holtmann 
23161da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
23171da177e4SLinus Torvalds {
2318052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2319052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2320052b30b0SMarcel Holtmann 
2321a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2322052b30b0SMarcel Holtmann 
2323052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2324052b30b0SMarcel Holtmann 
2325052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2326b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2327b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2328b6f98044SWaldemar Rymarkiewicz 
2329b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2330052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2331052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2332052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2333052b30b0SMarcel Holtmann 	}
2334052b30b0SMarcel Holtmann 
233503b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
233603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
233703b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2338582fbe9eSJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->flags)) {
2339a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2340a770bb5aSWaldemar Rymarkiewicz 
2341a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2342a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2343a770bb5aSWaldemar Rymarkiewicz 		else
2344a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2345a770bb5aSWaldemar Rymarkiewicz 
2346744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2347a770bb5aSWaldemar Rymarkiewicz 	}
2348980e1a53SJohan Hedberg 
2349b6f98044SWaldemar Rymarkiewicz unlock:
2350052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
23511da177e4SLinus Torvalds }
23521da177e4SLinus Torvalds 
23531da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
23541da177e4SLinus Torvalds {
235555ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
235655ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
235755ed8ca1SJohan Hedberg 	struct hci_conn *conn;
235855ed8ca1SJohan Hedberg 	struct link_key *key;
235955ed8ca1SJohan Hedberg 
2360a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
236155ed8ca1SJohan Hedberg 
236255ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
236355ed8ca1SJohan Hedberg 		return;
236455ed8ca1SJohan Hedberg 
236555ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
236655ed8ca1SJohan Hedberg 
236755ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
236855ed8ca1SJohan Hedberg 	if (!key) {
236955ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
237055ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
237155ed8ca1SJohan Hedberg 		goto not_found;
237255ed8ca1SJohan Hedberg 	}
237355ed8ca1SJohan Hedberg 
237455ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
237555ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
237655ed8ca1SJohan Hedberg 
2377b6020ba0SWaldemar Rymarkiewicz 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2378b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
237955ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
238055ed8ca1SJohan Hedberg 		goto not_found;
238155ed8ca1SJohan Hedberg 	}
238255ed8ca1SJohan Hedberg 
238355ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
238460b83f57SWaldemar Rymarkiewicz 	if (conn) {
238560b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
238660b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
238760b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
238855ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
238955ed8ca1SJohan Hedberg 			goto not_found;
239055ed8ca1SJohan Hedberg 		}
239155ed8ca1SJohan Hedberg 
239260b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
239360b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
239460b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
239560b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
239660b83f57SWaldemar Rymarkiewicz 			goto not_found;
239760b83f57SWaldemar Rymarkiewicz 		}
239860b83f57SWaldemar Rymarkiewicz 
239960b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
240060b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
240160b83f57SWaldemar Rymarkiewicz 	}
240260b83f57SWaldemar Rymarkiewicz 
240355ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
240455ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
240555ed8ca1SJohan Hedberg 
240655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
240755ed8ca1SJohan Hedberg 
240855ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
240955ed8ca1SJohan Hedberg 
241055ed8ca1SJohan Hedberg 	return;
241155ed8ca1SJohan Hedberg 
241255ed8ca1SJohan Hedberg not_found:
241355ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
241455ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
24151da177e4SLinus Torvalds }
24161da177e4SLinus Torvalds 
24171da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
24181da177e4SLinus Torvalds {
2419052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2420052b30b0SMarcel Holtmann 	struct hci_conn *conn;
242155ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2422052b30b0SMarcel Holtmann 
2423a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2424052b30b0SMarcel Holtmann 
2425052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2426052b30b0SMarcel Holtmann 
2427052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2428052b30b0SMarcel Holtmann 	if (conn) {
2429052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2430052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2431980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
243213d39315SWaldemar Rymarkiewicz 
243313d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
243413d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
243513d39315SWaldemar Rymarkiewicz 
2436052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2437052b30b0SMarcel Holtmann 	}
2438052b30b0SMarcel Holtmann 
243955ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2440d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
244155ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
244255ed8ca1SJohan Hedberg 
2443052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
24441da177e4SLinus Torvalds }
24451da177e4SLinus Torvalds 
244604837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
244704837f64SMarcel Holtmann {
2448a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
244904837f64SMarcel Holtmann 	struct hci_conn *conn;
245004837f64SMarcel Holtmann 
245104837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
245204837f64SMarcel Holtmann 
245304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
245404837f64SMarcel Holtmann 
245504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
24561da177e4SLinus Torvalds 	if (conn && !ev->status) {
24571da177e4SLinus Torvalds 		struct inquiry_entry *ie;
24581da177e4SLinus Torvalds 
2459cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2460cc11b9c1SAndrei Emeltchenko 		if (ie) {
24611da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
24621da177e4SLinus Torvalds 			ie->timestamp = jiffies;
24631da177e4SLinus Torvalds 		}
24641da177e4SLinus Torvalds 	}
24651da177e4SLinus Torvalds 
24661da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
24671da177e4SLinus Torvalds }
24681da177e4SLinus Torvalds 
2469a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2470a8746417SMarcel Holtmann {
2471a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2472a8746417SMarcel Holtmann 	struct hci_conn *conn;
2473a8746417SMarcel Holtmann 
2474a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2475a8746417SMarcel Holtmann 
2476a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2477a8746417SMarcel Holtmann 
2478a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2479a8746417SMarcel Holtmann 	if (conn && !ev->status)
2480a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2481a8746417SMarcel Holtmann 
2482a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2483a8746417SMarcel Holtmann }
2484a8746417SMarcel Holtmann 
248585a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
248685a1e930SMarcel Holtmann {
2487a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
248885a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
248985a1e930SMarcel Holtmann 
249085a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
249185a1e930SMarcel Holtmann 
249285a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
249385a1e930SMarcel Holtmann 
2494cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2495cc11b9c1SAndrei Emeltchenko 	if (ie) {
249685a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
249785a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
249885a1e930SMarcel Holtmann 	}
249985a1e930SMarcel Holtmann 
250085a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
250185a1e930SMarcel Holtmann }
250285a1e930SMarcel Holtmann 
2503a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2504a9de9248SMarcel Holtmann {
2505a9de9248SMarcel Holtmann 	struct inquiry_data data;
2506a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2507a9de9248SMarcel Holtmann 
2508a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2509a9de9248SMarcel Holtmann 
2510a9de9248SMarcel Holtmann 	if (!num_rsp)
2511a9de9248SMarcel Holtmann 		return;
2512a9de9248SMarcel Holtmann 
2513a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2514a9de9248SMarcel Holtmann 
2515a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2516138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2517138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2518a9de9248SMarcel Holtmann 
2519e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2520a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2521a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2522a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2523a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2524a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2525a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2526a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
252741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2528a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
252948264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2530e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2531e17acd40SJohan Hedberg 						NULL);
2532a9de9248SMarcel Holtmann 		}
2533a9de9248SMarcel Holtmann 	} else {
2534a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2535a9de9248SMarcel Holtmann 
2536e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2537a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2538a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2539a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2540a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2541a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2542a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2543a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
254441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2545a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
254648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2547e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2548e17acd40SJohan Hedberg 						NULL);
2549a9de9248SMarcel Holtmann 		}
2550a9de9248SMarcel Holtmann 	}
2551a9de9248SMarcel Holtmann 
2552a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2553a9de9248SMarcel Holtmann }
2554a9de9248SMarcel Holtmann 
2555a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2556a9de9248SMarcel Holtmann {
255741a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
255841a96212SMarcel Holtmann 	struct hci_conn *conn;
255941a96212SMarcel Holtmann 
2560a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
256141a96212SMarcel Holtmann 
256241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
256341a96212SMarcel Holtmann 
256441a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2565ccd556feSJohan Hedberg 	if (!conn)
2566ccd556feSJohan Hedberg 		goto unlock;
2567ccd556feSJohan Hedberg 
2568769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
256941a96212SMarcel Holtmann 		struct inquiry_entry *ie;
257041a96212SMarcel Holtmann 
2571cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2572cc11b9c1SAndrei Emeltchenko 		if (ie)
257341a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
257441a96212SMarcel Holtmann 
257541a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
257641a96212SMarcel Holtmann 	}
257741a96212SMarcel Holtmann 
2578ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2579ccd556feSJohan Hedberg 		goto unlock;
2580ccd556feSJohan Hedberg 
2581127178d2SJohan Hedberg 	if (!ev->status) {
2582127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2583127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2584127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2585127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2586127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2587127178d2SJohan Hedberg 	}
2588392599b9SJohan Hedberg 
2589127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2590769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2591769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2592769be974SMarcel Holtmann 		hci_conn_put(conn);
2593769be974SMarcel Holtmann 	}
2594769be974SMarcel Holtmann 
2595ccd556feSJohan Hedberg unlock:
259641a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2597a9de9248SMarcel Holtmann }
2598a9de9248SMarcel Holtmann 
2599a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2600a9de9248SMarcel Holtmann {
2601b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2602b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2603b6a0dc82SMarcel Holtmann 
2604b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2605b6a0dc82SMarcel Holtmann 
2606b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2607b6a0dc82SMarcel Holtmann 
2608b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
26099dc0a3afSMarcel Holtmann 	if (!conn) {
26109dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
26119dc0a3afSMarcel Holtmann 			goto unlock;
26129dc0a3afSMarcel Holtmann 
26139dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2614b6a0dc82SMarcel Holtmann 		if (!conn)
2615b6a0dc82SMarcel Holtmann 			goto unlock;
2616b6a0dc82SMarcel Holtmann 
26179dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
26189dc0a3afSMarcel Holtmann 	}
26199dc0a3afSMarcel Holtmann 
2620732547f9SMarcel Holtmann 	switch (ev->status) {
2621732547f9SMarcel Holtmann 	case 0x00:
2622732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2623732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2624732547f9SMarcel Holtmann 
26259eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2626732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2627732547f9SMarcel Holtmann 		break;
2628732547f9SMarcel Holtmann 
2629705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2630732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
26311038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2632732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2633732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2634efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2635efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2636efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2637efc7688bSMarcel Holtmann 			goto unlock;
2638efc7688bSMarcel Holtmann 		}
2639732547f9SMarcel Holtmann 		/* fall through */
2640efc7688bSMarcel Holtmann 
2641732547f9SMarcel Holtmann 	default:
2642b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2643732547f9SMarcel Holtmann 		break;
2644732547f9SMarcel Holtmann 	}
2645b6a0dc82SMarcel Holtmann 
2646b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2647b6a0dc82SMarcel Holtmann 	if (ev->status)
2648b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2649b6a0dc82SMarcel Holtmann 
2650b6a0dc82SMarcel Holtmann unlock:
2651b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2652a9de9248SMarcel Holtmann }
2653a9de9248SMarcel Holtmann 
2654a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2655a9de9248SMarcel Holtmann {
2656a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2657a9de9248SMarcel Holtmann }
2658a9de9248SMarcel Holtmann 
265904837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
266004837f64SMarcel Holtmann {
2661a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
266204837f64SMarcel Holtmann 
266304837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
266404837f64SMarcel Holtmann }
266504837f64SMarcel Holtmann 
2666a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2667a9de9248SMarcel Holtmann {
2668a9de9248SMarcel Holtmann 	struct inquiry_data data;
2669a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2670a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2671a9de9248SMarcel Holtmann 
2672a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2673a9de9248SMarcel Holtmann 
2674a9de9248SMarcel Holtmann 	if (!num_rsp)
2675a9de9248SMarcel Holtmann 		return;
2676a9de9248SMarcel Holtmann 
2677a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2678a9de9248SMarcel Holtmann 
2679e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2680a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2681a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2682a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2683a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2684a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2685a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2686a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
268741a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2688a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
268948264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
26904c659c39SJohan Hedberg 				info->dev_class, info->rssi, info->data);
2691a9de9248SMarcel Holtmann 	}
2692a9de9248SMarcel Holtmann 
2693a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2694a9de9248SMarcel Holtmann }
2695a9de9248SMarcel Holtmann 
269617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
269717fa4b9dSJohan Hedberg {
269817fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
269917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
270017fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
270117fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
270217fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
270317fa4b9dSJohan Hedberg 			return 0x02;
270417fa4b9dSJohan Hedberg 		else
270517fa4b9dSJohan Hedberg 			return 0x03;
270617fa4b9dSJohan Hedberg 	}
270717fa4b9dSJohan Hedberg 
270817fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
270917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
271058797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
271117fa4b9dSJohan Hedberg 
271217fa4b9dSJohan Hedberg 	return conn->auth_type;
271317fa4b9dSJohan Hedberg }
271417fa4b9dSJohan Hedberg 
27150493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
27160493684eSMarcel Holtmann {
27170493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
27180493684eSMarcel Holtmann 	struct hci_conn *conn;
27190493684eSMarcel Holtmann 
27200493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
27210493684eSMarcel Holtmann 
27220493684eSMarcel Holtmann 	hci_dev_lock(hdev);
27230493684eSMarcel Holtmann 
27240493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
272503b555e1SJohan Hedberg 	if (!conn)
272603b555e1SJohan Hedberg 		goto unlock;
272703b555e1SJohan Hedberg 
27280493684eSMarcel Holtmann 	hci_conn_hold(conn);
27290493684eSMarcel Holtmann 
273003b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
273103b555e1SJohan Hedberg 		goto unlock;
273203b555e1SJohan Hedberg 
273303b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
273403b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
273517fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
273617fa4b9dSJohan Hedberg 
273717fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
273817fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
27397cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
27407cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
274117fa4b9dSJohan Hedberg 
2742ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2743ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2744ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2745ce85ee13SSzymon Janc 		else
2746ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2747ce85ee13SSzymon Janc 
274817fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
274917fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
275003b555e1SJohan Hedberg 	} else {
275103b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
275203b555e1SJohan Hedberg 
275303b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
27549f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
275503b555e1SJohan Hedberg 
275603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
275703b555e1SJohan Hedberg 							sizeof(cp), &cp);
275803b555e1SJohan Hedberg 	}
275903b555e1SJohan Hedberg 
276003b555e1SJohan Hedberg unlock:
276103b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
276203b555e1SJohan Hedberg }
276303b555e1SJohan Hedberg 
276403b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
276503b555e1SJohan Hedberg {
276603b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
276703b555e1SJohan Hedberg 	struct hci_conn *conn;
276803b555e1SJohan Hedberg 
276903b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
277003b555e1SJohan Hedberg 
277103b555e1SJohan Hedberg 	hci_dev_lock(hdev);
277203b555e1SJohan Hedberg 
277303b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
277403b555e1SJohan Hedberg 	if (!conn)
277503b555e1SJohan Hedberg 		goto unlock;
277603b555e1SJohan Hedberg 
277703b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
277803b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
277903b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
278003b555e1SJohan Hedberg 
278103b555e1SJohan Hedberg unlock:
27820493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
27830493684eSMarcel Holtmann }
27840493684eSMarcel Holtmann 
2785a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2786a5c29683SJohan Hedberg 							struct sk_buff *skb)
2787a5c29683SJohan Hedberg {
2788a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
278955bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
27907a828908SJohan Hedberg 	struct hci_conn *conn;
2791a5c29683SJohan Hedberg 
2792a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
2793a5c29683SJohan Hedberg 
2794a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
2795a5c29683SJohan Hedberg 
27967a828908SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
27977a828908SJohan Hedberg 		goto unlock;
27987a828908SJohan Hedberg 
27997a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
28007a828908SJohan Hedberg 	if (!conn)
28017a828908SJohan Hedberg 		goto unlock;
28027a828908SJohan Hedberg 
28037a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
28047a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
28057a828908SJohan Hedberg 
28067a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
28077a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
28087a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
28097a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
28107a828908SJohan Hedberg 	 * bit set. */
28117a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
28127a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
28137a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
28147a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
28157a828908SJohan Hedberg 		goto unlock;
28167a828908SJohan Hedberg 	}
28177a828908SJohan Hedberg 
28187a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
28197a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
28207a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
282155bc1a37SJohan Hedberg 
282255bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
282355bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
282455bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
282555bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
282655bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
282755bc1a37SJohan Hedberg 			confirm_hint = 1;
282855bc1a37SJohan Hedberg 			goto confirm;
282955bc1a37SJohan Hedberg 		}
283055bc1a37SJohan Hedberg 
28319f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
28329f61656aSJohan Hedberg 						hdev->auto_accept_delay);
28339f61656aSJohan Hedberg 
28349f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
28359f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
28369f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
28379f61656aSJohan Hedberg 			goto unlock;
28389f61656aSJohan Hedberg 		}
28399f61656aSJohan Hedberg 
28407a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
28417a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
28427a828908SJohan Hedberg 		goto unlock;
28437a828908SJohan Hedberg 	}
28447a828908SJohan Hedberg 
284555bc1a37SJohan Hedberg confirm:
2846744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
284755bc1a37SJohan Hedberg 								confirm_hint);
2848a5c29683SJohan Hedberg 
28497a828908SJohan Hedberg unlock:
2850a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
2851a5c29683SJohan Hedberg }
2852a5c29683SJohan Hedberg 
28531143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
28541143d458SBrian Gix 							struct sk_buff *skb)
28551143d458SBrian Gix {
28561143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
28571143d458SBrian Gix 
28581143d458SBrian Gix 	BT_DBG("%s", hdev->name);
28591143d458SBrian Gix 
28601143d458SBrian Gix 	hci_dev_lock(hdev);
28611143d458SBrian Gix 
28621143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
28631143d458SBrian Gix 		mgmt_user_passkey_request(hdev, &ev->bdaddr);
28641143d458SBrian Gix 
28651143d458SBrian Gix 	hci_dev_unlock(hdev);
28661143d458SBrian Gix }
28671143d458SBrian Gix 
28680493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
28690493684eSMarcel Holtmann {
28700493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
28710493684eSMarcel Holtmann 	struct hci_conn *conn;
28720493684eSMarcel Holtmann 
28730493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
28740493684eSMarcel Holtmann 
28750493684eSMarcel Holtmann 	hci_dev_lock(hdev);
28760493684eSMarcel Holtmann 
28770493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
28782a611692SJohan Hedberg 	if (!conn)
28792a611692SJohan Hedberg 		goto unlock;
28802a611692SJohan Hedberg 
28812a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
28822a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
28832a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
28842a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
28852a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
28862a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
2887744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
28882a611692SJohan Hedberg 
28890493684eSMarcel Holtmann 	hci_conn_put(conn);
28900493684eSMarcel Holtmann 
28912a611692SJohan Hedberg unlock:
28920493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
28930493684eSMarcel Holtmann }
28940493684eSMarcel Holtmann 
289541a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
289641a96212SMarcel Holtmann {
289741a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
289841a96212SMarcel Holtmann 	struct inquiry_entry *ie;
289941a96212SMarcel Holtmann 
290041a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
290141a96212SMarcel Holtmann 
290241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
290341a96212SMarcel Holtmann 
2904cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2905cc11b9c1SAndrei Emeltchenko 	if (ie)
290641a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
290741a96212SMarcel Holtmann 
290841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
290941a96212SMarcel Holtmann }
291041a96212SMarcel Holtmann 
29112763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
29122763eda6SSzymon Janc 							struct sk_buff *skb)
29132763eda6SSzymon Janc {
29142763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
29152763eda6SSzymon Janc 	struct oob_data *data;
29162763eda6SSzymon Janc 
29172763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
29182763eda6SSzymon Janc 
29192763eda6SSzymon Janc 	hci_dev_lock(hdev);
29202763eda6SSzymon Janc 
2921e1ba1f15SSzymon Janc 	if (!test_bit(HCI_MGMT, &hdev->flags))
2922e1ba1f15SSzymon Janc 		goto unlock;
2923e1ba1f15SSzymon Janc 
29242763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
29252763eda6SSzymon Janc 	if (data) {
29262763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
29272763eda6SSzymon Janc 
29282763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
29292763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
29302763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
29312763eda6SSzymon Janc 
29322763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
29332763eda6SSzymon Janc 									&cp);
29342763eda6SSzymon Janc 	} else {
29352763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
29362763eda6SSzymon Janc 
29372763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
29382763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
29392763eda6SSzymon Janc 									&cp);
29402763eda6SSzymon Janc 	}
29412763eda6SSzymon Janc 
2942e1ba1f15SSzymon Janc unlock:
29432763eda6SSzymon Janc 	hci_dev_unlock(hdev);
29442763eda6SSzymon Janc }
29452763eda6SSzymon Janc 
2946fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2947fcd89c09SVille Tervo {
2948fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2949fcd89c09SVille Tervo 	struct hci_conn *conn;
2950fcd89c09SVille Tervo 
2951fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
2952fcd89c09SVille Tervo 
2953fcd89c09SVille Tervo 	hci_dev_lock(hdev);
2954fcd89c09SVille Tervo 
2955fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2956b62f328bSVille Tervo 	if (!conn) {
2957b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2958b62f328bSVille Tervo 		if (!conn) {
2959b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
2960b62f328bSVille Tervo 			hci_dev_unlock(hdev);
2961b62f328bSVille Tervo 			return;
2962b62f328bSVille Tervo 		}
296329b7988aSAndre Guedes 
296429b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
2965b62f328bSVille Tervo 	}
2966fcd89c09SVille Tervo 
2967fcd89c09SVille Tervo 	if (ev->status) {
296848264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
296948264f06SJohan Hedberg 						conn->dst_type, ev->status);
2970fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
2971fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
2972fcd89c09SVille Tervo 		hci_conn_del(conn);
2973fcd89c09SVille Tervo 		goto unlock;
2974fcd89c09SVille Tervo 	}
2975fcd89c09SVille Tervo 
297648264f06SJohan Hedberg 	mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
297783bc71b4SVinicius Costa Gomes 
29787b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
2979fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
2980fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
2981fcd89c09SVille Tervo 
2982fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
2983fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
2984fcd89c09SVille Tervo 
2985fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
2986fcd89c09SVille Tervo 
2987fcd89c09SVille Tervo unlock:
2988fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
2989fcd89c09SVille Tervo }
2990fcd89c09SVille Tervo 
29919aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
29929aa04c91SAndre Guedes 						struct sk_buff *skb)
29939aa04c91SAndre Guedes {
2994e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
2995e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
29969aa04c91SAndre Guedes 
29979aa04c91SAndre Guedes 	hci_dev_lock(hdev);
29989aa04c91SAndre Guedes 
2999e95beb41SAndre Guedes 	while (num_reports--) {
3000e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3001e95beb41SAndre Guedes 
30029aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
30039aa04c91SAndre Guedes 
3004e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
30059aa04c91SAndre Guedes 	}
30069aa04c91SAndre Guedes 
30079aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
30089aa04c91SAndre Guedes }
30099aa04c91SAndre Guedes 
3010a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3011a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3012a7a595f6SVinicius Costa Gomes {
3013a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3014a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3015bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3016a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3017bea710feSVinicius Costa Gomes 	struct link_key *ltk;
3018a7a595f6SVinicius Costa Gomes 
3019a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3020a7a595f6SVinicius Costa Gomes 
3021a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3022a7a595f6SVinicius Costa Gomes 
3023a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3024bea710feSVinicius Costa Gomes 	if (conn == NULL)
3025bea710feSVinicius Costa Gomes 		goto not_found;
3026a7a595f6SVinicius Costa Gomes 
3027bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3028bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3029bea710feSVinicius Costa Gomes 		goto not_found;
3030bea710feSVinicius Costa Gomes 
3031bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3032a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3033726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
3034a7a595f6SVinicius Costa Gomes 
3035a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3036a7a595f6SVinicius Costa Gomes 
3037a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3038bea710feSVinicius Costa Gomes 
3039bea710feSVinicius Costa Gomes 	return;
3040bea710feSVinicius Costa Gomes 
3041bea710feSVinicius Costa Gomes not_found:
3042bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3043bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3044bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3045a7a595f6SVinicius Costa Gomes }
3046a7a595f6SVinicius Costa Gomes 
3047fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3048fcd89c09SVille Tervo {
3049fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3050fcd89c09SVille Tervo 
3051fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3052fcd89c09SVille Tervo 
3053fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3054fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3055fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3056fcd89c09SVille Tervo 		break;
3057fcd89c09SVille Tervo 
30589aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
30599aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
30609aa04c91SAndre Guedes 		break;
30619aa04c91SAndre Guedes 
3062a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3063a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3064a7a595f6SVinicius Costa Gomes 		break;
3065a7a595f6SVinicius Costa Gomes 
3066fcd89c09SVille Tervo 	default:
3067fcd89c09SVille Tervo 		break;
3068fcd89c09SVille Tervo 	}
3069fcd89c09SVille Tervo }
3070fcd89c09SVille Tervo 
30711da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
30721da177e4SLinus Torvalds {
3073a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3074a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
30751da177e4SLinus Torvalds 
30761da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
30771da177e4SLinus Torvalds 
3078a9de9248SMarcel Holtmann 	switch (event) {
30791da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
30801da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
30811da177e4SLinus Torvalds 		break;
30821da177e4SLinus Torvalds 
30831da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
30841da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
30851da177e4SLinus Torvalds 		break;
30861da177e4SLinus Torvalds 
3087a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3088a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
308921d9e30eSMarcel Holtmann 		break;
309021d9e30eSMarcel Holtmann 
30911da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
30921da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
30931da177e4SLinus Torvalds 		break;
30941da177e4SLinus Torvalds 
30951da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
30961da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
30971da177e4SLinus Torvalds 		break;
30981da177e4SLinus Torvalds 
30991da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
31001da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
31011da177e4SLinus Torvalds 		break;
31021da177e4SLinus Torvalds 
3103a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3104a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3105a9de9248SMarcel Holtmann 		break;
3106a9de9248SMarcel Holtmann 
31071da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
31081da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
31091da177e4SLinus Torvalds 		break;
31101da177e4SLinus Torvalds 
3111a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3112a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3113a9de9248SMarcel Holtmann 		break;
3114a9de9248SMarcel Holtmann 
3115a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3116a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3117a9de9248SMarcel Holtmann 		break;
3118a9de9248SMarcel Holtmann 
3119a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3120a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3121a9de9248SMarcel Holtmann 		break;
3122a9de9248SMarcel Holtmann 
3123a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3124a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3125a9de9248SMarcel Holtmann 		break;
3126a9de9248SMarcel Holtmann 
3127a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3128a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3129a9de9248SMarcel Holtmann 		break;
3130a9de9248SMarcel Holtmann 
3131a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3132a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3133a9de9248SMarcel Holtmann 		break;
3134a9de9248SMarcel Holtmann 
3135a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3136a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3137a9de9248SMarcel Holtmann 		break;
3138a9de9248SMarcel Holtmann 
3139a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3140a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3141a9de9248SMarcel Holtmann 		break;
3142a9de9248SMarcel Holtmann 
3143a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3144a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
31451da177e4SLinus Torvalds 		break;
31461da177e4SLinus Torvalds 
31471da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
31481da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
31491da177e4SLinus Torvalds 		break;
31501da177e4SLinus Torvalds 
31511da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
31521da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
31531da177e4SLinus Torvalds 		break;
31541da177e4SLinus Torvalds 
31551da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
31561da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
31571da177e4SLinus Torvalds 		break;
31581da177e4SLinus Torvalds 
31591da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
31601da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
31611da177e4SLinus Torvalds 		break;
31621da177e4SLinus Torvalds 
3163a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3164a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3165a8746417SMarcel Holtmann 		break;
3166a8746417SMarcel Holtmann 
316785a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
316885a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
316985a1e930SMarcel Holtmann 		break;
317085a1e930SMarcel Holtmann 
3171a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3172a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3173a9de9248SMarcel Holtmann 		break;
3174a9de9248SMarcel Holtmann 
3175a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3176a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3177a9de9248SMarcel Holtmann 		break;
3178a9de9248SMarcel Holtmann 
3179a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3180a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3181a9de9248SMarcel Holtmann 		break;
3182a9de9248SMarcel Holtmann 
3183a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3184a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3185a9de9248SMarcel Holtmann 		break;
3186a9de9248SMarcel Holtmann 
318704837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
318804837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
318904837f64SMarcel Holtmann 		break;
319004837f64SMarcel Holtmann 
3191a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3192a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
31931da177e4SLinus Torvalds 		break;
31941da177e4SLinus Torvalds 
31950493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
31960493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
31970493684eSMarcel Holtmann 		break;
31980493684eSMarcel Holtmann 
319903b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
320003b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
320103b555e1SJohan Hedberg 		break;
320203b555e1SJohan Hedberg 
3203a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3204a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3205a5c29683SJohan Hedberg 		break;
3206a5c29683SJohan Hedberg 
32071143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
32081143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
32091143d458SBrian Gix 		break;
32101143d458SBrian Gix 
32110493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
32120493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
32130493684eSMarcel Holtmann 		break;
32140493684eSMarcel Holtmann 
321541a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
321641a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
321741a96212SMarcel Holtmann 		break;
321841a96212SMarcel Holtmann 
3219fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3220fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3221fcd89c09SVille Tervo 		break;
3222fcd89c09SVille Tervo 
32232763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
32242763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
32252763eda6SSzymon Janc 		break;
32262763eda6SSzymon Janc 
32271da177e4SLinus Torvalds 	default:
3228a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
32291da177e4SLinus Torvalds 		break;
32301da177e4SLinus Torvalds 	}
32311da177e4SLinus Torvalds 
32321da177e4SLinus Torvalds 	kfree_skb(skb);
32331da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
32341da177e4SLinus Torvalds }
32351da177e4SLinus Torvalds 
32361da177e4SLinus Torvalds /* Generate internal stack event */
32371da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
32381da177e4SLinus Torvalds {
32391da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
32401da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
32411da177e4SLinus Torvalds 	struct sk_buff *skb;
32421da177e4SLinus Torvalds 
32431da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
32441da177e4SLinus Torvalds 	if (!skb)
32451da177e4SLinus Torvalds 		return;
32461da177e4SLinus Torvalds 
32471da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
32481da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
32491da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
32501da177e4SLinus Torvalds 
32511da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
32521da177e4SLinus Torvalds 	ev->type = type;
32531da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
32541da177e4SLinus Torvalds 
3255576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3256a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3257576c7d85SMarcel Holtmann 
32580d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
32591da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3260eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
32611da177e4SLinus Torvalds 	kfree_skb(skb);
32621da177e4SLinus Torvalds }
3263e6100a25SAndre Guedes 
3264669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3265e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3266