xref: /openbmc/linux/net/bluetooth/hci_event.c (revision c5993de8)
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 
3813c54711cSGustavo F. Padovan 	if (hdev->notify)
382a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
383a9de9248SMarcel Holtmann }
384a9de9248SMarcel Holtmann 
385a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
386a9de9248SMarcel Holtmann {
387a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
388f383f275SMarcel Holtmann 	__u16 setting;
389a9de9248SMarcel Holtmann 	void *sent;
390a9de9248SMarcel Holtmann 
391a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
392a9de9248SMarcel Holtmann 
393f383f275SMarcel Holtmann 	if (status)
394f383f275SMarcel Holtmann 		return;
395f383f275SMarcel Holtmann 
396a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
397a9de9248SMarcel Holtmann 	if (!sent)
398a9de9248SMarcel Holtmann 		return;
399a9de9248SMarcel Holtmann 
400f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4011da177e4SLinus Torvalds 
402f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
403f383f275SMarcel Holtmann 		return;
404f383f275SMarcel Holtmann 
4051da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4061da177e4SLinus Torvalds 
407a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4081da177e4SLinus Torvalds 
4093c54711cSGustavo F. Padovan 	if (hdev->notify)
4101da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4111da177e4SLinus Torvalds }
4121da177e4SLinus Torvalds 
413a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4141da177e4SLinus Torvalds {
415a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4161da177e4SLinus Torvalds 
417a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4181da177e4SLinus Torvalds 
41923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4201143e5a6SMarcel Holtmann }
4211143e5a6SMarcel Holtmann 
422333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
423333140b5SMarcel Holtmann {
424333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
425333140b5SMarcel Holtmann 
426333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
427333140b5SMarcel Holtmann 
428333140b5SMarcel Holtmann 	if (rp->status)
429333140b5SMarcel Holtmann 		return;
430333140b5SMarcel Holtmann 
431333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
432333140b5SMarcel Holtmann }
433333140b5SMarcel Holtmann 
434333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
435333140b5SMarcel Holtmann {
436333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
437333140b5SMarcel Holtmann 	void *sent;
438333140b5SMarcel Holtmann 
439333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
440333140b5SMarcel Holtmann 
441333140b5SMarcel Holtmann 	if (status)
442333140b5SMarcel Holtmann 		return;
443333140b5SMarcel Holtmann 
444333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
445333140b5SMarcel Holtmann 	if (!sent)
446333140b5SMarcel Holtmann 		return;
447333140b5SMarcel Holtmann 
448333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
449333140b5SMarcel Holtmann }
450333140b5SMarcel Holtmann 
451d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
452d5859e22SJohan Hedberg {
453d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
454d5859e22SJohan Hedberg 		return 2;
455d5859e22SJohan Hedberg 
456d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
457d5859e22SJohan Hedberg 		return 1;
458d5859e22SJohan Hedberg 
459d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
460d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
461d5859e22SJohan Hedberg 		return 1;
462d5859e22SJohan Hedberg 
463d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
464d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
465d5859e22SJohan Hedberg 			return 1;
466d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
467d5859e22SJohan Hedberg 			return 1;
468d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
469d5859e22SJohan Hedberg 			return 1;
470d5859e22SJohan Hedberg 	}
471d5859e22SJohan Hedberg 
472d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
473d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
474d5859e22SJohan Hedberg 		return 1;
475d5859e22SJohan Hedberg 
476d5859e22SJohan Hedberg 	return 0;
477d5859e22SJohan Hedberg }
478d5859e22SJohan Hedberg 
479d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
480d5859e22SJohan Hedberg {
481d5859e22SJohan Hedberg 	u8 mode;
482d5859e22SJohan Hedberg 
483d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
484d5859e22SJohan Hedberg 
485d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
486d5859e22SJohan Hedberg }
487d5859e22SJohan Hedberg 
488d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
489d5859e22SJohan Hedberg {
490d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
491d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
492d5859e22SJohan Hedberg 	 * command otherwise */
493d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
494d5859e22SJohan Hedberg 
4956de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
4966de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
4975a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
4986de6c18dSVille Tervo 		return;
4996de6c18dSVille Tervo 
500d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
501d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
502d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
503d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
504d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
505d5859e22SJohan Hedberg 
506d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
507d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
508d5859e22SJohan Hedberg 
509d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
510d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
511d5859e22SJohan Hedberg 
512d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
513d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
514d5859e22SJohan Hedberg 
515d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
516d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
517d5859e22SJohan Hedberg 
518d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
519d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
520d5859e22SJohan Hedberg 
521d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
522d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
523d5859e22SJohan Hedberg 
524d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
525d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
526d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
527d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
528d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
529d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
530d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
531d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
532d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
533d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
534d5859e22SJohan Hedberg 					 * Features Notification */
535d5859e22SJohan Hedberg 	}
536d5859e22SJohan Hedberg 
537d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
538d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
539d5859e22SJohan Hedberg 
540d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
541d5859e22SJohan Hedberg }
542d5859e22SJohan Hedberg 
543e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
544e6100a25SAndre Guedes {
545e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
546e6100a25SAndre Guedes 
547e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
548e6100a25SAndre Guedes 
549e6100a25SAndre Guedes 	if (enable_le) {
550e6100a25SAndre Guedes 		cp.le = 1;
551e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
552e6100a25SAndre Guedes 	}
553e6100a25SAndre Guedes 
554e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
555e6100a25SAndre Guedes }
556e6100a25SAndre Guedes 
557d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
558d5859e22SJohan Hedberg {
559e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
560e61ef499SAndrei Emeltchenko 		return;
561e61ef499SAndrei Emeltchenko 
562d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
563d5859e22SJohan Hedberg 
564d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
565d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
566d5859e22SJohan Hedberg 
567d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
568d5859e22SJohan Hedberg 		u8 mode = 0x01;
569d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
570d5859e22SJohan Hedberg 	}
571d5859e22SJohan Hedberg 
572d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
573d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
574d5859e22SJohan Hedberg 
575d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
576d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
577971e3a4bSAndre Guedes 
578971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
579971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
580971e3a4bSAndre Guedes 
581971e3a4bSAndre Guedes 		cp.page = 0x01;
582971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
583971e3a4bSAndre Guedes 							sizeof(cp), &cp);
584971e3a4bSAndre Guedes 	}
585e6100a25SAndre Guedes 
586e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
587e6100a25SAndre Guedes 		hci_set_le_support(hdev);
588d5859e22SJohan Hedberg }
589d5859e22SJohan Hedberg 
590a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
591a9de9248SMarcel Holtmann {
592a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5931143e5a6SMarcel Holtmann 
594a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5951143e5a6SMarcel Holtmann 
596a9de9248SMarcel Holtmann 	if (rp->status)
597a9de9248SMarcel Holtmann 		return;
5981143e5a6SMarcel Holtmann 
599a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
600e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
601d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
602e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
603d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6041da177e4SLinus Torvalds 
605a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
606a9de9248SMarcel Holtmann 					hdev->manufacturer,
607a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
608d5859e22SJohan Hedberg 
609d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
610d5859e22SJohan Hedberg 		hci_setup(hdev);
611d5859e22SJohan Hedberg }
612d5859e22SJohan Hedberg 
613d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
614d5859e22SJohan Hedberg {
615d5859e22SJohan Hedberg 	u16 link_policy = 0;
616d5859e22SJohan Hedberg 
617d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
618d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
619d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
620d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
621d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
622d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
623d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
624d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
625d5859e22SJohan Hedberg 
626d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
627d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
628d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6291da177e4SLinus Torvalds }
6301da177e4SLinus Torvalds 
631a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
632a9de9248SMarcel Holtmann {
633a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
634a9de9248SMarcel Holtmann 
635a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
636a9de9248SMarcel Holtmann 
637a9de9248SMarcel Holtmann 	if (rp->status)
638d5859e22SJohan Hedberg 		goto done;
639a9de9248SMarcel Holtmann 
640a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
641d5859e22SJohan Hedberg 
642d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
643d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
644d5859e22SJohan Hedberg 
645d5859e22SJohan Hedberg done:
646d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
647a9de9248SMarcel Holtmann }
648a9de9248SMarcel Holtmann 
649a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
650a9de9248SMarcel Holtmann {
651a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
652a9de9248SMarcel Holtmann 
653a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
654a9de9248SMarcel Holtmann 
655a9de9248SMarcel Holtmann 	if (rp->status)
656a9de9248SMarcel Holtmann 		return;
657a9de9248SMarcel Holtmann 
658a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6591da177e4SLinus Torvalds 
6601da177e4SLinus Torvalds 	/* Adjust default settings according to features
6611da177e4SLinus Torvalds 	 * supported by device. */
662a9de9248SMarcel Holtmann 
6631da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6641da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6651da177e4SLinus Torvalds 
6661da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6671da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6681da177e4SLinus Torvalds 
6695b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6701da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6715b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6725b7f9909SMarcel Holtmann 	}
6731da177e4SLinus Torvalds 
6745b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6751da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6765b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6775b7f9909SMarcel Holtmann 	}
6785b7f9909SMarcel Holtmann 
6795b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6805b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6815b7f9909SMarcel Holtmann 
6825b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6835b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6845b7f9909SMarcel Holtmann 
6855b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6865b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6871da177e4SLinus Torvalds 
688efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
689efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
690efc7688bSMarcel Holtmann 
691efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
692efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
693efc7688bSMarcel Holtmann 
694efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
695efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
696efc7688bSMarcel Holtmann 
697a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
698a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
699a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
700a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
701a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7021da177e4SLinus Torvalds }
7031da177e4SLinus Torvalds 
704971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
705971e3a4bSAndre Guedes 							struct sk_buff *skb)
706971e3a4bSAndre Guedes {
707971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
708971e3a4bSAndre Guedes 
709971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
710971e3a4bSAndre Guedes 
711971e3a4bSAndre Guedes 	if (rp->status)
712971e3a4bSAndre Guedes 		return;
713971e3a4bSAndre Guedes 
714b5b32b65SAndre Guedes 	switch (rp->page) {
715b5b32b65SAndre Guedes 	case 0:
716b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
717b5b32b65SAndre Guedes 		break;
718b5b32b65SAndre Guedes 	case 1:
71959e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
720b5b32b65SAndre Guedes 		break;
721b5b32b65SAndre Guedes 	}
722971e3a4bSAndre Guedes 
723971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
724971e3a4bSAndre Guedes }
725971e3a4bSAndre Guedes 
7261e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7271e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7281e89cffbSAndrei Emeltchenko {
7291e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7301e89cffbSAndrei Emeltchenko 
7311e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7321e89cffbSAndrei Emeltchenko 
7331e89cffbSAndrei Emeltchenko 	if (rp->status)
7341e89cffbSAndrei Emeltchenko 		return;
7351e89cffbSAndrei Emeltchenko 
7361e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7371e89cffbSAndrei Emeltchenko 
7381e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7391e89cffbSAndrei Emeltchenko }
7401e89cffbSAndrei Emeltchenko 
741a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
742a9de9248SMarcel Holtmann {
743a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
744a9de9248SMarcel Holtmann 
745a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
746a9de9248SMarcel Holtmann 
747a9de9248SMarcel Holtmann 	if (rp->status)
748a9de9248SMarcel Holtmann 		return;
749a9de9248SMarcel Holtmann 
750a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
751a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
752a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
753a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
754da1f5198SMarcel Holtmann 
755da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
756da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
757da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
758da1f5198SMarcel Holtmann 	}
759da1f5198SMarcel Holtmann 
760da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
761da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7621da177e4SLinus Torvalds 
763a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
764a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
765a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7661da177e4SLinus Torvalds }
7671da177e4SLinus Torvalds 
768a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
769a9de9248SMarcel Holtmann {
770a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7711da177e4SLinus Torvalds 
772a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
773a9de9248SMarcel Holtmann 
774a9de9248SMarcel Holtmann 	if (!rp->status)
775a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
776a9de9248SMarcel Holtmann 
77723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
77823bb5763SJohan Hedberg }
77923bb5763SJohan Hedberg 
780350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
781350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
782350ee4cfSAndrei Emeltchenko {
783350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
784350ee4cfSAndrei Emeltchenko 
785350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
786350ee4cfSAndrei Emeltchenko 
787350ee4cfSAndrei Emeltchenko 	if (rp->status)
788350ee4cfSAndrei Emeltchenko 		return;
789350ee4cfSAndrei Emeltchenko 
790350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
791350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
792350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
793350ee4cfSAndrei Emeltchenko 
794350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
795350ee4cfSAndrei Emeltchenko 
796350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
797350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
798350ee4cfSAndrei Emeltchenko 
799350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
800350ee4cfSAndrei Emeltchenko }
801350ee4cfSAndrei Emeltchenko 
80223bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
80323bb5763SJohan Hedberg {
80423bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
80523bb5763SJohan Hedberg 
80623bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
80723bb5763SJohan Hedberg 
80823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8091da177e4SLinus Torvalds }
8101da177e4SLinus Torvalds 
811928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
812928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
813928abaa7SAndrei Emeltchenko {
814928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
815928abaa7SAndrei Emeltchenko 
816928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
817928abaa7SAndrei Emeltchenko 
818928abaa7SAndrei Emeltchenko 	if (rp->status)
819928abaa7SAndrei Emeltchenko 		return;
820928abaa7SAndrei Emeltchenko 
821928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
822928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
823928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
824928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
825928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
826928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
827928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
828928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
829928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
830928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
831928abaa7SAndrei Emeltchenko 
832928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
833928abaa7SAndrei Emeltchenko }
834928abaa7SAndrei Emeltchenko 
835b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
836b0916ea0SJohan Hedberg 							struct sk_buff *skb)
837b0916ea0SJohan Hedberg {
838b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
839b0916ea0SJohan Hedberg 
840b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
841b0916ea0SJohan Hedberg 
842b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
843b0916ea0SJohan Hedberg }
844b0916ea0SJohan Hedberg 
845d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
846d5859e22SJohan Hedberg {
847d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
848d5859e22SJohan Hedberg 
849d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
850d5859e22SJohan Hedberg 
851d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
852d5859e22SJohan Hedberg }
853d5859e22SJohan Hedberg 
854d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
855d5859e22SJohan Hedberg 							struct sk_buff *skb)
856d5859e22SJohan Hedberg {
857d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
858d5859e22SJohan Hedberg 
859d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
860d5859e22SJohan Hedberg 
861d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
862d5859e22SJohan Hedberg }
863d5859e22SJohan Hedberg 
864d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
865d5859e22SJohan Hedberg 							struct sk_buff *skb)
866d5859e22SJohan Hedberg {
867d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
868d5859e22SJohan Hedberg 
869d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
870d5859e22SJohan Hedberg 
871d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
872d5859e22SJohan Hedberg }
873d5859e22SJohan Hedberg 
874d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
875d5859e22SJohan Hedberg {
876d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
877d5859e22SJohan Hedberg 
878d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
879d5859e22SJohan Hedberg 
880d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
881d5859e22SJohan Hedberg }
882d5859e22SJohan Hedberg 
883980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
884980e1a53SJohan Hedberg {
885980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
886980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
887980e1a53SJohan Hedberg 	struct hci_conn *conn;
888980e1a53SJohan Hedberg 
889980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
890980e1a53SJohan Hedberg 
89156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
89256e5cb86SJohan Hedberg 
893980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
894744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
895980e1a53SJohan Hedberg 
896980e1a53SJohan Hedberg 	if (rp->status != 0)
89756e5cb86SJohan Hedberg 		goto unlock;
898980e1a53SJohan Hedberg 
899980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
900980e1a53SJohan Hedberg 	if (!cp)
90156e5cb86SJohan Hedberg 		goto unlock;
902980e1a53SJohan Hedberg 
903980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
904980e1a53SJohan Hedberg 	if (conn)
905980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
90656e5cb86SJohan Hedberg 
90756e5cb86SJohan Hedberg unlock:
90856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
909980e1a53SJohan Hedberg }
910980e1a53SJohan Hedberg 
911980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
912980e1a53SJohan Hedberg {
913980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
914980e1a53SJohan Hedberg 
915980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
916980e1a53SJohan Hedberg 
91756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
91856e5cb86SJohan Hedberg 
919980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
920744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
921980e1a53SJohan Hedberg 								rp->status);
92256e5cb86SJohan Hedberg 
92356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
924980e1a53SJohan Hedberg }
92556e5cb86SJohan Hedberg 
9266ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9276ed58ec5SVille Tervo 				       struct sk_buff *skb)
9286ed58ec5SVille Tervo {
9296ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9306ed58ec5SVille Tervo 
9316ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9326ed58ec5SVille Tervo 
9336ed58ec5SVille Tervo 	if (rp->status)
9346ed58ec5SVille Tervo 		return;
9356ed58ec5SVille Tervo 
9366ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9376ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9386ed58ec5SVille Tervo 
9396ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9406ed58ec5SVille Tervo 
9416ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9426ed58ec5SVille Tervo 
9436ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9446ed58ec5SVille Tervo }
945980e1a53SJohan Hedberg 
946a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
947a5c29683SJohan Hedberg {
948a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
949a5c29683SJohan Hedberg 
950a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
951a5c29683SJohan Hedberg 
95256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
95356e5cb86SJohan Hedberg 
954a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
955744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
956a5c29683SJohan Hedberg 								rp->status);
95756e5cb86SJohan Hedberg 
95856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
959a5c29683SJohan Hedberg }
960a5c29683SJohan Hedberg 
961a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
962a5c29683SJohan Hedberg 							struct sk_buff *skb)
963a5c29683SJohan Hedberg {
964a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
965a5c29683SJohan Hedberg 
966a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
967a5c29683SJohan Hedberg 
96856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96956e5cb86SJohan Hedberg 
970a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
971744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
972a5c29683SJohan Hedberg 								rp->status);
97356e5cb86SJohan Hedberg 
97456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
975a5c29683SJohan Hedberg }
976a5c29683SJohan Hedberg 
9771143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9781143d458SBrian Gix {
9791143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9801143d458SBrian Gix 
9811143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9821143d458SBrian Gix 
9831143d458SBrian Gix 	hci_dev_lock(hdev);
9841143d458SBrian Gix 
9851143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
9861143d458SBrian Gix 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
9871143d458SBrian Gix 								rp->status);
9881143d458SBrian Gix 
9891143d458SBrian Gix 	hci_dev_unlock(hdev);
9901143d458SBrian Gix }
9911143d458SBrian Gix 
9921143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9931143d458SBrian Gix 							struct sk_buff *skb)
9941143d458SBrian Gix {
9951143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9961143d458SBrian Gix 
9971143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9981143d458SBrian Gix 
9991143d458SBrian Gix 	hci_dev_lock(hdev);
10001143d458SBrian Gix 
10011143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
10021143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
10031143d458SBrian Gix 								rp->status);
10041143d458SBrian Gix 
10051143d458SBrian Gix 	hci_dev_unlock(hdev);
10061143d458SBrian Gix }
10071143d458SBrian Gix 
1008c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1009c35938b2SSzymon Janc 							struct sk_buff *skb)
1010c35938b2SSzymon Janc {
1011c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1012c35938b2SSzymon Janc 
1013c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1014c35938b2SSzymon Janc 
101556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1016744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1017c35938b2SSzymon Janc 						rp->randomizer, rp->status);
101856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1019c35938b2SSzymon Janc }
1020c35938b2SSzymon Janc 
102107f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
102207f7fa5dSAndre Guedes {
102307f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
102407f7fa5dSAndre Guedes 
102507f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
102607f7fa5dSAndre Guedes }
102707f7fa5dSAndre Guedes 
1028eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1029eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1030eb9d91f5SAndre Guedes {
1031eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1032eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1033eb9d91f5SAndre Guedes 
1034eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1035eb9d91f5SAndre Guedes 
1036eb9d91f5SAndre Guedes 	if (status)
1037eb9d91f5SAndre Guedes 		return;
1038eb9d91f5SAndre Guedes 
1039eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1040eb9d91f5SAndre Guedes 	if (!cp)
1041eb9d91f5SAndre Guedes 		return;
1042eb9d91f5SAndre Guedes 
104368a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
104468a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
1045d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1046d23264a8SAndre Guedes 
1047db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1048a8f13c8cSAndre Guedes 
1049a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1050eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1051a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
105268a8aea4SAndrei Emeltchenko 		break;
105368a8aea4SAndrei Emeltchenko 
105468a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1055d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1056d23264a8SAndre Guedes 
1057d084329eSAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
105868a8aea4SAndrei Emeltchenko 		break;
105968a8aea4SAndrei Emeltchenko 
106068a8aea4SAndrei Emeltchenko 	default:
106168a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
106268a8aea4SAndrei Emeltchenko 		break;
106335815085SAndre Guedes 	}
1064eb9d91f5SAndre Guedes }
1065eb9d91f5SAndre Guedes 
1066a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1067a7a595f6SVinicius Costa Gomes {
1068a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1069a7a595f6SVinicius Costa Gomes 
1070a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1071a7a595f6SVinicius Costa Gomes 
1072a7a595f6SVinicius Costa Gomes 	if (rp->status)
1073a7a595f6SVinicius Costa Gomes 		return;
1074a7a595f6SVinicius Costa Gomes 
1075a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1076a7a595f6SVinicius Costa Gomes }
1077a7a595f6SVinicius Costa Gomes 
1078a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1079a7a595f6SVinicius Costa Gomes {
1080a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1081a7a595f6SVinicius Costa Gomes 
1082a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1083a7a595f6SVinicius Costa Gomes 
1084a7a595f6SVinicius Costa Gomes 	if (rp->status)
1085a7a595f6SVinicius Costa Gomes 		return;
1086a7a595f6SVinicius Costa Gomes 
1087a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1088a7a595f6SVinicius Costa Gomes }
1089a7a595f6SVinicius Costa Gomes 
1090f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1091f9b49306SAndre Guedes 							struct sk_buff *skb)
1092f9b49306SAndre Guedes {
1093f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1094f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1095f9b49306SAndre Guedes 
1096f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1097f9b49306SAndre Guedes 
1098f9b49306SAndre Guedes 	if (status)
1099f9b49306SAndre Guedes 		return;
1100f9b49306SAndre Guedes 
1101f9b49306SAndre Guedes 	cp.page = 0x01;
1102f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1103f9b49306SAndre Guedes }
1104f9b49306SAndre Guedes 
1105a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1106a9de9248SMarcel Holtmann {
1107a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1108a9de9248SMarcel Holtmann 
1109a9de9248SMarcel Holtmann 	if (status) {
111023bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1111a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
111256e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1113164a6e78SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
11147a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
111556e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1116314b2381SJohan Hedberg 		return;
1117314b2381SJohan Hedberg 	}
1118314b2381SJohan Hedberg 
111989352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
112089352e7dSAndre Guedes 
112156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1122744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 1);
112356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1124a9de9248SMarcel Holtmann }
1125a9de9248SMarcel Holtmann 
11261da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11271da177e4SLinus Torvalds {
1128a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11291da177e4SLinus Torvalds 	struct hci_conn *conn;
11301da177e4SLinus Torvalds 
1131a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1132a9de9248SMarcel Holtmann 
1133a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11341da177e4SLinus Torvalds 	if (!cp)
11351da177e4SLinus Torvalds 		return;
11361da177e4SLinus Torvalds 
11371da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11381da177e4SLinus Torvalds 
11391da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11401da177e4SLinus Torvalds 
1141a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11421da177e4SLinus Torvalds 
11431da177e4SLinus Torvalds 	if (status) {
11441da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11454c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11461da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11471da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11481da177e4SLinus Torvalds 				hci_conn_del(conn);
11494c67bc74SMarcel Holtmann 			} else
11504c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11511da177e4SLinus Torvalds 		}
11521da177e4SLinus Torvalds 	} else {
11531da177e4SLinus Torvalds 		if (!conn) {
11541da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11551da177e4SLinus Torvalds 			if (conn) {
11561da177e4SLinus Torvalds 				conn->out = 1;
11571da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11581da177e4SLinus Torvalds 			} else
1159893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11601da177e4SLinus Torvalds 		}
11611da177e4SLinus Torvalds 	}
11621da177e4SLinus Torvalds 
11631da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11641da177e4SLinus Torvalds }
11651da177e4SLinus Torvalds 
1166a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11671da177e4SLinus Torvalds {
1168a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11691da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11701da177e4SLinus Torvalds 	__u16 handle;
11711da177e4SLinus Torvalds 
1172b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1173b6a0dc82SMarcel Holtmann 
1174a9de9248SMarcel Holtmann 	if (!status)
1175a9de9248SMarcel Holtmann 		return;
1176a9de9248SMarcel Holtmann 
1177a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11781da177e4SLinus Torvalds 	if (!cp)
1179a9de9248SMarcel Holtmann 		return;
11801da177e4SLinus Torvalds 
11811da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11821da177e4SLinus Torvalds 
1183a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
11841da177e4SLinus Torvalds 
11851da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11861da177e4SLinus Torvalds 
11871da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11885a08ecceSAndrei Emeltchenko 	if (acl) {
11895a08ecceSAndrei Emeltchenko 		sco = acl->link;
11905a08ecceSAndrei Emeltchenko 		if (sco) {
11911da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11941da177e4SLinus Torvalds 			hci_conn_del(sco);
11951da177e4SLinus Torvalds 		}
11965a08ecceSAndrei Emeltchenko 	}
11971da177e4SLinus Torvalds 
11981da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11991da177e4SLinus Torvalds }
12001da177e4SLinus Torvalds 
1201f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1202f8558555SMarcel Holtmann {
1203f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1204f8558555SMarcel Holtmann 	struct hci_conn *conn;
1205f8558555SMarcel Holtmann 
1206f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1207f8558555SMarcel Holtmann 
1208f8558555SMarcel Holtmann 	if (!status)
1209f8558555SMarcel Holtmann 		return;
1210f8558555SMarcel Holtmann 
1211f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1212f8558555SMarcel Holtmann 	if (!cp)
1213f8558555SMarcel Holtmann 		return;
1214f8558555SMarcel Holtmann 
1215f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1216f8558555SMarcel Holtmann 
1217f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1218f8558555SMarcel Holtmann 	if (conn) {
1219f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1220f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1221f8558555SMarcel Holtmann 			hci_conn_put(conn);
1222f8558555SMarcel Holtmann 		}
1223f8558555SMarcel Holtmann 	}
1224f8558555SMarcel Holtmann 
1225f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1226f8558555SMarcel Holtmann }
1227f8558555SMarcel Holtmann 
1228f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1229f8558555SMarcel Holtmann {
1230f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1231f8558555SMarcel Holtmann 	struct hci_conn *conn;
1232f8558555SMarcel Holtmann 
1233f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1234f8558555SMarcel Holtmann 
1235f8558555SMarcel Holtmann 	if (!status)
1236f8558555SMarcel Holtmann 		return;
1237f8558555SMarcel Holtmann 
1238f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1239f8558555SMarcel Holtmann 	if (!cp)
1240f8558555SMarcel Holtmann 		return;
1241f8558555SMarcel Holtmann 
1242f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1243f8558555SMarcel Holtmann 
1244f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1245f8558555SMarcel Holtmann 	if (conn) {
1246f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1247f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1248f8558555SMarcel Holtmann 			hci_conn_put(conn);
1249f8558555SMarcel Holtmann 		}
1250f8558555SMarcel Holtmann 	}
1251f8558555SMarcel Holtmann 
1252f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1253f8558555SMarcel Holtmann }
1254f8558555SMarcel Holtmann 
1255127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1256392599b9SJohan Hedberg 							struct hci_conn *conn)
1257392599b9SJohan Hedberg {
1258392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1259392599b9SJohan Hedberg 		return 0;
1260392599b9SJohan Hedberg 
1261765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1262392599b9SJohan Hedberg 		return 0;
1263392599b9SJohan Hedberg 
1264392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1265e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1266392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1267e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1268e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1269392599b9SJohan Hedberg 		return 0;
1270392599b9SJohan Hedberg 
1271392599b9SJohan Hedberg 	return 1;
1272392599b9SJohan Hedberg }
1273392599b9SJohan Hedberg 
1274a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
12751da177e4SLinus Torvalds {
1276127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1277127178d2SJohan Hedberg 	struct hci_conn *conn;
1278127178d2SJohan Hedberg 
1279a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1280127178d2SJohan Hedberg 
1281127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1282127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1283127178d2SJohan Hedberg 	if (!status)
1284127178d2SJohan Hedberg 		return;
1285127178d2SJohan Hedberg 
1286127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1287127178d2SJohan Hedberg 	if (!cp)
1288127178d2SJohan Hedberg 		return;
1289127178d2SJohan Hedberg 
1290127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1291127178d2SJohan Hedberg 
1292127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
129379c6c70cSJohan Hedberg 	if (!conn)
129479c6c70cSJohan Hedberg 		goto unlock;
129579c6c70cSJohan Hedberg 
129679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
129779c6c70cSJohan Hedberg 		goto unlock;
129879c6c70cSJohan Hedberg 
129979c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1300127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1301127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1302127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1303127178d2SJohan Hedberg 	}
1304127178d2SJohan Hedberg 
130579c6c70cSJohan Hedberg unlock:
1306127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1307a9de9248SMarcel Holtmann }
13081da177e4SLinus Torvalds 
1309769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1310769be974SMarcel Holtmann {
1311769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1312769be974SMarcel Holtmann 	struct hci_conn *conn;
1313769be974SMarcel Holtmann 
1314769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1315769be974SMarcel Holtmann 
1316769be974SMarcel Holtmann 	if (!status)
1317769be974SMarcel Holtmann 		return;
1318769be974SMarcel Holtmann 
1319769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1320769be974SMarcel Holtmann 	if (!cp)
1321769be974SMarcel Holtmann 		return;
1322769be974SMarcel Holtmann 
1323769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1324769be974SMarcel Holtmann 
1325769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1326769be974SMarcel Holtmann 	if (conn) {
1327769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1328769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1329769be974SMarcel Holtmann 			hci_conn_put(conn);
1330769be974SMarcel Holtmann 		}
1331769be974SMarcel Holtmann 	}
1332769be974SMarcel Holtmann 
1333769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1334769be974SMarcel Holtmann }
1335769be974SMarcel Holtmann 
1336769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1337769be974SMarcel Holtmann {
1338769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1339769be974SMarcel Holtmann 	struct hci_conn *conn;
1340769be974SMarcel Holtmann 
1341769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1342769be974SMarcel Holtmann 
1343769be974SMarcel Holtmann 	if (!status)
1344769be974SMarcel Holtmann 		return;
1345769be974SMarcel Holtmann 
1346769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1347769be974SMarcel Holtmann 	if (!cp)
1348769be974SMarcel Holtmann 		return;
1349769be974SMarcel Holtmann 
1350769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1351769be974SMarcel Holtmann 
1352769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1353769be974SMarcel Holtmann 	if (conn) {
1354769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1355769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1356769be974SMarcel Holtmann 			hci_conn_put(conn);
1357769be974SMarcel Holtmann 		}
1358769be974SMarcel Holtmann 	}
1359769be974SMarcel Holtmann 
1360769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1361769be974SMarcel Holtmann }
1362769be974SMarcel Holtmann 
1363a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1364a9de9248SMarcel Holtmann {
1365b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1366b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1367b6a0dc82SMarcel Holtmann 	__u16 handle;
1368b6a0dc82SMarcel Holtmann 
1369a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1370b6a0dc82SMarcel Holtmann 
1371b6a0dc82SMarcel Holtmann 	if (!status)
1372b6a0dc82SMarcel Holtmann 		return;
1373b6a0dc82SMarcel Holtmann 
1374b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1375b6a0dc82SMarcel Holtmann 	if (!cp)
1376b6a0dc82SMarcel Holtmann 		return;
1377b6a0dc82SMarcel Holtmann 
1378b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1379b6a0dc82SMarcel Holtmann 
1380b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1381b6a0dc82SMarcel Holtmann 
1382b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1383b6a0dc82SMarcel Holtmann 
1384b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
13855a08ecceSAndrei Emeltchenko 	if (acl) {
13865a08ecceSAndrei Emeltchenko 		sco = acl->link;
13875a08ecceSAndrei Emeltchenko 		if (sco) {
1388b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1389b6a0dc82SMarcel Holtmann 
1390b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1391b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1392b6a0dc82SMarcel Holtmann 		}
13935a08ecceSAndrei Emeltchenko 	}
1394b6a0dc82SMarcel Holtmann 
1395b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1396a9de9248SMarcel Holtmann }
1397a9de9248SMarcel Holtmann 
1398a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1399a9de9248SMarcel Holtmann {
1400a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
140104837f64SMarcel Holtmann 	struct hci_conn *conn;
140204837f64SMarcel Holtmann 
1403a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1404a9de9248SMarcel Holtmann 
1405a9de9248SMarcel Holtmann 	if (!status)
1406a9de9248SMarcel Holtmann 		return;
1407a9de9248SMarcel Holtmann 
1408a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
140904837f64SMarcel Holtmann 	if (!cp)
1410a9de9248SMarcel Holtmann 		return;
141104837f64SMarcel Holtmann 
141204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
141304837f64SMarcel Holtmann 
141404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1415e73439d8SMarcel Holtmann 	if (conn) {
141604837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
141704837f64SMarcel Holtmann 
1418e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1419e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1420e73439d8SMarcel Holtmann 	}
1421e73439d8SMarcel Holtmann 
142204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
142304837f64SMarcel Holtmann }
142404837f64SMarcel Holtmann 
1425a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1426a9de9248SMarcel Holtmann {
1427a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
142804837f64SMarcel Holtmann 	struct hci_conn *conn;
142904837f64SMarcel Holtmann 
1430a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1431a9de9248SMarcel Holtmann 
1432a9de9248SMarcel Holtmann 	if (!status)
1433a9de9248SMarcel Holtmann 		return;
1434a9de9248SMarcel Holtmann 
1435a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
143604837f64SMarcel Holtmann 	if (!cp)
1437a9de9248SMarcel Holtmann 		return;
143804837f64SMarcel Holtmann 
143904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
144004837f64SMarcel Holtmann 
144104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1442e73439d8SMarcel Holtmann 	if (conn) {
144304837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
144404837f64SMarcel Holtmann 
1445e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1446e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1447e73439d8SMarcel Holtmann 	}
1448e73439d8SMarcel Holtmann 
144904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
145004837f64SMarcel Holtmann }
145104837f64SMarcel Holtmann 
1452fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1453fcd89c09SVille Tervo {
1454fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1455fcd89c09SVille Tervo 	struct hci_conn *conn;
1456fcd89c09SVille Tervo 
1457fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1458fcd89c09SVille Tervo 
1459fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1460fcd89c09SVille Tervo 	if (!cp)
1461fcd89c09SVille Tervo 		return;
1462fcd89c09SVille Tervo 
1463fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1464fcd89c09SVille Tervo 
1465fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1466fcd89c09SVille Tervo 
1467fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1468fcd89c09SVille Tervo 		conn);
1469fcd89c09SVille Tervo 
1470fcd89c09SVille Tervo 	if (status) {
1471fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1472fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1473fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1474fcd89c09SVille Tervo 			hci_conn_del(conn);
1475fcd89c09SVille Tervo 		}
1476fcd89c09SVille Tervo 	} else {
1477fcd89c09SVille Tervo 		if (!conn) {
1478fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
147929b7988aSAndre Guedes 			if (conn) {
148029b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1481fcd89c09SVille Tervo 				conn->out = 1;
148229b7988aSAndre Guedes 			} else {
1483fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1484fcd89c09SVille Tervo 			}
1485fcd89c09SVille Tervo 		}
148629b7988aSAndre Guedes 	}
1487fcd89c09SVille Tervo 
1488fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1489fcd89c09SVille Tervo }
1490fcd89c09SVille Tervo 
1491a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1492a7a595f6SVinicius Costa Gomes {
1493a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1494a7a595f6SVinicius Costa Gomes }
1495a7a595f6SVinicius Costa Gomes 
14961da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14971da177e4SLinus Torvalds {
14981da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
14991da177e4SLinus Torvalds 
15001da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
15011da177e4SLinus Torvalds 
150223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
15036bd57416SMarcel Holtmann 
1504a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
150589352e7dSAndre Guedes 
150689352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
150789352e7dSAndre Guedes 		return;
150889352e7dSAndre Guedes 
150956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1510744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 0);
151156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
15121da177e4SLinus Torvalds }
15131da177e4SLinus Torvalds 
15141da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
15151da177e4SLinus Torvalds {
151645bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1517a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
15181da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
15191da177e4SLinus Torvalds 
15201da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
15211da177e4SLinus Torvalds 
152245bb4bf0SMarcel Holtmann 	if (!num_rsp)
152345bb4bf0SMarcel Holtmann 		return;
152445bb4bf0SMarcel Holtmann 
15251da177e4SLinus Torvalds 	hci_dev_lock(hdev);
152645bb4bf0SMarcel Holtmann 
1527e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
15281da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
15291da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
15301da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
15311da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
15321da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
15331da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
15341da177e4SLinus Torvalds 		data.rssi		= 0x00;
153541a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
15361da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
153748264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
15384c659c39SJohan Hedberg 						info->dev_class, 0, NULL);
15391da177e4SLinus Torvalds 	}
154045bb4bf0SMarcel Holtmann 
15411da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15421da177e4SLinus Torvalds }
15431da177e4SLinus Torvalds 
1544a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15451da177e4SLinus Torvalds {
1546a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1547a9de9248SMarcel Holtmann 	struct hci_conn *conn;
15481da177e4SLinus Torvalds 
1549a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
155045bb4bf0SMarcel Holtmann 
15511da177e4SLinus Torvalds 	hci_dev_lock(hdev);
155245bb4bf0SMarcel Holtmann 
1553a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
15549499237aSMarcel Holtmann 	if (!conn) {
15559499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
15569499237aSMarcel Holtmann 			goto unlock;
15579499237aSMarcel Holtmann 
15589499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1559a9de9248SMarcel Holtmann 		if (!conn)
1560a9de9248SMarcel Holtmann 			goto unlock;
156145bb4bf0SMarcel Holtmann 
15629499237aSMarcel Holtmann 		conn->type = SCO_LINK;
15639499237aSMarcel Holtmann 	}
15649499237aSMarcel Holtmann 
1565a9de9248SMarcel Holtmann 	if (!ev->status) {
1566a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1567769be974SMarcel Holtmann 
1568769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1569769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1570769be974SMarcel Holtmann 			hci_conn_hold(conn);
1571052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
157248264f06SJohan Hedberg 			mgmt_connected(hdev, &ev->bdaddr, conn->type,
157348264f06SJohan Hedberg 							conn->dst_type);
1574769be974SMarcel Holtmann 		} else
1575a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1576a9de9248SMarcel Holtmann 
15779eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
15787d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
15797d0db0a3SMarcel Holtmann 
1580a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1581a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1582a9de9248SMarcel Holtmann 
1583a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1584a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1585a9de9248SMarcel Holtmann 
1586a9de9248SMarcel Holtmann 		/* Get remote features */
1587a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1588a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1589a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1590769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1591769be974SMarcel Holtmann 							sizeof(cp), &cp);
159245bb4bf0SMarcel Holtmann 		}
1593a9de9248SMarcel Holtmann 
1594a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1595d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1596a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1597a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1598a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1599a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1600a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1601a9de9248SMarcel Holtmann 		}
160217d5c04cSJohan Hedberg 	} else {
1603a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
160417d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1605744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
160648264f06SJohan Hedberg 						conn->dst_type, ev->status);
160717d5c04cSJohan Hedberg 	}
160845bb4bf0SMarcel Holtmann 
1609e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1610e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
161145bb4bf0SMarcel Holtmann 
1612769be974SMarcel Holtmann 	if (ev->status) {
1613a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1614a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1615c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1616c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1617a9de9248SMarcel Holtmann 
1618a9de9248SMarcel Holtmann unlock:
16191da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1620a9de9248SMarcel Holtmann 
1621a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
16221da177e4SLinus Torvalds }
16231da177e4SLinus Torvalds 
16241da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
16251da177e4SLinus Torvalds {
1626a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
16271da177e4SLinus Torvalds 	int mask = hdev->link_mode;
16281da177e4SLinus Torvalds 
1629a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
16301da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
16311da177e4SLinus Torvalds 
16321da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
16331da177e4SLinus Torvalds 
1634138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1635138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
16361da177e4SLinus Torvalds 		/* Connection accepted */
1637c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
16381da177e4SLinus Torvalds 		struct hci_conn *conn;
16391da177e4SLinus Torvalds 
16401da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1641b6a0dc82SMarcel Holtmann 
1642cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1643cc11b9c1SAndrei Emeltchenko 		if (ie)
1644c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1645c7bdd502SMarcel Holtmann 
16461da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16471da177e4SLinus Torvalds 		if (!conn) {
1648cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1649cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1650893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
16511da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
16521da177e4SLinus Torvalds 				return;
16531da177e4SLinus Torvalds 			}
16541da177e4SLinus Torvalds 		}
1655b6a0dc82SMarcel Holtmann 
16561da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
16571da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1658b6a0dc82SMarcel Holtmann 
16591da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
16601da177e4SLinus Torvalds 
1661b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1662b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1663b6a0dc82SMarcel Holtmann 
16641da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
16651da177e4SLinus Torvalds 
16661da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
16671da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
16681da177e4SLinus Torvalds 			else
16691da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
16701da177e4SLinus Torvalds 
1671b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1672b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1673b6a0dc82SMarcel Holtmann 		} else {
1674b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1675b6a0dc82SMarcel Holtmann 
1676b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1677a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1678b6a0dc82SMarcel Holtmann 
1679b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1680b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1681b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1682b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1683b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1684b6a0dc82SMarcel Holtmann 
1685b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1686b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1687b6a0dc82SMarcel Holtmann 		}
16881da177e4SLinus Torvalds 	} else {
16891da177e4SLinus Torvalds 		/* Connection rejected */
16901da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
16911da177e4SLinus Torvalds 
16921da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
16939f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1694a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
16951da177e4SLinus Torvalds 	}
16961da177e4SLinus Torvalds }
16971da177e4SLinus Torvalds 
16981da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16991da177e4SLinus Torvalds {
1700a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
170104837f64SMarcel Holtmann 	struct hci_conn *conn;
17021da177e4SLinus Torvalds 
17031da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
17041da177e4SLinus Torvalds 
17051da177e4SLinus Torvalds 	hci_dev_lock(hdev);
17061da177e4SLinus Torvalds 
170704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1708f7520543SJohan Hedberg 	if (!conn)
1709f7520543SJohan Hedberg 		goto unlock;
1710f7520543SJohan Hedberg 
171137d9ef76SJohan Hedberg 	if (ev->status == 0)
17121da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
17137d0db0a3SMarcel Holtmann 
171437d9ef76SJohan Hedberg 	if (conn->type == ACL_LINK || conn->type == LE_LINK) {
171537d9ef76SJohan Hedberg 		if (ev->status != 0)
171637d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
171737d9ef76SJohan Hedberg 		else
171848264f06SJohan Hedberg 			mgmt_disconnected(hdev, &conn->dst, conn->type,
171948264f06SJohan Hedberg 							conn->dst_type);
172037d9ef76SJohan Hedberg 	}
1721f7520543SJohan Hedberg 
172237d9ef76SJohan Hedberg 	if (ev->status == 0) {
17232950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
17241da177e4SLinus Torvalds 		hci_conn_del(conn);
172537d9ef76SJohan Hedberg 	}
17261da177e4SLinus Torvalds 
1727f7520543SJohan Hedberg unlock:
17281da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17291da177e4SLinus Torvalds }
17301da177e4SLinus Torvalds 
1731a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1732a9de9248SMarcel Holtmann {
1733a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1734a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1735a9de9248SMarcel Holtmann 
1736a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1737a9de9248SMarcel Holtmann 
1738a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1739a9de9248SMarcel Holtmann 
1740a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1741d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1742d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1743d7556e20SWaldemar Rymarkiewicz 
1744765c2a96SJohan Hedberg 	if (!ev->status) {
174519f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1746d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1747d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
174819f8def0SWaldemar Rymarkiewicz 		} else {
1749a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1750765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
175119f8def0SWaldemar Rymarkiewicz 		}
17522a611692SJohan Hedberg 	} else {
1753744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
17542a611692SJohan Hedberg 	}
1755a9de9248SMarcel Holtmann 
1756a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
175719f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1758a9de9248SMarcel Holtmann 
1759f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1760d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1761f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1762f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1763f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1764d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1765d7556e20SWaldemar Rymarkiewicz 									&cp);
1766f8558555SMarcel Holtmann 		} else {
1767f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1768f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1769f8558555SMarcel Holtmann 			hci_conn_put(conn);
1770f8558555SMarcel Holtmann 		}
1771052b30b0SMarcel Holtmann 	} else {
1772a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1773a9de9248SMarcel Holtmann 
1774052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1775052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1776052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1777052b30b0SMarcel Holtmann 	}
1778052b30b0SMarcel Holtmann 
1779a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1780a9de9248SMarcel Holtmann 		if (!ev->status) {
1781a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1782f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1783f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1784d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1785d7556e20SWaldemar Rymarkiewicz 									&cp);
1786a9de9248SMarcel Holtmann 		} else {
1787a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1788a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1789a9de9248SMarcel Holtmann 		}
1790a9de9248SMarcel Holtmann 	}
1791a9de9248SMarcel Holtmann 
1792d7556e20SWaldemar Rymarkiewicz unlock:
1793a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1794a9de9248SMarcel Holtmann }
1795a9de9248SMarcel Holtmann 
1796a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1797a9de9248SMarcel Holtmann {
1798127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1799127178d2SJohan Hedberg 	struct hci_conn *conn;
1800127178d2SJohan Hedberg 
1801a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1802a9de9248SMarcel Holtmann 
1803a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1804127178d2SJohan Hedberg 
1805127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1806127178d2SJohan Hedberg 
1807a88a9652SJohan Hedberg 	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
1808744cf19eSJohan Hedberg 		mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
1809a88a9652SJohan Hedberg 
1810127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
181179c6c70cSJohan Hedberg 	if (!conn)
181279c6c70cSJohan Hedberg 		goto unlock;
181379c6c70cSJohan Hedberg 
181479c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
181579c6c70cSJohan Hedberg 		goto unlock;
181679c6c70cSJohan Hedberg 
181779c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1818127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1819127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1820127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1821127178d2SJohan Hedberg 	}
1822127178d2SJohan Hedberg 
182379c6c70cSJohan Hedberg unlock:
1824127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1825a9de9248SMarcel Holtmann }
1826a9de9248SMarcel Holtmann 
1827a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1828a9de9248SMarcel Holtmann {
1829a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1830a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1831a9de9248SMarcel Holtmann 
1832a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1833a9de9248SMarcel Holtmann 
1834a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1835a9de9248SMarcel Holtmann 
1836a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1837a9de9248SMarcel Holtmann 	if (conn) {
1838a9de9248SMarcel Holtmann 		if (!ev->status) {
1839ae293196SMarcel Holtmann 			if (ev->encrypt) {
1840ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1841ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1842a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1843da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1844ae293196SMarcel Holtmann 			} else
1845a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1846a9de9248SMarcel Holtmann 		}
1847a9de9248SMarcel Holtmann 
1848a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1849a9de9248SMarcel Holtmann 
1850f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1851f8558555SMarcel Holtmann 			if (!ev->status)
1852f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1853f8558555SMarcel Holtmann 
1854f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1855f8558555SMarcel Holtmann 			hci_conn_put(conn);
1856f8558555SMarcel Holtmann 		} else
1857a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1858a9de9248SMarcel Holtmann 	}
1859a9de9248SMarcel Holtmann 
1860a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1861a9de9248SMarcel Holtmann }
1862a9de9248SMarcel Holtmann 
1863a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1864a9de9248SMarcel Holtmann {
1865a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1866a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1867a9de9248SMarcel Holtmann 
1868a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1869a9de9248SMarcel Holtmann 
1870a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1871a9de9248SMarcel Holtmann 
1872a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1873a9de9248SMarcel Holtmann 	if (conn) {
1874a9de9248SMarcel Holtmann 		if (!ev->status)
1875a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1876a9de9248SMarcel Holtmann 
1877a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1878a9de9248SMarcel Holtmann 
1879a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1880a9de9248SMarcel Holtmann 	}
1881a9de9248SMarcel Holtmann 
1882a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1883a9de9248SMarcel Holtmann }
1884a9de9248SMarcel Holtmann 
1885a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1886a9de9248SMarcel Holtmann {
1887a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1888a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1889a9de9248SMarcel Holtmann 
1890a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1891a9de9248SMarcel Holtmann 
1892a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1893a9de9248SMarcel Holtmann 
1894a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1895ccd556feSJohan Hedberg 	if (!conn)
1896ccd556feSJohan Hedberg 		goto unlock;
1897ccd556feSJohan Hedberg 
1898769be974SMarcel Holtmann 	if (!ev->status)
1899a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1900a9de9248SMarcel Holtmann 
1901ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1902ccd556feSJohan Hedberg 		goto unlock;
1903ccd556feSJohan Hedberg 
1904ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1905769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1906769be974SMarcel Holtmann 		cp.handle = ev->handle;
1907769be974SMarcel Holtmann 		cp.page = 0x01;
1908ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1909769be974SMarcel Holtmann 							sizeof(cp), &cp);
1910392599b9SJohan Hedberg 		goto unlock;
1911392599b9SJohan Hedberg 	}
1912392599b9SJohan Hedberg 
1913127178d2SJohan Hedberg 	if (!ev->status) {
1914127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1915127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1916127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1917127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1918127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1919127178d2SJohan Hedberg 	}
1920392599b9SJohan Hedberg 
1921127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1922769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1923769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1924769be974SMarcel Holtmann 		hci_conn_put(conn);
1925769be974SMarcel Holtmann 	}
1926769be974SMarcel Holtmann 
1927ccd556feSJohan Hedberg unlock:
1928a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1929a9de9248SMarcel Holtmann }
1930a9de9248SMarcel Holtmann 
1931a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1932a9de9248SMarcel Holtmann {
1933a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1934a9de9248SMarcel Holtmann }
1935a9de9248SMarcel Holtmann 
1936a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1937a9de9248SMarcel Holtmann {
1938a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1939a9de9248SMarcel Holtmann }
1940a9de9248SMarcel Holtmann 
1941a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1942a9de9248SMarcel Holtmann {
1943a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1944a9de9248SMarcel Holtmann 	__u16 opcode;
1945a9de9248SMarcel Holtmann 
1946a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1947a9de9248SMarcel Holtmann 
1948a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1949a9de9248SMarcel Holtmann 
1950a9de9248SMarcel Holtmann 	switch (opcode) {
1951a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1952a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1953a9de9248SMarcel Holtmann 		break;
1954a9de9248SMarcel Holtmann 
1955a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1956a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1957a9de9248SMarcel Holtmann 		break;
1958a9de9248SMarcel Holtmann 
1959a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1960a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1961a9de9248SMarcel Holtmann 		break;
1962a9de9248SMarcel Holtmann 
1963a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1964a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1965a9de9248SMarcel Holtmann 		break;
1966a9de9248SMarcel Holtmann 
1967e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1968e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1969e4e8e37cSMarcel Holtmann 		break;
1970e4e8e37cSMarcel Holtmann 
1971a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1972a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1973a9de9248SMarcel Holtmann 		break;
1974a9de9248SMarcel Holtmann 
1975e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1976e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1977e4e8e37cSMarcel Holtmann 		break;
1978e4e8e37cSMarcel Holtmann 
1979e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1980e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1981e4e8e37cSMarcel Holtmann 		break;
1982e4e8e37cSMarcel Holtmann 
1983a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1984a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1985a9de9248SMarcel Holtmann 		break;
1986a9de9248SMarcel Holtmann 
1987a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1988a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1989a9de9248SMarcel Holtmann 		break;
1990a9de9248SMarcel Holtmann 
1991a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1992a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1993a9de9248SMarcel Holtmann 		break;
1994a9de9248SMarcel Holtmann 
1995a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1996a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1997a9de9248SMarcel Holtmann 		break;
1998a9de9248SMarcel Holtmann 
1999a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2000a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2001a9de9248SMarcel Holtmann 		break;
2002a9de9248SMarcel Holtmann 
2003a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2004a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2005a9de9248SMarcel Holtmann 		break;
2006a9de9248SMarcel Holtmann 
2007a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2008a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2009a9de9248SMarcel Holtmann 		break;
2010a9de9248SMarcel Holtmann 
2011a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2012a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2013a9de9248SMarcel Holtmann 		break;
2014a9de9248SMarcel Holtmann 
2015a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2016a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2017a9de9248SMarcel Holtmann 		break;
2018a9de9248SMarcel Holtmann 
2019a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2020a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2021a9de9248SMarcel Holtmann 		break;
2022a9de9248SMarcel Holtmann 
2023a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2024a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2025a9de9248SMarcel Holtmann 		break;
2026a9de9248SMarcel Holtmann 
2027333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
2028333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
2029333140b5SMarcel Holtmann 		break;
2030333140b5SMarcel Holtmann 
2031333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2032333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2033333140b5SMarcel Holtmann 		break;
2034333140b5SMarcel Holtmann 
2035a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2036a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2037a9de9248SMarcel Holtmann 		break;
2038a9de9248SMarcel Holtmann 
2039a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2040a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2041a9de9248SMarcel Holtmann 		break;
2042a9de9248SMarcel Holtmann 
2043a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2044a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2045a9de9248SMarcel Holtmann 		break;
2046a9de9248SMarcel Holtmann 
2047971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2048971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2049971e3a4bSAndre Guedes 		break;
2050971e3a4bSAndre Guedes 
2051a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2052a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2053a9de9248SMarcel Holtmann 		break;
2054a9de9248SMarcel Holtmann 
2055a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2056a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2057a9de9248SMarcel Holtmann 		break;
2058a9de9248SMarcel Holtmann 
2059350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2060350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2061350ee4cfSAndrei Emeltchenko 		break;
2062350ee4cfSAndrei Emeltchenko 
206323bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
206423bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
206523bb5763SJohan Hedberg 		break;
206623bb5763SJohan Hedberg 
20671e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
20681e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
20691e89cffbSAndrei Emeltchenko 		break;
20701e89cffbSAndrei Emeltchenko 
2071928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2072928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2073928abaa7SAndrei Emeltchenko 		break;
2074928abaa7SAndrei Emeltchenko 
2075b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2076b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2077b0916ea0SJohan Hedberg 		break;
2078b0916ea0SJohan Hedberg 
2079d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2080d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2081d5859e22SJohan Hedberg 		break;
2082d5859e22SJohan Hedberg 
2083d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2084d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2085d5859e22SJohan Hedberg 		break;
2086d5859e22SJohan Hedberg 
2087d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2088d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2089d5859e22SJohan Hedberg 		break;
2090d5859e22SJohan Hedberg 
2091d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2092d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2093d5859e22SJohan Hedberg 		break;
2094d5859e22SJohan Hedberg 
2095980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2096980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2097980e1a53SJohan Hedberg 		break;
2098980e1a53SJohan Hedberg 
2099980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2100980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2101980e1a53SJohan Hedberg 		break;
2102980e1a53SJohan Hedberg 
2103c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2104c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2105c35938b2SSzymon Janc 		break;
2106c35938b2SSzymon Janc 
21076ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
21086ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
21096ed58ec5SVille Tervo 		break;
21106ed58ec5SVille Tervo 
2111a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2112a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2113a5c29683SJohan Hedberg 		break;
2114a5c29683SJohan Hedberg 
2115a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2116a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2117a5c29683SJohan Hedberg 		break;
2118a5c29683SJohan Hedberg 
21191143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
21201143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
21211143d458SBrian Gix 		break;
21221143d458SBrian Gix 
21231143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
21241143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
212507f7fa5dSAndre Guedes 
212607f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
212707f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
21281143d458SBrian Gix 		break;
21291143d458SBrian Gix 
2130eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2131eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2132eb9d91f5SAndre Guedes 		break;
2133eb9d91f5SAndre Guedes 
2134a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2135a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2136a7a595f6SVinicius Costa Gomes 		break;
2137a7a595f6SVinicius Costa Gomes 
2138a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2139a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2140a7a595f6SVinicius Costa Gomes 		break;
2141a7a595f6SVinicius Costa Gomes 
2142f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2143f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2144f9b49306SAndre Guedes 		break;
2145f9b49306SAndre Guedes 
2146a9de9248SMarcel Holtmann 	default:
2147a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2148a9de9248SMarcel Holtmann 		break;
2149a9de9248SMarcel Holtmann 	}
2150a9de9248SMarcel Holtmann 
21516bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
21526bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
21536bd32326SVille Tervo 
2154a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2155a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2156a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2157c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2158a9de9248SMarcel Holtmann 	}
2159a9de9248SMarcel Holtmann }
2160a9de9248SMarcel Holtmann 
2161a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2162a9de9248SMarcel Holtmann {
2163a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2164a9de9248SMarcel Holtmann 	__u16 opcode;
2165a9de9248SMarcel Holtmann 
2166a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2167a9de9248SMarcel Holtmann 
2168a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2169a9de9248SMarcel Holtmann 
2170a9de9248SMarcel Holtmann 	switch (opcode) {
2171a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2172a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2173a9de9248SMarcel Holtmann 		break;
2174a9de9248SMarcel Holtmann 
2175a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2176a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2177a9de9248SMarcel Holtmann 		break;
2178a9de9248SMarcel Holtmann 
2179a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2180a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2181a9de9248SMarcel Holtmann 		break;
2182a9de9248SMarcel Holtmann 
2183f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2184f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2185f8558555SMarcel Holtmann 		break;
2186f8558555SMarcel Holtmann 
2187f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2188f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2189f8558555SMarcel Holtmann 		break;
2190f8558555SMarcel Holtmann 
2191a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2192a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2193a9de9248SMarcel Holtmann 		break;
2194a9de9248SMarcel Holtmann 
2195769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2196769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2197769be974SMarcel Holtmann 		break;
2198769be974SMarcel Holtmann 
2199769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2200769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2201769be974SMarcel Holtmann 		break;
2202769be974SMarcel Holtmann 
2203a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2204a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2205a9de9248SMarcel Holtmann 		break;
2206a9de9248SMarcel Holtmann 
2207a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2208a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2209a9de9248SMarcel Holtmann 		break;
2210a9de9248SMarcel Holtmann 
2211a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2212a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2213a9de9248SMarcel Holtmann 		break;
2214a9de9248SMarcel Holtmann 
22158962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
22168962ee74SJohan Hedberg 		if (ev->status != 0)
221737d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
22188962ee74SJohan Hedberg 		break;
22198962ee74SJohan Hedberg 
2220fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2221fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2222fcd89c09SVille Tervo 		break;
2223fcd89c09SVille Tervo 
2224a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2225a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2226a7a595f6SVinicius Costa Gomes 		break;
2227a7a595f6SVinicius Costa Gomes 
2228a9de9248SMarcel Holtmann 	default:
2229a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2230a9de9248SMarcel Holtmann 		break;
2231a9de9248SMarcel Holtmann 	}
2232a9de9248SMarcel Holtmann 
22336bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
22346bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
22356bd32326SVille Tervo 
223610572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2237a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2238a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2239c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2240a9de9248SMarcel Holtmann 	}
2241a9de9248SMarcel Holtmann }
2242a9de9248SMarcel Holtmann 
2243a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2244a9de9248SMarcel Holtmann {
2245a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2246a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2247a9de9248SMarcel Holtmann 
2248a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2249a9de9248SMarcel Holtmann 
2250a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2251a9de9248SMarcel Holtmann 
2252a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2253a9de9248SMarcel Holtmann 	if (conn) {
2254a9de9248SMarcel Holtmann 		if (!ev->status) {
2255a9de9248SMarcel Holtmann 			if (ev->role)
2256a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2257a9de9248SMarcel Holtmann 			else
2258a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2259a9de9248SMarcel Holtmann 		}
2260a9de9248SMarcel Holtmann 
2261a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2262a9de9248SMarcel Holtmann 
2263a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2264a9de9248SMarcel Holtmann 	}
2265a9de9248SMarcel Holtmann 
2266a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2267a9de9248SMarcel Holtmann }
2268a9de9248SMarcel Holtmann 
22691da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
22701da177e4SLinus Torvalds {
2271a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
22721da177e4SLinus Torvalds 	int i;
22731da177e4SLinus Torvalds 
227432ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
227532ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
227632ac5b9bSAndrei Emeltchenko 		return;
227732ac5b9bSAndrei Emeltchenko 	}
227832ac5b9bSAndrei Emeltchenko 
2279c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2280c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
22811da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
22821da177e4SLinus Torvalds 		return;
22831da177e4SLinus Torvalds 	}
22841da177e4SLinus Torvalds 
2285c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2286c5993de8SAndrei Emeltchenko 
2287613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2288613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
22891da177e4SLinus Torvalds 		struct hci_conn *conn;
22901da177e4SLinus Torvalds 		__u16  handle, count;
22911da177e4SLinus Torvalds 
2292613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2293613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
22941da177e4SLinus Torvalds 
22951da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2296f4280918SAndrei Emeltchenko 		if (!conn)
2297f4280918SAndrei Emeltchenko 			continue;
2298f4280918SAndrei Emeltchenko 
22991da177e4SLinus Torvalds 		conn->sent -= count;
23001da177e4SLinus Torvalds 
2301f4280918SAndrei Emeltchenko 		switch (conn->type) {
2302f4280918SAndrei Emeltchenko 		case ACL_LINK:
230370f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
230470f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
23051da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2306f4280918SAndrei Emeltchenko 			break;
2307f4280918SAndrei Emeltchenko 
2308f4280918SAndrei Emeltchenko 		case LE_LINK:
23096ed58ec5SVille Tervo 			if (hdev->le_pkts) {
23106ed58ec5SVille Tervo 				hdev->le_cnt += count;
23116ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
23126ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
23136ed58ec5SVille Tervo 			} else {
23146ed58ec5SVille Tervo 				hdev->acl_cnt += count;
23156ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
23166ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
23176ed58ec5SVille Tervo 			}
2318f4280918SAndrei Emeltchenko 			break;
2319f4280918SAndrei Emeltchenko 
2320f4280918SAndrei Emeltchenko 		case SCO_LINK:
232170f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
232270f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
23235b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2324f4280918SAndrei Emeltchenko 			break;
2325f4280918SAndrei Emeltchenko 
2326f4280918SAndrei Emeltchenko 		default:
2327f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2328f4280918SAndrei Emeltchenko 			break;
23291da177e4SLinus Torvalds 		}
23301da177e4SLinus Torvalds 	}
2331a9de9248SMarcel Holtmann 
23323eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
23331da177e4SLinus Torvalds }
23341da177e4SLinus Torvalds 
233504837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
23361da177e4SLinus Torvalds {
2337a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
233804837f64SMarcel Holtmann 	struct hci_conn *conn;
23391da177e4SLinus Torvalds 
23401da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
23411da177e4SLinus Torvalds 
23421da177e4SLinus Torvalds 	hci_dev_lock(hdev);
23431da177e4SLinus Torvalds 
234404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
234504837f64SMarcel Holtmann 	if (conn) {
234604837f64SMarcel Holtmann 		conn->mode = ev->mode;
234704837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
234804837f64SMarcel Holtmann 
234904837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
235004837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
235104837f64SMarcel Holtmann 				conn->power_save = 1;
235204837f64SMarcel Holtmann 			else
235304837f64SMarcel Holtmann 				conn->power_save = 0;
235404837f64SMarcel Holtmann 		}
2355e73439d8SMarcel Holtmann 
2356e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2357e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
235804837f64SMarcel Holtmann 	}
235904837f64SMarcel Holtmann 
236004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
236104837f64SMarcel Holtmann }
236204837f64SMarcel Holtmann 
23631da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
23641da177e4SLinus Torvalds {
2365052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2366052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2367052b30b0SMarcel Holtmann 
2368a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2369052b30b0SMarcel Holtmann 
2370052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2371052b30b0SMarcel Holtmann 
2372052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2373b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2374b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2375b6f98044SWaldemar Rymarkiewicz 
2376b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2377052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2378052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2379052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2380052b30b0SMarcel Holtmann 	}
2381052b30b0SMarcel Holtmann 
238203b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
238303b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
238403b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2385582fbe9eSJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->flags)) {
2386a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2387a770bb5aSWaldemar Rymarkiewicz 
2388a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2389a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2390a770bb5aSWaldemar Rymarkiewicz 		else
2391a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2392a770bb5aSWaldemar Rymarkiewicz 
2393744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2394a770bb5aSWaldemar Rymarkiewicz 	}
2395980e1a53SJohan Hedberg 
2396b6f98044SWaldemar Rymarkiewicz unlock:
2397052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
23981da177e4SLinus Torvalds }
23991da177e4SLinus Torvalds 
24001da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
24011da177e4SLinus Torvalds {
240255ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
240355ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
240455ed8ca1SJohan Hedberg 	struct hci_conn *conn;
240555ed8ca1SJohan Hedberg 	struct link_key *key;
240655ed8ca1SJohan Hedberg 
2407a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
240855ed8ca1SJohan Hedberg 
240955ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
241055ed8ca1SJohan Hedberg 		return;
241155ed8ca1SJohan Hedberg 
241255ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
241355ed8ca1SJohan Hedberg 
241455ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
241555ed8ca1SJohan Hedberg 	if (!key) {
241655ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
241755ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
241855ed8ca1SJohan Hedberg 		goto not_found;
241955ed8ca1SJohan Hedberg 	}
242055ed8ca1SJohan Hedberg 
242155ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
242255ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
242355ed8ca1SJohan Hedberg 
2424b6020ba0SWaldemar Rymarkiewicz 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2425b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
242655ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
242755ed8ca1SJohan Hedberg 		goto not_found;
242855ed8ca1SJohan Hedberg 	}
242955ed8ca1SJohan Hedberg 
243055ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
243160b83f57SWaldemar Rymarkiewicz 	if (conn) {
243260b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
243360b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
243460b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
243555ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
243655ed8ca1SJohan Hedberg 			goto not_found;
243755ed8ca1SJohan Hedberg 		}
243855ed8ca1SJohan Hedberg 
243960b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
244060b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
244160b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
244260b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
244360b83f57SWaldemar Rymarkiewicz 			goto not_found;
244460b83f57SWaldemar Rymarkiewicz 		}
244560b83f57SWaldemar Rymarkiewicz 
244660b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
244760b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
244860b83f57SWaldemar Rymarkiewicz 	}
244960b83f57SWaldemar Rymarkiewicz 
245055ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
245155ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
245255ed8ca1SJohan Hedberg 
245355ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
245455ed8ca1SJohan Hedberg 
245555ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
245655ed8ca1SJohan Hedberg 
245755ed8ca1SJohan Hedberg 	return;
245855ed8ca1SJohan Hedberg 
245955ed8ca1SJohan Hedberg not_found:
246055ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
246155ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
24621da177e4SLinus Torvalds }
24631da177e4SLinus Torvalds 
24641da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
24651da177e4SLinus Torvalds {
2466052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2467052b30b0SMarcel Holtmann 	struct hci_conn *conn;
246855ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2469052b30b0SMarcel Holtmann 
2470a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2471052b30b0SMarcel Holtmann 
2472052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2473052b30b0SMarcel Holtmann 
2474052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2475052b30b0SMarcel Holtmann 	if (conn) {
2476052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2477052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2478980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
247913d39315SWaldemar Rymarkiewicz 
248013d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
248113d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
248213d39315SWaldemar Rymarkiewicz 
2483052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2484052b30b0SMarcel Holtmann 	}
2485052b30b0SMarcel Holtmann 
248655ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2487d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
248855ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
248955ed8ca1SJohan Hedberg 
2490052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
24911da177e4SLinus Torvalds }
24921da177e4SLinus Torvalds 
249304837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
249404837f64SMarcel Holtmann {
2495a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
249604837f64SMarcel Holtmann 	struct hci_conn *conn;
249704837f64SMarcel Holtmann 
249804837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
249904837f64SMarcel Holtmann 
250004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
250104837f64SMarcel Holtmann 
250204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
25031da177e4SLinus Torvalds 	if (conn && !ev->status) {
25041da177e4SLinus Torvalds 		struct inquiry_entry *ie;
25051da177e4SLinus Torvalds 
2506cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2507cc11b9c1SAndrei Emeltchenko 		if (ie) {
25081da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
25091da177e4SLinus Torvalds 			ie->timestamp = jiffies;
25101da177e4SLinus Torvalds 		}
25111da177e4SLinus Torvalds 	}
25121da177e4SLinus Torvalds 
25131da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
25141da177e4SLinus Torvalds }
25151da177e4SLinus Torvalds 
2516a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2517a8746417SMarcel Holtmann {
2518a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2519a8746417SMarcel Holtmann 	struct hci_conn *conn;
2520a8746417SMarcel Holtmann 
2521a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2522a8746417SMarcel Holtmann 
2523a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2524a8746417SMarcel Holtmann 
2525a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2526a8746417SMarcel Holtmann 	if (conn && !ev->status)
2527a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2528a8746417SMarcel Holtmann 
2529a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2530a8746417SMarcel Holtmann }
2531a8746417SMarcel Holtmann 
253285a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
253385a1e930SMarcel Holtmann {
2534a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
253585a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
253685a1e930SMarcel Holtmann 
253785a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
253885a1e930SMarcel Holtmann 
253985a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
254085a1e930SMarcel Holtmann 
2541cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2542cc11b9c1SAndrei Emeltchenko 	if (ie) {
254385a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
254485a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
254585a1e930SMarcel Holtmann 	}
254685a1e930SMarcel Holtmann 
254785a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
254885a1e930SMarcel Holtmann }
254985a1e930SMarcel Holtmann 
2550a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2551a9de9248SMarcel Holtmann {
2552a9de9248SMarcel Holtmann 	struct inquiry_data data;
2553a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2554a9de9248SMarcel Holtmann 
2555a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2556a9de9248SMarcel Holtmann 
2557a9de9248SMarcel Holtmann 	if (!num_rsp)
2558a9de9248SMarcel Holtmann 		return;
2559a9de9248SMarcel Holtmann 
2560a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2561a9de9248SMarcel Holtmann 
2562a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2563138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2564138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2565a9de9248SMarcel Holtmann 
2566e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2567a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2568a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2569a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2570a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2571a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2572a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2573a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
257441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2575a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
257648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2577e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2578e17acd40SJohan Hedberg 						NULL);
2579a9de9248SMarcel Holtmann 		}
2580a9de9248SMarcel Holtmann 	} else {
2581a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2582a9de9248SMarcel Holtmann 
2583e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2584a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2585a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2586a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2587a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2588a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2589a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2590a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
259141a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2592a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
259348264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2594e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2595e17acd40SJohan Hedberg 						NULL);
2596a9de9248SMarcel Holtmann 		}
2597a9de9248SMarcel Holtmann 	}
2598a9de9248SMarcel Holtmann 
2599a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2600a9de9248SMarcel Holtmann }
2601a9de9248SMarcel Holtmann 
2602a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2603a9de9248SMarcel Holtmann {
260441a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
260541a96212SMarcel Holtmann 	struct hci_conn *conn;
260641a96212SMarcel Holtmann 
2607a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
260841a96212SMarcel Holtmann 
260941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
261041a96212SMarcel Holtmann 
261141a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2612ccd556feSJohan Hedberg 	if (!conn)
2613ccd556feSJohan Hedberg 		goto unlock;
2614ccd556feSJohan Hedberg 
2615769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
261641a96212SMarcel Holtmann 		struct inquiry_entry *ie;
261741a96212SMarcel Holtmann 
2618cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2619cc11b9c1SAndrei Emeltchenko 		if (ie)
262041a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
262141a96212SMarcel Holtmann 
262241a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
262341a96212SMarcel Holtmann 	}
262441a96212SMarcel Holtmann 
2625ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2626ccd556feSJohan Hedberg 		goto unlock;
2627ccd556feSJohan Hedberg 
2628127178d2SJohan Hedberg 	if (!ev->status) {
2629127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2630127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2631127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2632127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2633127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2634127178d2SJohan Hedberg 	}
2635392599b9SJohan Hedberg 
2636127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2637769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2638769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2639769be974SMarcel Holtmann 		hci_conn_put(conn);
2640769be974SMarcel Holtmann 	}
2641769be974SMarcel Holtmann 
2642ccd556feSJohan Hedberg unlock:
264341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2644a9de9248SMarcel Holtmann }
2645a9de9248SMarcel Holtmann 
2646a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2647a9de9248SMarcel Holtmann {
2648b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2649b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2650b6a0dc82SMarcel Holtmann 
2651b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2652b6a0dc82SMarcel Holtmann 
2653b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2654b6a0dc82SMarcel Holtmann 
2655b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
26569dc0a3afSMarcel Holtmann 	if (!conn) {
26579dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
26589dc0a3afSMarcel Holtmann 			goto unlock;
26599dc0a3afSMarcel Holtmann 
26609dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2661b6a0dc82SMarcel Holtmann 		if (!conn)
2662b6a0dc82SMarcel Holtmann 			goto unlock;
2663b6a0dc82SMarcel Holtmann 
26649dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
26659dc0a3afSMarcel Holtmann 	}
26669dc0a3afSMarcel Holtmann 
2667732547f9SMarcel Holtmann 	switch (ev->status) {
2668732547f9SMarcel Holtmann 	case 0x00:
2669732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2670732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2671732547f9SMarcel Holtmann 
26729eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2673732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2674732547f9SMarcel Holtmann 		break;
2675732547f9SMarcel Holtmann 
2676705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2677732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
26781038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2679732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2680732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2681efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2682efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2683efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2684efc7688bSMarcel Holtmann 			goto unlock;
2685efc7688bSMarcel Holtmann 		}
2686732547f9SMarcel Holtmann 		/* fall through */
2687efc7688bSMarcel Holtmann 
2688732547f9SMarcel Holtmann 	default:
2689b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2690732547f9SMarcel Holtmann 		break;
2691732547f9SMarcel Holtmann 	}
2692b6a0dc82SMarcel Holtmann 
2693b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2694b6a0dc82SMarcel Holtmann 	if (ev->status)
2695b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2696b6a0dc82SMarcel Holtmann 
2697b6a0dc82SMarcel Holtmann unlock:
2698b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2699a9de9248SMarcel Holtmann }
2700a9de9248SMarcel Holtmann 
2701a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2702a9de9248SMarcel Holtmann {
2703a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2704a9de9248SMarcel Holtmann }
2705a9de9248SMarcel Holtmann 
270604837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
270704837f64SMarcel Holtmann {
2708a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
270904837f64SMarcel Holtmann 
271004837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
271104837f64SMarcel Holtmann }
271204837f64SMarcel Holtmann 
2713a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2714a9de9248SMarcel Holtmann {
2715a9de9248SMarcel Holtmann 	struct inquiry_data data;
2716a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2717a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2718a9de9248SMarcel Holtmann 
2719a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2720a9de9248SMarcel Holtmann 
2721a9de9248SMarcel Holtmann 	if (!num_rsp)
2722a9de9248SMarcel Holtmann 		return;
2723a9de9248SMarcel Holtmann 
2724a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2725a9de9248SMarcel Holtmann 
2726e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2727a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2728a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2729a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2730a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2731a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2732a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2733a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
273441a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2735a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
273648264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
27374c659c39SJohan Hedberg 				info->dev_class, info->rssi, info->data);
2738a9de9248SMarcel Holtmann 	}
2739a9de9248SMarcel Holtmann 
2740a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2741a9de9248SMarcel Holtmann }
2742a9de9248SMarcel Holtmann 
274317fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
274417fa4b9dSJohan Hedberg {
274517fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
274617fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
274717fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
274817fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
274917fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
275017fa4b9dSJohan Hedberg 			return 0x02;
275117fa4b9dSJohan Hedberg 		else
275217fa4b9dSJohan Hedberg 			return 0x03;
275317fa4b9dSJohan Hedberg 	}
275417fa4b9dSJohan Hedberg 
275517fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
275617fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
275758797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
275817fa4b9dSJohan Hedberg 
275917fa4b9dSJohan Hedberg 	return conn->auth_type;
276017fa4b9dSJohan Hedberg }
276117fa4b9dSJohan Hedberg 
27620493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
27630493684eSMarcel Holtmann {
27640493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
27650493684eSMarcel Holtmann 	struct hci_conn *conn;
27660493684eSMarcel Holtmann 
27670493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
27680493684eSMarcel Holtmann 
27690493684eSMarcel Holtmann 	hci_dev_lock(hdev);
27700493684eSMarcel Holtmann 
27710493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
277203b555e1SJohan Hedberg 	if (!conn)
277303b555e1SJohan Hedberg 		goto unlock;
277403b555e1SJohan Hedberg 
27750493684eSMarcel Holtmann 	hci_conn_hold(conn);
27760493684eSMarcel Holtmann 
277703b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
277803b555e1SJohan Hedberg 		goto unlock;
277903b555e1SJohan Hedberg 
278003b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
278103b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
278217fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
278317fa4b9dSJohan Hedberg 
278417fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
278517fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
27867cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
27877cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
278817fa4b9dSJohan Hedberg 
2789ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2790ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2791ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2792ce85ee13SSzymon Janc 		else
2793ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2794ce85ee13SSzymon Janc 
279517fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
279617fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
279703b555e1SJohan Hedberg 	} else {
279803b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
279903b555e1SJohan Hedberg 
280003b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
28019f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
280203b555e1SJohan Hedberg 
280303b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
280403b555e1SJohan Hedberg 							sizeof(cp), &cp);
280503b555e1SJohan Hedberg 	}
280603b555e1SJohan Hedberg 
280703b555e1SJohan Hedberg unlock:
280803b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
280903b555e1SJohan Hedberg }
281003b555e1SJohan Hedberg 
281103b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
281203b555e1SJohan Hedberg {
281303b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
281403b555e1SJohan Hedberg 	struct hci_conn *conn;
281503b555e1SJohan Hedberg 
281603b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
281703b555e1SJohan Hedberg 
281803b555e1SJohan Hedberg 	hci_dev_lock(hdev);
281903b555e1SJohan Hedberg 
282003b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
282103b555e1SJohan Hedberg 	if (!conn)
282203b555e1SJohan Hedberg 		goto unlock;
282303b555e1SJohan Hedberg 
282403b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
282503b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
282603b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
282703b555e1SJohan Hedberg 
282803b555e1SJohan Hedberg unlock:
28290493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
28300493684eSMarcel Holtmann }
28310493684eSMarcel Holtmann 
2832a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2833a5c29683SJohan Hedberg 							struct sk_buff *skb)
2834a5c29683SJohan Hedberg {
2835a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
283655bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
28377a828908SJohan Hedberg 	struct hci_conn *conn;
2838a5c29683SJohan Hedberg 
2839a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
2840a5c29683SJohan Hedberg 
2841a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
2842a5c29683SJohan Hedberg 
28437a828908SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
28447a828908SJohan Hedberg 		goto unlock;
28457a828908SJohan Hedberg 
28467a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
28477a828908SJohan Hedberg 	if (!conn)
28487a828908SJohan Hedberg 		goto unlock;
28497a828908SJohan Hedberg 
28507a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
28517a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
28527a828908SJohan Hedberg 
28537a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
28547a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
28557a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
28567a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
28577a828908SJohan Hedberg 	 * bit set. */
28587a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
28597a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
28607a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
28617a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
28627a828908SJohan Hedberg 		goto unlock;
28637a828908SJohan Hedberg 	}
28647a828908SJohan Hedberg 
28657a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
28667a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
28677a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
286855bc1a37SJohan Hedberg 
286955bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
287055bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
287155bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
287255bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
287355bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
287455bc1a37SJohan Hedberg 			confirm_hint = 1;
287555bc1a37SJohan Hedberg 			goto confirm;
287655bc1a37SJohan Hedberg 		}
287755bc1a37SJohan Hedberg 
28789f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
28799f61656aSJohan Hedberg 						hdev->auto_accept_delay);
28809f61656aSJohan Hedberg 
28819f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
28829f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
28839f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
28849f61656aSJohan Hedberg 			goto unlock;
28859f61656aSJohan Hedberg 		}
28869f61656aSJohan Hedberg 
28877a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
28887a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
28897a828908SJohan Hedberg 		goto unlock;
28907a828908SJohan Hedberg 	}
28917a828908SJohan Hedberg 
289255bc1a37SJohan Hedberg confirm:
2893744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
289455bc1a37SJohan Hedberg 								confirm_hint);
2895a5c29683SJohan Hedberg 
28967a828908SJohan Hedberg unlock:
2897a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
2898a5c29683SJohan Hedberg }
2899a5c29683SJohan Hedberg 
29001143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
29011143d458SBrian Gix 							struct sk_buff *skb)
29021143d458SBrian Gix {
29031143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
29041143d458SBrian Gix 
29051143d458SBrian Gix 	BT_DBG("%s", hdev->name);
29061143d458SBrian Gix 
29071143d458SBrian Gix 	hci_dev_lock(hdev);
29081143d458SBrian Gix 
29091143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
29101143d458SBrian Gix 		mgmt_user_passkey_request(hdev, &ev->bdaddr);
29111143d458SBrian Gix 
29121143d458SBrian Gix 	hci_dev_unlock(hdev);
29131143d458SBrian Gix }
29141143d458SBrian Gix 
29150493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
29160493684eSMarcel Holtmann {
29170493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
29180493684eSMarcel Holtmann 	struct hci_conn *conn;
29190493684eSMarcel Holtmann 
29200493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
29210493684eSMarcel Holtmann 
29220493684eSMarcel Holtmann 	hci_dev_lock(hdev);
29230493684eSMarcel Holtmann 
29240493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
29252a611692SJohan Hedberg 	if (!conn)
29262a611692SJohan Hedberg 		goto unlock;
29272a611692SJohan Hedberg 
29282a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
29292a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
29302a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
29312a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
29322a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
29332a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
2934744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
29352a611692SJohan Hedberg 
29360493684eSMarcel Holtmann 	hci_conn_put(conn);
29370493684eSMarcel Holtmann 
29382a611692SJohan Hedberg unlock:
29390493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
29400493684eSMarcel Holtmann }
29410493684eSMarcel Holtmann 
294241a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
294341a96212SMarcel Holtmann {
294441a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
294541a96212SMarcel Holtmann 	struct inquiry_entry *ie;
294641a96212SMarcel Holtmann 
294741a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
294841a96212SMarcel Holtmann 
294941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
295041a96212SMarcel Holtmann 
2951cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2952cc11b9c1SAndrei Emeltchenko 	if (ie)
295341a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
295441a96212SMarcel Holtmann 
295541a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
295641a96212SMarcel Holtmann }
295741a96212SMarcel Holtmann 
29582763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
29592763eda6SSzymon Janc 							struct sk_buff *skb)
29602763eda6SSzymon Janc {
29612763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
29622763eda6SSzymon Janc 	struct oob_data *data;
29632763eda6SSzymon Janc 
29642763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
29652763eda6SSzymon Janc 
29662763eda6SSzymon Janc 	hci_dev_lock(hdev);
29672763eda6SSzymon Janc 
2968e1ba1f15SSzymon Janc 	if (!test_bit(HCI_MGMT, &hdev->flags))
2969e1ba1f15SSzymon Janc 		goto unlock;
2970e1ba1f15SSzymon Janc 
29712763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
29722763eda6SSzymon Janc 	if (data) {
29732763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
29742763eda6SSzymon Janc 
29752763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
29762763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
29772763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
29782763eda6SSzymon Janc 
29792763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
29802763eda6SSzymon Janc 									&cp);
29812763eda6SSzymon Janc 	} else {
29822763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
29832763eda6SSzymon Janc 
29842763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
29852763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
29862763eda6SSzymon Janc 									&cp);
29872763eda6SSzymon Janc 	}
29882763eda6SSzymon Janc 
2989e1ba1f15SSzymon Janc unlock:
29902763eda6SSzymon Janc 	hci_dev_unlock(hdev);
29912763eda6SSzymon Janc }
29922763eda6SSzymon Janc 
2993fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2994fcd89c09SVille Tervo {
2995fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2996fcd89c09SVille Tervo 	struct hci_conn *conn;
2997fcd89c09SVille Tervo 
2998fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
2999fcd89c09SVille Tervo 
3000fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3001fcd89c09SVille Tervo 
3002fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3003b62f328bSVille Tervo 	if (!conn) {
3004b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3005b62f328bSVille Tervo 		if (!conn) {
3006b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3007b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3008b62f328bSVille Tervo 			return;
3009b62f328bSVille Tervo 		}
301029b7988aSAndre Guedes 
301129b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3012b62f328bSVille Tervo 	}
3013fcd89c09SVille Tervo 
3014fcd89c09SVille Tervo 	if (ev->status) {
301548264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
301648264f06SJohan Hedberg 						conn->dst_type, ev->status);
3017fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3018fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3019fcd89c09SVille Tervo 		hci_conn_del(conn);
3020fcd89c09SVille Tervo 		goto unlock;
3021fcd89c09SVille Tervo 	}
3022fcd89c09SVille Tervo 
302348264f06SJohan Hedberg 	mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
302483bc71b4SVinicius Costa Gomes 
30257b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3026fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3027fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3028fcd89c09SVille Tervo 
3029fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3030fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3031fcd89c09SVille Tervo 
3032fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3033fcd89c09SVille Tervo 
3034fcd89c09SVille Tervo unlock:
3035fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3036fcd89c09SVille Tervo }
3037fcd89c09SVille Tervo 
30389aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
30399aa04c91SAndre Guedes 						struct sk_buff *skb)
30409aa04c91SAndre Guedes {
3041e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3042e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
30439aa04c91SAndre Guedes 
30449aa04c91SAndre Guedes 	hci_dev_lock(hdev);
30459aa04c91SAndre Guedes 
3046e95beb41SAndre Guedes 	while (num_reports--) {
3047e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3048e95beb41SAndre Guedes 
30499aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
30509aa04c91SAndre Guedes 
3051e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
30529aa04c91SAndre Guedes 	}
30539aa04c91SAndre Guedes 
30549aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
30559aa04c91SAndre Guedes }
30569aa04c91SAndre Guedes 
3057a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3058a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3059a7a595f6SVinicius Costa Gomes {
3060a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3061a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3062bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3063a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3064bea710feSVinicius Costa Gomes 	struct link_key *ltk;
3065a7a595f6SVinicius Costa Gomes 
3066a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3067a7a595f6SVinicius Costa Gomes 
3068a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3069a7a595f6SVinicius Costa Gomes 
3070a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3071bea710feSVinicius Costa Gomes 	if (conn == NULL)
3072bea710feSVinicius Costa Gomes 		goto not_found;
3073a7a595f6SVinicius Costa Gomes 
3074bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3075bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3076bea710feSVinicius Costa Gomes 		goto not_found;
3077bea710feSVinicius Costa Gomes 
3078bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3079a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3080726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
3081a7a595f6SVinicius Costa Gomes 
3082a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3083a7a595f6SVinicius Costa Gomes 
3084a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3085bea710feSVinicius Costa Gomes 
3086bea710feSVinicius Costa Gomes 	return;
3087bea710feSVinicius Costa Gomes 
3088bea710feSVinicius Costa Gomes not_found:
3089bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3090bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3091bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3092a7a595f6SVinicius Costa Gomes }
3093a7a595f6SVinicius Costa Gomes 
3094fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3095fcd89c09SVille Tervo {
3096fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3097fcd89c09SVille Tervo 
3098fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3099fcd89c09SVille Tervo 
3100fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3101fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3102fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3103fcd89c09SVille Tervo 		break;
3104fcd89c09SVille Tervo 
31059aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
31069aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
31079aa04c91SAndre Guedes 		break;
31089aa04c91SAndre Guedes 
3109a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3110a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3111a7a595f6SVinicius Costa Gomes 		break;
3112a7a595f6SVinicius Costa Gomes 
3113fcd89c09SVille Tervo 	default:
3114fcd89c09SVille Tervo 		break;
3115fcd89c09SVille Tervo 	}
3116fcd89c09SVille Tervo }
3117fcd89c09SVille Tervo 
31181da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
31191da177e4SLinus Torvalds {
3120a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3121a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
31221da177e4SLinus Torvalds 
31231da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
31241da177e4SLinus Torvalds 
3125a9de9248SMarcel Holtmann 	switch (event) {
31261da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
31271da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
31281da177e4SLinus Torvalds 		break;
31291da177e4SLinus Torvalds 
31301da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
31311da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
31321da177e4SLinus Torvalds 		break;
31331da177e4SLinus Torvalds 
3134a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3135a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
313621d9e30eSMarcel Holtmann 		break;
313721d9e30eSMarcel Holtmann 
31381da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
31391da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
31401da177e4SLinus Torvalds 		break;
31411da177e4SLinus Torvalds 
31421da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
31431da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
31441da177e4SLinus Torvalds 		break;
31451da177e4SLinus Torvalds 
31461da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
31471da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
31481da177e4SLinus Torvalds 		break;
31491da177e4SLinus Torvalds 
3150a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3151a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3152a9de9248SMarcel Holtmann 		break;
3153a9de9248SMarcel Holtmann 
31541da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
31551da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
31561da177e4SLinus Torvalds 		break;
31571da177e4SLinus Torvalds 
3158a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3159a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3160a9de9248SMarcel Holtmann 		break;
3161a9de9248SMarcel Holtmann 
3162a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3163a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3164a9de9248SMarcel Holtmann 		break;
3165a9de9248SMarcel Holtmann 
3166a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3167a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3168a9de9248SMarcel Holtmann 		break;
3169a9de9248SMarcel Holtmann 
3170a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3171a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3172a9de9248SMarcel Holtmann 		break;
3173a9de9248SMarcel Holtmann 
3174a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3175a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3176a9de9248SMarcel Holtmann 		break;
3177a9de9248SMarcel Holtmann 
3178a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3179a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3180a9de9248SMarcel Holtmann 		break;
3181a9de9248SMarcel Holtmann 
3182a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3183a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3184a9de9248SMarcel Holtmann 		break;
3185a9de9248SMarcel Holtmann 
3186a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3187a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3188a9de9248SMarcel Holtmann 		break;
3189a9de9248SMarcel Holtmann 
3190a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3191a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
31921da177e4SLinus Torvalds 		break;
31931da177e4SLinus Torvalds 
31941da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
31951da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
31961da177e4SLinus Torvalds 		break;
31971da177e4SLinus Torvalds 
31981da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
31991da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
32001da177e4SLinus Torvalds 		break;
32011da177e4SLinus Torvalds 
32021da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
32031da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
32041da177e4SLinus Torvalds 		break;
32051da177e4SLinus Torvalds 
32061da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
32071da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
32081da177e4SLinus Torvalds 		break;
32091da177e4SLinus Torvalds 
3210a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3211a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3212a8746417SMarcel Holtmann 		break;
3213a8746417SMarcel Holtmann 
321485a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
321585a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
321685a1e930SMarcel Holtmann 		break;
321785a1e930SMarcel Holtmann 
3218a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3219a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3220a9de9248SMarcel Holtmann 		break;
3221a9de9248SMarcel Holtmann 
3222a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3223a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3224a9de9248SMarcel Holtmann 		break;
3225a9de9248SMarcel Holtmann 
3226a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3227a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3228a9de9248SMarcel Holtmann 		break;
3229a9de9248SMarcel Holtmann 
3230a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3231a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3232a9de9248SMarcel Holtmann 		break;
3233a9de9248SMarcel Holtmann 
323404837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
323504837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
323604837f64SMarcel Holtmann 		break;
323704837f64SMarcel Holtmann 
3238a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3239a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
32401da177e4SLinus Torvalds 		break;
32411da177e4SLinus Torvalds 
32420493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
32430493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
32440493684eSMarcel Holtmann 		break;
32450493684eSMarcel Holtmann 
324603b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
324703b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
324803b555e1SJohan Hedberg 		break;
324903b555e1SJohan Hedberg 
3250a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3251a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3252a5c29683SJohan Hedberg 		break;
3253a5c29683SJohan Hedberg 
32541143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
32551143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
32561143d458SBrian Gix 		break;
32571143d458SBrian Gix 
32580493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
32590493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
32600493684eSMarcel Holtmann 		break;
32610493684eSMarcel Holtmann 
326241a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
326341a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
326441a96212SMarcel Holtmann 		break;
326541a96212SMarcel Holtmann 
3266fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3267fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3268fcd89c09SVille Tervo 		break;
3269fcd89c09SVille Tervo 
32702763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
32712763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
32722763eda6SSzymon Janc 		break;
32732763eda6SSzymon Janc 
32741da177e4SLinus Torvalds 	default:
3275a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
32761da177e4SLinus Torvalds 		break;
32771da177e4SLinus Torvalds 	}
32781da177e4SLinus Torvalds 
32791da177e4SLinus Torvalds 	kfree_skb(skb);
32801da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
32811da177e4SLinus Torvalds }
32821da177e4SLinus Torvalds 
32831da177e4SLinus Torvalds /* Generate internal stack event */
32841da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
32851da177e4SLinus Torvalds {
32861da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
32871da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
32881da177e4SLinus Torvalds 	struct sk_buff *skb;
32891da177e4SLinus Torvalds 
32901da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
32911da177e4SLinus Torvalds 	if (!skb)
32921da177e4SLinus Torvalds 		return;
32931da177e4SLinus Torvalds 
32941da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
32951da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
32961da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
32971da177e4SLinus Torvalds 
32981da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
32991da177e4SLinus Torvalds 	ev->type = type;
33001da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
33011da177e4SLinus Torvalds 
3302576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3303a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3304576c7d85SMarcel Holtmann 
33050d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
33061da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3307eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
33081da177e4SLinus Torvalds 	kfree_skb(skb);
33091da177e4SLinus Torvalds }
3310e6100a25SAndre Guedes 
3311669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3312e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3313