xref: /openbmc/linux/net/bluetooth/hci_event.c (revision e61ef499)
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 
714971e3a4bSAndre Guedes 	memcpy(hdev->extfeatures, rp->features, 8);
715971e3a4bSAndre Guedes 
716971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
717971e3a4bSAndre Guedes }
718971e3a4bSAndre Guedes 
7191e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7201e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7211e89cffbSAndrei Emeltchenko {
7221e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7231e89cffbSAndrei Emeltchenko 
7241e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7251e89cffbSAndrei Emeltchenko 
7261e89cffbSAndrei Emeltchenko 	if (rp->status)
7271e89cffbSAndrei Emeltchenko 		return;
7281e89cffbSAndrei Emeltchenko 
7291e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7301e89cffbSAndrei Emeltchenko 
7311e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7321e89cffbSAndrei Emeltchenko }
7331e89cffbSAndrei Emeltchenko 
734a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
735a9de9248SMarcel Holtmann {
736a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
737a9de9248SMarcel Holtmann 
738a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
739a9de9248SMarcel Holtmann 
740a9de9248SMarcel Holtmann 	if (rp->status)
741a9de9248SMarcel Holtmann 		return;
742a9de9248SMarcel Holtmann 
743a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
744a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
745a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
746a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
747da1f5198SMarcel Holtmann 
748da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
749da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
750da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
751da1f5198SMarcel Holtmann 	}
752da1f5198SMarcel Holtmann 
753da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
754da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7551da177e4SLinus Torvalds 
756a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
757a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
758a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7591da177e4SLinus Torvalds }
7601da177e4SLinus Torvalds 
761a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
762a9de9248SMarcel Holtmann {
763a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7641da177e4SLinus Torvalds 
765a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
766a9de9248SMarcel Holtmann 
767a9de9248SMarcel Holtmann 	if (!rp->status)
768a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
769a9de9248SMarcel Holtmann 
77023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
77123bb5763SJohan Hedberg }
77223bb5763SJohan Hedberg 
773350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
774350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
775350ee4cfSAndrei Emeltchenko {
776350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
777350ee4cfSAndrei Emeltchenko 
778350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
779350ee4cfSAndrei Emeltchenko 
780350ee4cfSAndrei Emeltchenko 	if (rp->status)
781350ee4cfSAndrei Emeltchenko 		return;
782350ee4cfSAndrei Emeltchenko 
783350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
784350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
785350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
786350ee4cfSAndrei Emeltchenko 
787350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
788350ee4cfSAndrei Emeltchenko 
789350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
790350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
791350ee4cfSAndrei Emeltchenko 
792350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
793350ee4cfSAndrei Emeltchenko }
794350ee4cfSAndrei Emeltchenko 
79523bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
79623bb5763SJohan Hedberg {
79723bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
79823bb5763SJohan Hedberg 
79923bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
80023bb5763SJohan Hedberg 
80123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8021da177e4SLinus Torvalds }
8031da177e4SLinus Torvalds 
804928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
805928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
806928abaa7SAndrei Emeltchenko {
807928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
808928abaa7SAndrei Emeltchenko 
809928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
810928abaa7SAndrei Emeltchenko 
811928abaa7SAndrei Emeltchenko 	if (rp->status)
812928abaa7SAndrei Emeltchenko 		return;
813928abaa7SAndrei Emeltchenko 
814928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
815928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
816928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
817928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
818928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
819928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
820928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
821928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
822928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
823928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
824928abaa7SAndrei Emeltchenko 
825928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
826928abaa7SAndrei Emeltchenko }
827928abaa7SAndrei Emeltchenko 
828b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
829b0916ea0SJohan Hedberg 							struct sk_buff *skb)
830b0916ea0SJohan Hedberg {
831b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
832b0916ea0SJohan Hedberg 
833b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
834b0916ea0SJohan Hedberg 
835b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
836b0916ea0SJohan Hedberg }
837b0916ea0SJohan Hedberg 
838d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
839d5859e22SJohan Hedberg {
840d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
841d5859e22SJohan Hedberg 
842d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
843d5859e22SJohan Hedberg 
844d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
845d5859e22SJohan Hedberg }
846d5859e22SJohan Hedberg 
847d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
848d5859e22SJohan Hedberg 							struct sk_buff *skb)
849d5859e22SJohan Hedberg {
850d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
851d5859e22SJohan Hedberg 
852d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
853d5859e22SJohan Hedberg 
854d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
855d5859e22SJohan Hedberg }
856d5859e22SJohan Hedberg 
857d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
858d5859e22SJohan Hedberg 							struct sk_buff *skb)
859d5859e22SJohan Hedberg {
860d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
861d5859e22SJohan Hedberg 
862d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
863d5859e22SJohan Hedberg 
864d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
865d5859e22SJohan Hedberg }
866d5859e22SJohan Hedberg 
867d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
868d5859e22SJohan Hedberg {
869d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
870d5859e22SJohan Hedberg 
871d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
872d5859e22SJohan Hedberg 
873d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
874d5859e22SJohan Hedberg }
875d5859e22SJohan Hedberg 
876980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
877980e1a53SJohan Hedberg {
878980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
879980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
880980e1a53SJohan Hedberg 	struct hci_conn *conn;
881980e1a53SJohan Hedberg 
882980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
883980e1a53SJohan Hedberg 
88456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
88556e5cb86SJohan Hedberg 
886980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
887744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
888980e1a53SJohan Hedberg 
889980e1a53SJohan Hedberg 	if (rp->status != 0)
89056e5cb86SJohan Hedberg 		goto unlock;
891980e1a53SJohan Hedberg 
892980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
893980e1a53SJohan Hedberg 	if (!cp)
89456e5cb86SJohan Hedberg 		goto unlock;
895980e1a53SJohan Hedberg 
896980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
897980e1a53SJohan Hedberg 	if (conn)
898980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
89956e5cb86SJohan Hedberg 
90056e5cb86SJohan Hedberg unlock:
90156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
902980e1a53SJohan Hedberg }
903980e1a53SJohan Hedberg 
904980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
905980e1a53SJohan Hedberg {
906980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
907980e1a53SJohan Hedberg 
908980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
909980e1a53SJohan Hedberg 
91056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
91156e5cb86SJohan Hedberg 
912980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
913744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
914980e1a53SJohan Hedberg 								rp->status);
91556e5cb86SJohan Hedberg 
91656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
917980e1a53SJohan Hedberg }
91856e5cb86SJohan Hedberg 
9196ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9206ed58ec5SVille Tervo 				       struct sk_buff *skb)
9216ed58ec5SVille Tervo {
9226ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9236ed58ec5SVille Tervo 
9246ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9256ed58ec5SVille Tervo 
9266ed58ec5SVille Tervo 	if (rp->status)
9276ed58ec5SVille Tervo 		return;
9286ed58ec5SVille Tervo 
9296ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9306ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9316ed58ec5SVille Tervo 
9326ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9336ed58ec5SVille Tervo 
9346ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9356ed58ec5SVille Tervo 
9366ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9376ed58ec5SVille Tervo }
938980e1a53SJohan Hedberg 
939a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
940a5c29683SJohan Hedberg {
941a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
942a5c29683SJohan Hedberg 
943a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
944a5c29683SJohan Hedberg 
94556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
94656e5cb86SJohan Hedberg 
947a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
948744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
949a5c29683SJohan Hedberg 								rp->status);
95056e5cb86SJohan Hedberg 
95156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
952a5c29683SJohan Hedberg }
953a5c29683SJohan Hedberg 
954a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
955a5c29683SJohan Hedberg 							struct sk_buff *skb)
956a5c29683SJohan Hedberg {
957a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
958a5c29683SJohan Hedberg 
959a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
960a5c29683SJohan Hedberg 
96156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96256e5cb86SJohan Hedberg 
963a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
964744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
965a5c29683SJohan Hedberg 								rp->status);
96656e5cb86SJohan Hedberg 
96756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
968a5c29683SJohan Hedberg }
969a5c29683SJohan Hedberg 
9701143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9711143d458SBrian Gix {
9721143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9731143d458SBrian Gix 
9741143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9751143d458SBrian Gix 
9761143d458SBrian Gix 	hci_dev_lock(hdev);
9771143d458SBrian Gix 
9781143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
9791143d458SBrian Gix 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
9801143d458SBrian Gix 								rp->status);
9811143d458SBrian Gix 
9821143d458SBrian Gix 	hci_dev_unlock(hdev);
9831143d458SBrian Gix }
9841143d458SBrian Gix 
9851143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9861143d458SBrian Gix 							struct sk_buff *skb)
9871143d458SBrian Gix {
9881143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9891143d458SBrian Gix 
9901143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9911143d458SBrian Gix 
9921143d458SBrian Gix 	hci_dev_lock(hdev);
9931143d458SBrian Gix 
9941143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
9951143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
9961143d458SBrian Gix 								rp->status);
9971143d458SBrian Gix 
9981143d458SBrian Gix 	hci_dev_unlock(hdev);
9991143d458SBrian Gix }
10001143d458SBrian Gix 
1001c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1002c35938b2SSzymon Janc 							struct sk_buff *skb)
1003c35938b2SSzymon Janc {
1004c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1005c35938b2SSzymon Janc 
1006c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1007c35938b2SSzymon Janc 
100856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1009744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1010c35938b2SSzymon Janc 						rp->randomizer, rp->status);
101156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1012c35938b2SSzymon Janc }
1013c35938b2SSzymon Janc 
101407f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
101507f7fa5dSAndre Guedes {
101607f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
101707f7fa5dSAndre Guedes 
101807f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
101907f7fa5dSAndre Guedes }
102007f7fa5dSAndre Guedes 
1021eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1022eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1023eb9d91f5SAndre Guedes {
1024eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1025eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1026eb9d91f5SAndre Guedes 
1027eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1028eb9d91f5SAndre Guedes 
1029eb9d91f5SAndre Guedes 	if (status)
1030eb9d91f5SAndre Guedes 		return;
1031eb9d91f5SAndre Guedes 
1032eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1033eb9d91f5SAndre Guedes 	if (!cp)
1034eb9d91f5SAndre Guedes 		return;
1035eb9d91f5SAndre Guedes 
103635815085SAndre Guedes 	if (cp->enable == 0x01) {
1037d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1038d23264a8SAndre Guedes 
1039db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1040a8f13c8cSAndre Guedes 
1041a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1042eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1043a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
104435815085SAndre Guedes 	} else if (cp->enable == 0x00) {
1045d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1046d23264a8SAndre Guedes 
1047db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1048db323f2fSGustavo F. Padovan 		queue_delayed_work(hdev->workqueue, &hdev->adv_work,
1049db323f2fSGustavo F. Padovan 						 jiffies + ADV_CLEAR_TIMEOUT);
105035815085SAndre Guedes 	}
1051eb9d91f5SAndre Guedes }
1052eb9d91f5SAndre Guedes 
1053a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1054a7a595f6SVinicius Costa Gomes {
1055a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1056a7a595f6SVinicius Costa Gomes 
1057a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1058a7a595f6SVinicius Costa Gomes 
1059a7a595f6SVinicius Costa Gomes 	if (rp->status)
1060a7a595f6SVinicius Costa Gomes 		return;
1061a7a595f6SVinicius Costa Gomes 
1062a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1063a7a595f6SVinicius Costa Gomes }
1064a7a595f6SVinicius Costa Gomes 
1065a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1066a7a595f6SVinicius Costa Gomes {
1067a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1068a7a595f6SVinicius Costa Gomes 
1069a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1070a7a595f6SVinicius Costa Gomes 
1071a7a595f6SVinicius Costa Gomes 	if (rp->status)
1072a7a595f6SVinicius Costa Gomes 		return;
1073a7a595f6SVinicius Costa Gomes 
1074a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1075a7a595f6SVinicius Costa Gomes }
1076a7a595f6SVinicius Costa Gomes 
1077f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1078f9b49306SAndre Guedes 							struct sk_buff *skb)
1079f9b49306SAndre Guedes {
1080f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1081f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1082f9b49306SAndre Guedes 
1083f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1084f9b49306SAndre Guedes 
1085f9b49306SAndre Guedes 	if (status)
1086f9b49306SAndre Guedes 		return;
1087f9b49306SAndre Guedes 
1088f9b49306SAndre Guedes 	cp.page = 0x01;
1089f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1090f9b49306SAndre Guedes }
1091f9b49306SAndre Guedes 
1092a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1093a9de9248SMarcel Holtmann {
1094a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1095a9de9248SMarcel Holtmann 
1096a9de9248SMarcel Holtmann 	if (status) {
109723bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1098a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
109956e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1100164a6e78SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
11017a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
110256e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1103314b2381SJohan Hedberg 		return;
1104314b2381SJohan Hedberg 	}
1105314b2381SJohan Hedberg 
110689352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
110789352e7dSAndre Guedes 
110856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1109744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 1);
111056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1111a9de9248SMarcel Holtmann }
1112a9de9248SMarcel Holtmann 
11131da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11141da177e4SLinus Torvalds {
1115a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11161da177e4SLinus Torvalds 	struct hci_conn *conn;
11171da177e4SLinus Torvalds 
1118a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1119a9de9248SMarcel Holtmann 
1120a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11211da177e4SLinus Torvalds 	if (!cp)
11221da177e4SLinus Torvalds 		return;
11231da177e4SLinus Torvalds 
11241da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11251da177e4SLinus Torvalds 
11261da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11271da177e4SLinus Torvalds 
1128a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11291da177e4SLinus Torvalds 
11301da177e4SLinus Torvalds 	if (status) {
11311da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11324c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11331da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11341da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11351da177e4SLinus Torvalds 				hci_conn_del(conn);
11364c67bc74SMarcel Holtmann 			} else
11374c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11381da177e4SLinus Torvalds 		}
11391da177e4SLinus Torvalds 	} else {
11401da177e4SLinus Torvalds 		if (!conn) {
11411da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11421da177e4SLinus Torvalds 			if (conn) {
11431da177e4SLinus Torvalds 				conn->out = 1;
11441da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11451da177e4SLinus Torvalds 			} else
1146893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11471da177e4SLinus Torvalds 		}
11481da177e4SLinus Torvalds 	}
11491da177e4SLinus Torvalds 
11501da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11511da177e4SLinus Torvalds }
11521da177e4SLinus Torvalds 
1153a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11541da177e4SLinus Torvalds {
1155a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11561da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11571da177e4SLinus Torvalds 	__u16 handle;
11581da177e4SLinus Torvalds 
1159b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1160b6a0dc82SMarcel Holtmann 
1161a9de9248SMarcel Holtmann 	if (!status)
1162a9de9248SMarcel Holtmann 		return;
1163a9de9248SMarcel Holtmann 
1164a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11651da177e4SLinus Torvalds 	if (!cp)
1166a9de9248SMarcel Holtmann 		return;
11671da177e4SLinus Torvalds 
11681da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11691da177e4SLinus Torvalds 
1170a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
11711da177e4SLinus Torvalds 
11721da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11731da177e4SLinus Torvalds 
11741da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11755a08ecceSAndrei Emeltchenko 	if (acl) {
11765a08ecceSAndrei Emeltchenko 		sco = acl->link;
11775a08ecceSAndrei Emeltchenko 		if (sco) {
11781da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11791da177e4SLinus Torvalds 
11801da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11811da177e4SLinus Torvalds 			hci_conn_del(sco);
11821da177e4SLinus Torvalds 		}
11835a08ecceSAndrei Emeltchenko 	}
11841da177e4SLinus Torvalds 
11851da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11861da177e4SLinus Torvalds }
11871da177e4SLinus Torvalds 
1188f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1189f8558555SMarcel Holtmann {
1190f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1191f8558555SMarcel Holtmann 	struct hci_conn *conn;
1192f8558555SMarcel Holtmann 
1193f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1194f8558555SMarcel Holtmann 
1195f8558555SMarcel Holtmann 	if (!status)
1196f8558555SMarcel Holtmann 		return;
1197f8558555SMarcel Holtmann 
1198f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1199f8558555SMarcel Holtmann 	if (!cp)
1200f8558555SMarcel Holtmann 		return;
1201f8558555SMarcel Holtmann 
1202f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1203f8558555SMarcel Holtmann 
1204f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1205f8558555SMarcel Holtmann 	if (conn) {
1206f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1207f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1208f8558555SMarcel Holtmann 			hci_conn_put(conn);
1209f8558555SMarcel Holtmann 		}
1210f8558555SMarcel Holtmann 	}
1211f8558555SMarcel Holtmann 
1212f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1213f8558555SMarcel Holtmann }
1214f8558555SMarcel Holtmann 
1215f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1216f8558555SMarcel Holtmann {
1217f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1218f8558555SMarcel Holtmann 	struct hci_conn *conn;
1219f8558555SMarcel Holtmann 
1220f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1221f8558555SMarcel Holtmann 
1222f8558555SMarcel Holtmann 	if (!status)
1223f8558555SMarcel Holtmann 		return;
1224f8558555SMarcel Holtmann 
1225f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1226f8558555SMarcel Holtmann 	if (!cp)
1227f8558555SMarcel Holtmann 		return;
1228f8558555SMarcel Holtmann 
1229f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1230f8558555SMarcel Holtmann 
1231f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1232f8558555SMarcel Holtmann 	if (conn) {
1233f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1234f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1235f8558555SMarcel Holtmann 			hci_conn_put(conn);
1236f8558555SMarcel Holtmann 		}
1237f8558555SMarcel Holtmann 	}
1238f8558555SMarcel Holtmann 
1239f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1240f8558555SMarcel Holtmann }
1241f8558555SMarcel Holtmann 
1242127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1243392599b9SJohan Hedberg 							struct hci_conn *conn)
1244392599b9SJohan Hedberg {
1245392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1246392599b9SJohan Hedberg 		return 0;
1247392599b9SJohan Hedberg 
1248765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1249392599b9SJohan Hedberg 		return 0;
1250392599b9SJohan Hedberg 
1251392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1252e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1253392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1254e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1255e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1256392599b9SJohan Hedberg 		return 0;
1257392599b9SJohan Hedberg 
1258392599b9SJohan Hedberg 	return 1;
1259392599b9SJohan Hedberg }
1260392599b9SJohan Hedberg 
1261a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
12621da177e4SLinus Torvalds {
1263127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1264127178d2SJohan Hedberg 	struct hci_conn *conn;
1265127178d2SJohan Hedberg 
1266a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1267127178d2SJohan Hedberg 
1268127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1269127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1270127178d2SJohan Hedberg 	if (!status)
1271127178d2SJohan Hedberg 		return;
1272127178d2SJohan Hedberg 
1273127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1274127178d2SJohan Hedberg 	if (!cp)
1275127178d2SJohan Hedberg 		return;
1276127178d2SJohan Hedberg 
1277127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1278127178d2SJohan Hedberg 
1279127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
128079c6c70cSJohan Hedberg 	if (!conn)
128179c6c70cSJohan Hedberg 		goto unlock;
128279c6c70cSJohan Hedberg 
128379c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
128479c6c70cSJohan Hedberg 		goto unlock;
128579c6c70cSJohan Hedberg 
128679c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1287127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1288127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1289127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1290127178d2SJohan Hedberg 	}
1291127178d2SJohan Hedberg 
129279c6c70cSJohan Hedberg unlock:
1293127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1294a9de9248SMarcel Holtmann }
12951da177e4SLinus Torvalds 
1296769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1297769be974SMarcel Holtmann {
1298769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1299769be974SMarcel Holtmann 	struct hci_conn *conn;
1300769be974SMarcel Holtmann 
1301769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1302769be974SMarcel Holtmann 
1303769be974SMarcel Holtmann 	if (!status)
1304769be974SMarcel Holtmann 		return;
1305769be974SMarcel Holtmann 
1306769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1307769be974SMarcel Holtmann 	if (!cp)
1308769be974SMarcel Holtmann 		return;
1309769be974SMarcel Holtmann 
1310769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1311769be974SMarcel Holtmann 
1312769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1313769be974SMarcel Holtmann 	if (conn) {
1314769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1315769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1316769be974SMarcel Holtmann 			hci_conn_put(conn);
1317769be974SMarcel Holtmann 		}
1318769be974SMarcel Holtmann 	}
1319769be974SMarcel Holtmann 
1320769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1321769be974SMarcel Holtmann }
1322769be974SMarcel Holtmann 
1323769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1324769be974SMarcel Holtmann {
1325769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1326769be974SMarcel Holtmann 	struct hci_conn *conn;
1327769be974SMarcel Holtmann 
1328769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1329769be974SMarcel Holtmann 
1330769be974SMarcel Holtmann 	if (!status)
1331769be974SMarcel Holtmann 		return;
1332769be974SMarcel Holtmann 
1333769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1334769be974SMarcel Holtmann 	if (!cp)
1335769be974SMarcel Holtmann 		return;
1336769be974SMarcel Holtmann 
1337769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1338769be974SMarcel Holtmann 
1339769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1340769be974SMarcel Holtmann 	if (conn) {
1341769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1342769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1343769be974SMarcel Holtmann 			hci_conn_put(conn);
1344769be974SMarcel Holtmann 		}
1345769be974SMarcel Holtmann 	}
1346769be974SMarcel Holtmann 
1347769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1348769be974SMarcel Holtmann }
1349769be974SMarcel Holtmann 
1350a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1351a9de9248SMarcel Holtmann {
1352b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1353b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1354b6a0dc82SMarcel Holtmann 	__u16 handle;
1355b6a0dc82SMarcel Holtmann 
1356a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1357b6a0dc82SMarcel Holtmann 
1358b6a0dc82SMarcel Holtmann 	if (!status)
1359b6a0dc82SMarcel Holtmann 		return;
1360b6a0dc82SMarcel Holtmann 
1361b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1362b6a0dc82SMarcel Holtmann 	if (!cp)
1363b6a0dc82SMarcel Holtmann 		return;
1364b6a0dc82SMarcel Holtmann 
1365b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1366b6a0dc82SMarcel Holtmann 
1367b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1368b6a0dc82SMarcel Holtmann 
1369b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1370b6a0dc82SMarcel Holtmann 
1371b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
13725a08ecceSAndrei Emeltchenko 	if (acl) {
13735a08ecceSAndrei Emeltchenko 		sco = acl->link;
13745a08ecceSAndrei Emeltchenko 		if (sco) {
1375b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1376b6a0dc82SMarcel Holtmann 
1377b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1378b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1379b6a0dc82SMarcel Holtmann 		}
13805a08ecceSAndrei Emeltchenko 	}
1381b6a0dc82SMarcel Holtmann 
1382b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1383a9de9248SMarcel Holtmann }
1384a9de9248SMarcel Holtmann 
1385a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1386a9de9248SMarcel Holtmann {
1387a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
138804837f64SMarcel Holtmann 	struct hci_conn *conn;
138904837f64SMarcel Holtmann 
1390a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1391a9de9248SMarcel Holtmann 
1392a9de9248SMarcel Holtmann 	if (!status)
1393a9de9248SMarcel Holtmann 		return;
1394a9de9248SMarcel Holtmann 
1395a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
139604837f64SMarcel Holtmann 	if (!cp)
1397a9de9248SMarcel Holtmann 		return;
139804837f64SMarcel Holtmann 
139904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
140004837f64SMarcel Holtmann 
140104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1402e73439d8SMarcel Holtmann 	if (conn) {
140304837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
140404837f64SMarcel Holtmann 
1405e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1406e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1407e73439d8SMarcel Holtmann 	}
1408e73439d8SMarcel Holtmann 
140904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
141004837f64SMarcel Holtmann }
141104837f64SMarcel Holtmann 
1412a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1413a9de9248SMarcel Holtmann {
1414a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
141504837f64SMarcel Holtmann 	struct hci_conn *conn;
141604837f64SMarcel Holtmann 
1417a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1418a9de9248SMarcel Holtmann 
1419a9de9248SMarcel Holtmann 	if (!status)
1420a9de9248SMarcel Holtmann 		return;
1421a9de9248SMarcel Holtmann 
1422a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
142304837f64SMarcel Holtmann 	if (!cp)
1424a9de9248SMarcel Holtmann 		return;
142504837f64SMarcel Holtmann 
142604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
142704837f64SMarcel Holtmann 
142804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1429e73439d8SMarcel Holtmann 	if (conn) {
143004837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
143104837f64SMarcel Holtmann 
1432e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1433e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1434e73439d8SMarcel Holtmann 	}
1435e73439d8SMarcel Holtmann 
143604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
143704837f64SMarcel Holtmann }
143804837f64SMarcel Holtmann 
1439fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1440fcd89c09SVille Tervo {
1441fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1442fcd89c09SVille Tervo 	struct hci_conn *conn;
1443fcd89c09SVille Tervo 
1444fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1445fcd89c09SVille Tervo 
1446fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1447fcd89c09SVille Tervo 	if (!cp)
1448fcd89c09SVille Tervo 		return;
1449fcd89c09SVille Tervo 
1450fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1451fcd89c09SVille Tervo 
1452fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1453fcd89c09SVille Tervo 
1454fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1455fcd89c09SVille Tervo 		conn);
1456fcd89c09SVille Tervo 
1457fcd89c09SVille Tervo 	if (status) {
1458fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1459fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1460fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1461fcd89c09SVille Tervo 			hci_conn_del(conn);
1462fcd89c09SVille Tervo 		}
1463fcd89c09SVille Tervo 	} else {
1464fcd89c09SVille Tervo 		if (!conn) {
1465fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
146629b7988aSAndre Guedes 			if (conn) {
146729b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1468fcd89c09SVille Tervo 				conn->out = 1;
146929b7988aSAndre Guedes 			} else {
1470fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1471fcd89c09SVille Tervo 			}
1472fcd89c09SVille Tervo 		}
147329b7988aSAndre Guedes 	}
1474fcd89c09SVille Tervo 
1475fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1476fcd89c09SVille Tervo }
1477fcd89c09SVille Tervo 
1478a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1479a7a595f6SVinicius Costa Gomes {
1480a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1481a7a595f6SVinicius Costa Gomes }
1482a7a595f6SVinicius Costa Gomes 
14831da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14841da177e4SLinus Torvalds {
14851da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
14861da177e4SLinus Torvalds 
14871da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
14881da177e4SLinus Torvalds 
148923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
14906bd57416SMarcel Holtmann 
1491a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
149289352e7dSAndre Guedes 
149389352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
149489352e7dSAndre Guedes 		return;
149589352e7dSAndre Guedes 
149656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1497744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 0);
149856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
14991da177e4SLinus Torvalds }
15001da177e4SLinus Torvalds 
15011da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
15021da177e4SLinus Torvalds {
150345bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1504a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
15051da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
15061da177e4SLinus Torvalds 
15071da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
15081da177e4SLinus Torvalds 
150945bb4bf0SMarcel Holtmann 	if (!num_rsp)
151045bb4bf0SMarcel Holtmann 		return;
151145bb4bf0SMarcel Holtmann 
15121da177e4SLinus Torvalds 	hci_dev_lock(hdev);
151345bb4bf0SMarcel Holtmann 
1514e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
15151da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
15161da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
15171da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
15181da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
15191da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
15201da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
15211da177e4SLinus Torvalds 		data.rssi		= 0x00;
152241a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
15231da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
152448264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
15254c659c39SJohan Hedberg 						info->dev_class, 0, NULL);
15261da177e4SLinus Torvalds 	}
152745bb4bf0SMarcel Holtmann 
15281da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15291da177e4SLinus Torvalds }
15301da177e4SLinus Torvalds 
1531a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15321da177e4SLinus Torvalds {
1533a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1534a9de9248SMarcel Holtmann 	struct hci_conn *conn;
15351da177e4SLinus Torvalds 
1536a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
153745bb4bf0SMarcel Holtmann 
15381da177e4SLinus Torvalds 	hci_dev_lock(hdev);
153945bb4bf0SMarcel Holtmann 
1540a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
15419499237aSMarcel Holtmann 	if (!conn) {
15429499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
15439499237aSMarcel Holtmann 			goto unlock;
15449499237aSMarcel Holtmann 
15459499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1546a9de9248SMarcel Holtmann 		if (!conn)
1547a9de9248SMarcel Holtmann 			goto unlock;
154845bb4bf0SMarcel Holtmann 
15499499237aSMarcel Holtmann 		conn->type = SCO_LINK;
15509499237aSMarcel Holtmann 	}
15519499237aSMarcel Holtmann 
1552a9de9248SMarcel Holtmann 	if (!ev->status) {
1553a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1554769be974SMarcel Holtmann 
1555769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1556769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1557769be974SMarcel Holtmann 			hci_conn_hold(conn);
1558052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
155948264f06SJohan Hedberg 			mgmt_connected(hdev, &ev->bdaddr, conn->type,
156048264f06SJohan Hedberg 							conn->dst_type);
1561769be974SMarcel Holtmann 		} else
1562a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1563a9de9248SMarcel Holtmann 
15649eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
15657d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
15667d0db0a3SMarcel Holtmann 
1567a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1568a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1569a9de9248SMarcel Holtmann 
1570a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1571a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1572a9de9248SMarcel Holtmann 
1573a9de9248SMarcel Holtmann 		/* Get remote features */
1574a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1575a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1576a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1577769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1578769be974SMarcel Holtmann 							sizeof(cp), &cp);
157945bb4bf0SMarcel Holtmann 		}
1580a9de9248SMarcel Holtmann 
1581a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1582d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1583a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1584a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1585a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1586a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1587a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1588a9de9248SMarcel Holtmann 		}
158917d5c04cSJohan Hedberg 	} else {
1590a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
159117d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1592744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
159348264f06SJohan Hedberg 						conn->dst_type, ev->status);
159417d5c04cSJohan Hedberg 	}
159545bb4bf0SMarcel Holtmann 
1596e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1597e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
159845bb4bf0SMarcel Holtmann 
1599769be974SMarcel Holtmann 	if (ev->status) {
1600a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1601a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1602c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1603c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1604a9de9248SMarcel Holtmann 
1605a9de9248SMarcel Holtmann unlock:
16061da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1607a9de9248SMarcel Holtmann 
1608a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
16091da177e4SLinus Torvalds }
16101da177e4SLinus Torvalds 
16111da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
16121da177e4SLinus Torvalds {
1613a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
16141da177e4SLinus Torvalds 	int mask = hdev->link_mode;
16151da177e4SLinus Torvalds 
1616a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
16171da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
16181da177e4SLinus Torvalds 
16191da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
16201da177e4SLinus Torvalds 
1621138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1622138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
16231da177e4SLinus Torvalds 		/* Connection accepted */
1624c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
16251da177e4SLinus Torvalds 		struct hci_conn *conn;
16261da177e4SLinus Torvalds 
16271da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1628b6a0dc82SMarcel Holtmann 
1629cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1630cc11b9c1SAndrei Emeltchenko 		if (ie)
1631c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1632c7bdd502SMarcel Holtmann 
16331da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16341da177e4SLinus Torvalds 		if (!conn) {
1635cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1636cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1637893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
16381da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
16391da177e4SLinus Torvalds 				return;
16401da177e4SLinus Torvalds 			}
16411da177e4SLinus Torvalds 		}
1642b6a0dc82SMarcel Holtmann 
16431da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
16441da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1645b6a0dc82SMarcel Holtmann 
16461da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
16471da177e4SLinus Torvalds 
1648b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1649b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1650b6a0dc82SMarcel Holtmann 
16511da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
16521da177e4SLinus Torvalds 
16531da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
16541da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
16551da177e4SLinus Torvalds 			else
16561da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
16571da177e4SLinus Torvalds 
1658b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1659b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1660b6a0dc82SMarcel Holtmann 		} else {
1661b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1662b6a0dc82SMarcel Holtmann 
1663b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1664a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1665b6a0dc82SMarcel Holtmann 
1666b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1667b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1668b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1669b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1670b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1671b6a0dc82SMarcel Holtmann 
1672b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1673b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1674b6a0dc82SMarcel Holtmann 		}
16751da177e4SLinus Torvalds 	} else {
16761da177e4SLinus Torvalds 		/* Connection rejected */
16771da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
16781da177e4SLinus Torvalds 
16791da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
16809f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1681a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
16821da177e4SLinus Torvalds 	}
16831da177e4SLinus Torvalds }
16841da177e4SLinus Torvalds 
16851da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16861da177e4SLinus Torvalds {
1687a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
168804837f64SMarcel Holtmann 	struct hci_conn *conn;
16891da177e4SLinus Torvalds 
16901da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
16911da177e4SLinus Torvalds 
16921da177e4SLinus Torvalds 	hci_dev_lock(hdev);
16931da177e4SLinus Torvalds 
169404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1695f7520543SJohan Hedberg 	if (!conn)
1696f7520543SJohan Hedberg 		goto unlock;
1697f7520543SJohan Hedberg 
169837d9ef76SJohan Hedberg 	if (ev->status == 0)
16991da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
17007d0db0a3SMarcel Holtmann 
170137d9ef76SJohan Hedberg 	if (conn->type == ACL_LINK || conn->type == LE_LINK) {
170237d9ef76SJohan Hedberg 		if (ev->status != 0)
170337d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
170437d9ef76SJohan Hedberg 		else
170548264f06SJohan Hedberg 			mgmt_disconnected(hdev, &conn->dst, conn->type,
170648264f06SJohan Hedberg 							conn->dst_type);
170737d9ef76SJohan Hedberg 	}
1708f7520543SJohan Hedberg 
170937d9ef76SJohan Hedberg 	if (ev->status == 0) {
17102950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
17111da177e4SLinus Torvalds 		hci_conn_del(conn);
171237d9ef76SJohan Hedberg 	}
17131da177e4SLinus Torvalds 
1714f7520543SJohan Hedberg unlock:
17151da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17161da177e4SLinus Torvalds }
17171da177e4SLinus Torvalds 
1718a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1719a9de9248SMarcel Holtmann {
1720a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1721a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1722a9de9248SMarcel Holtmann 
1723a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1724a9de9248SMarcel Holtmann 
1725a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1726a9de9248SMarcel Holtmann 
1727a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1728d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1729d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1730d7556e20SWaldemar Rymarkiewicz 
1731765c2a96SJohan Hedberg 	if (!ev->status) {
173219f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1733d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1734d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
173519f8def0SWaldemar Rymarkiewicz 		} else {
1736a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1737765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
173819f8def0SWaldemar Rymarkiewicz 		}
17392a611692SJohan Hedberg 	} else {
1740744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
17412a611692SJohan Hedberg 	}
1742a9de9248SMarcel Holtmann 
1743a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
174419f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1745a9de9248SMarcel Holtmann 
1746f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1747d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1748f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1749f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1750f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1751d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1752d7556e20SWaldemar Rymarkiewicz 									&cp);
1753f8558555SMarcel Holtmann 		} else {
1754f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1755f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1756f8558555SMarcel Holtmann 			hci_conn_put(conn);
1757f8558555SMarcel Holtmann 		}
1758052b30b0SMarcel Holtmann 	} else {
1759a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1760a9de9248SMarcel Holtmann 
1761052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1762052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1763052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1764052b30b0SMarcel Holtmann 	}
1765052b30b0SMarcel Holtmann 
1766a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1767a9de9248SMarcel Holtmann 		if (!ev->status) {
1768a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1769f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1770f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1771d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1772d7556e20SWaldemar Rymarkiewicz 									&cp);
1773a9de9248SMarcel Holtmann 		} else {
1774a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1775a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1776a9de9248SMarcel Holtmann 		}
1777a9de9248SMarcel Holtmann 	}
1778a9de9248SMarcel Holtmann 
1779d7556e20SWaldemar Rymarkiewicz unlock:
1780a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1781a9de9248SMarcel Holtmann }
1782a9de9248SMarcel Holtmann 
1783a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1784a9de9248SMarcel Holtmann {
1785127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1786127178d2SJohan Hedberg 	struct hci_conn *conn;
1787127178d2SJohan Hedberg 
1788a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1789a9de9248SMarcel Holtmann 
1790a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1791127178d2SJohan Hedberg 
1792127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1793127178d2SJohan Hedberg 
1794a88a9652SJohan Hedberg 	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
1795744cf19eSJohan Hedberg 		mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
1796a88a9652SJohan Hedberg 
1797127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
179879c6c70cSJohan Hedberg 	if (!conn)
179979c6c70cSJohan Hedberg 		goto unlock;
180079c6c70cSJohan Hedberg 
180179c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
180279c6c70cSJohan Hedberg 		goto unlock;
180379c6c70cSJohan Hedberg 
180479c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1805127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1806127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1807127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1808127178d2SJohan Hedberg 	}
1809127178d2SJohan Hedberg 
181079c6c70cSJohan Hedberg unlock:
1811127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1812a9de9248SMarcel Holtmann }
1813a9de9248SMarcel Holtmann 
1814a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1815a9de9248SMarcel Holtmann {
1816a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1817a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1818a9de9248SMarcel Holtmann 
1819a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1820a9de9248SMarcel Holtmann 
1821a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1822a9de9248SMarcel Holtmann 
1823a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1824a9de9248SMarcel Holtmann 	if (conn) {
1825a9de9248SMarcel Holtmann 		if (!ev->status) {
1826ae293196SMarcel Holtmann 			if (ev->encrypt) {
1827ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1828ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1829a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1830da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1831ae293196SMarcel Holtmann 			} else
1832a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1833a9de9248SMarcel Holtmann 		}
1834a9de9248SMarcel Holtmann 
1835a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1836a9de9248SMarcel Holtmann 
1837f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1838f8558555SMarcel Holtmann 			if (!ev->status)
1839f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1840f8558555SMarcel Holtmann 
1841f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1842f8558555SMarcel Holtmann 			hci_conn_put(conn);
1843f8558555SMarcel Holtmann 		} else
1844a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1845a9de9248SMarcel Holtmann 	}
1846a9de9248SMarcel Holtmann 
1847a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1848a9de9248SMarcel Holtmann }
1849a9de9248SMarcel Holtmann 
1850a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1851a9de9248SMarcel Holtmann {
1852a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1853a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1854a9de9248SMarcel Holtmann 
1855a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1856a9de9248SMarcel Holtmann 
1857a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1858a9de9248SMarcel Holtmann 
1859a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1860a9de9248SMarcel Holtmann 	if (conn) {
1861a9de9248SMarcel Holtmann 		if (!ev->status)
1862a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1863a9de9248SMarcel Holtmann 
1864a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1865a9de9248SMarcel Holtmann 
1866a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1867a9de9248SMarcel Holtmann 	}
1868a9de9248SMarcel Holtmann 
1869a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1870a9de9248SMarcel Holtmann }
1871a9de9248SMarcel Holtmann 
1872a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1873a9de9248SMarcel Holtmann {
1874a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1875a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1876a9de9248SMarcel Holtmann 
1877a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1878a9de9248SMarcel Holtmann 
1879a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1880a9de9248SMarcel Holtmann 
1881a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1882ccd556feSJohan Hedberg 	if (!conn)
1883ccd556feSJohan Hedberg 		goto unlock;
1884ccd556feSJohan Hedberg 
1885769be974SMarcel Holtmann 	if (!ev->status)
1886a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1887a9de9248SMarcel Holtmann 
1888ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1889ccd556feSJohan Hedberg 		goto unlock;
1890ccd556feSJohan Hedberg 
1891ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1892769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1893769be974SMarcel Holtmann 		cp.handle = ev->handle;
1894769be974SMarcel Holtmann 		cp.page = 0x01;
1895ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1896769be974SMarcel Holtmann 							sizeof(cp), &cp);
1897392599b9SJohan Hedberg 		goto unlock;
1898392599b9SJohan Hedberg 	}
1899392599b9SJohan Hedberg 
1900127178d2SJohan Hedberg 	if (!ev->status) {
1901127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1902127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1903127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1904127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1905127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1906127178d2SJohan Hedberg 	}
1907392599b9SJohan Hedberg 
1908127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1909769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1910769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1911769be974SMarcel Holtmann 		hci_conn_put(conn);
1912769be974SMarcel Holtmann 	}
1913769be974SMarcel Holtmann 
1914ccd556feSJohan Hedberg unlock:
1915a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1916a9de9248SMarcel Holtmann }
1917a9de9248SMarcel Holtmann 
1918a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1919a9de9248SMarcel Holtmann {
1920a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1921a9de9248SMarcel Holtmann }
1922a9de9248SMarcel Holtmann 
1923a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1924a9de9248SMarcel Holtmann {
1925a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1926a9de9248SMarcel Holtmann }
1927a9de9248SMarcel Holtmann 
1928a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1929a9de9248SMarcel Holtmann {
1930a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1931a9de9248SMarcel Holtmann 	__u16 opcode;
1932a9de9248SMarcel Holtmann 
1933a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1934a9de9248SMarcel Holtmann 
1935a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1936a9de9248SMarcel Holtmann 
1937a9de9248SMarcel Holtmann 	switch (opcode) {
1938a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1939a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1940a9de9248SMarcel Holtmann 		break;
1941a9de9248SMarcel Holtmann 
1942a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1943a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1944a9de9248SMarcel Holtmann 		break;
1945a9de9248SMarcel Holtmann 
1946a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1947a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1948a9de9248SMarcel Holtmann 		break;
1949a9de9248SMarcel Holtmann 
1950a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1951a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1952a9de9248SMarcel Holtmann 		break;
1953a9de9248SMarcel Holtmann 
1954e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1955e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1956e4e8e37cSMarcel Holtmann 		break;
1957e4e8e37cSMarcel Holtmann 
1958a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1959a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1960a9de9248SMarcel Holtmann 		break;
1961a9de9248SMarcel Holtmann 
1962e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1963e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1964e4e8e37cSMarcel Holtmann 		break;
1965e4e8e37cSMarcel Holtmann 
1966e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1967e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1968e4e8e37cSMarcel Holtmann 		break;
1969e4e8e37cSMarcel Holtmann 
1970a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1971a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1972a9de9248SMarcel Holtmann 		break;
1973a9de9248SMarcel Holtmann 
1974a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1975a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1976a9de9248SMarcel Holtmann 		break;
1977a9de9248SMarcel Holtmann 
1978a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1979a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1980a9de9248SMarcel Holtmann 		break;
1981a9de9248SMarcel Holtmann 
1982a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1983a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1984a9de9248SMarcel Holtmann 		break;
1985a9de9248SMarcel Holtmann 
1986a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1987a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1988a9de9248SMarcel Holtmann 		break;
1989a9de9248SMarcel Holtmann 
1990a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1991a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1992a9de9248SMarcel Holtmann 		break;
1993a9de9248SMarcel Holtmann 
1994a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1995a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1996a9de9248SMarcel Holtmann 		break;
1997a9de9248SMarcel Holtmann 
1998a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1999a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2000a9de9248SMarcel Holtmann 		break;
2001a9de9248SMarcel Holtmann 
2002a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2003a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2004a9de9248SMarcel Holtmann 		break;
2005a9de9248SMarcel Holtmann 
2006a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2007a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2008a9de9248SMarcel Holtmann 		break;
2009a9de9248SMarcel Holtmann 
2010a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2011a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2012a9de9248SMarcel Holtmann 		break;
2013a9de9248SMarcel Holtmann 
2014333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
2015333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
2016333140b5SMarcel Holtmann 		break;
2017333140b5SMarcel Holtmann 
2018333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2019333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2020333140b5SMarcel Holtmann 		break;
2021333140b5SMarcel Holtmann 
2022a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2023a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2024a9de9248SMarcel Holtmann 		break;
2025a9de9248SMarcel Holtmann 
2026a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2027a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2028a9de9248SMarcel Holtmann 		break;
2029a9de9248SMarcel Holtmann 
2030a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2031a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2032a9de9248SMarcel Holtmann 		break;
2033a9de9248SMarcel Holtmann 
2034971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2035971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2036971e3a4bSAndre Guedes 		break;
2037971e3a4bSAndre Guedes 
2038a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2039a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2040a9de9248SMarcel Holtmann 		break;
2041a9de9248SMarcel Holtmann 
2042a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2043a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2044a9de9248SMarcel Holtmann 		break;
2045a9de9248SMarcel Holtmann 
2046350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2047350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2048350ee4cfSAndrei Emeltchenko 		break;
2049350ee4cfSAndrei Emeltchenko 
205023bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
205123bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
205223bb5763SJohan Hedberg 		break;
205323bb5763SJohan Hedberg 
20541e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
20551e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
20561e89cffbSAndrei Emeltchenko 		break;
20571e89cffbSAndrei Emeltchenko 
2058928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2059928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2060928abaa7SAndrei Emeltchenko 		break;
2061928abaa7SAndrei Emeltchenko 
2062b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2063b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2064b0916ea0SJohan Hedberg 		break;
2065b0916ea0SJohan Hedberg 
2066d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2067d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2068d5859e22SJohan Hedberg 		break;
2069d5859e22SJohan Hedberg 
2070d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2071d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2072d5859e22SJohan Hedberg 		break;
2073d5859e22SJohan Hedberg 
2074d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2075d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2076d5859e22SJohan Hedberg 		break;
2077d5859e22SJohan Hedberg 
2078d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2079d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2080d5859e22SJohan Hedberg 		break;
2081d5859e22SJohan Hedberg 
2082980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2083980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2084980e1a53SJohan Hedberg 		break;
2085980e1a53SJohan Hedberg 
2086980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2087980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2088980e1a53SJohan Hedberg 		break;
2089980e1a53SJohan Hedberg 
2090c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2091c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2092c35938b2SSzymon Janc 		break;
2093c35938b2SSzymon Janc 
20946ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
20956ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
20966ed58ec5SVille Tervo 		break;
20976ed58ec5SVille Tervo 
2098a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2099a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2100a5c29683SJohan Hedberg 		break;
2101a5c29683SJohan Hedberg 
2102a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2103a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2104a5c29683SJohan Hedberg 		break;
2105a5c29683SJohan Hedberg 
21061143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
21071143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
21081143d458SBrian Gix 		break;
21091143d458SBrian Gix 
21101143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
21111143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
211207f7fa5dSAndre Guedes 
211307f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
211407f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
21151143d458SBrian Gix 		break;
21161143d458SBrian Gix 
2117eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2118eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2119eb9d91f5SAndre Guedes 		break;
2120eb9d91f5SAndre Guedes 
2121a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2122a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2123a7a595f6SVinicius Costa Gomes 		break;
2124a7a595f6SVinicius Costa Gomes 
2125a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2126a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2127a7a595f6SVinicius Costa Gomes 		break;
2128a7a595f6SVinicius Costa Gomes 
2129f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2130f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2131f9b49306SAndre Guedes 		break;
2132f9b49306SAndre Guedes 
2133a9de9248SMarcel Holtmann 	default:
2134a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2135a9de9248SMarcel Holtmann 		break;
2136a9de9248SMarcel Holtmann 	}
2137a9de9248SMarcel Holtmann 
21386bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
21396bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
21406bd32326SVille Tervo 
2141a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2142a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2143a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2144c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2145a9de9248SMarcel Holtmann 	}
2146a9de9248SMarcel Holtmann }
2147a9de9248SMarcel Holtmann 
2148a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2149a9de9248SMarcel Holtmann {
2150a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2151a9de9248SMarcel Holtmann 	__u16 opcode;
2152a9de9248SMarcel Holtmann 
2153a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2154a9de9248SMarcel Holtmann 
2155a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2156a9de9248SMarcel Holtmann 
2157a9de9248SMarcel Holtmann 	switch (opcode) {
2158a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2159a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2160a9de9248SMarcel Holtmann 		break;
2161a9de9248SMarcel Holtmann 
2162a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2163a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2164a9de9248SMarcel Holtmann 		break;
2165a9de9248SMarcel Holtmann 
2166a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2167a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2168a9de9248SMarcel Holtmann 		break;
2169a9de9248SMarcel Holtmann 
2170f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2171f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2172f8558555SMarcel Holtmann 		break;
2173f8558555SMarcel Holtmann 
2174f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2175f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2176f8558555SMarcel Holtmann 		break;
2177f8558555SMarcel Holtmann 
2178a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2179a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2180a9de9248SMarcel Holtmann 		break;
2181a9de9248SMarcel Holtmann 
2182769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2183769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2184769be974SMarcel Holtmann 		break;
2185769be974SMarcel Holtmann 
2186769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2187769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2188769be974SMarcel Holtmann 		break;
2189769be974SMarcel Holtmann 
2190a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2191a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2192a9de9248SMarcel Holtmann 		break;
2193a9de9248SMarcel Holtmann 
2194a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2195a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2196a9de9248SMarcel Holtmann 		break;
2197a9de9248SMarcel Holtmann 
2198a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2199a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2200a9de9248SMarcel Holtmann 		break;
2201a9de9248SMarcel Holtmann 
22028962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
22038962ee74SJohan Hedberg 		if (ev->status != 0)
220437d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
22058962ee74SJohan Hedberg 		break;
22068962ee74SJohan Hedberg 
2207fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2208fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2209fcd89c09SVille Tervo 		break;
2210fcd89c09SVille Tervo 
2211a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2212a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2213a7a595f6SVinicius Costa Gomes 		break;
2214a7a595f6SVinicius Costa Gomes 
2215a9de9248SMarcel Holtmann 	default:
2216a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2217a9de9248SMarcel Holtmann 		break;
2218a9de9248SMarcel Holtmann 	}
2219a9de9248SMarcel Holtmann 
22206bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
22216bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
22226bd32326SVille Tervo 
222310572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2224a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2225a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2226c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2227a9de9248SMarcel Holtmann 	}
2228a9de9248SMarcel Holtmann }
2229a9de9248SMarcel Holtmann 
2230a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2231a9de9248SMarcel Holtmann {
2232a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2233a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2234a9de9248SMarcel Holtmann 
2235a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2236a9de9248SMarcel Holtmann 
2237a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2238a9de9248SMarcel Holtmann 
2239a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2240a9de9248SMarcel Holtmann 	if (conn) {
2241a9de9248SMarcel Holtmann 		if (!ev->status) {
2242a9de9248SMarcel Holtmann 			if (ev->role)
2243a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2244a9de9248SMarcel Holtmann 			else
2245a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2246a9de9248SMarcel Holtmann 		}
2247a9de9248SMarcel Holtmann 
2248a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2249a9de9248SMarcel Holtmann 
2250a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2251a9de9248SMarcel Holtmann 	}
2252a9de9248SMarcel Holtmann 
2253a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2254a9de9248SMarcel Holtmann }
2255a9de9248SMarcel Holtmann 
22561da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
22571da177e4SLinus Torvalds {
2258a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
22591ebb9252SMarcel Holtmann 	__le16 *ptr;
22601da177e4SLinus Torvalds 	int i;
22611da177e4SLinus Torvalds 
22621da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
22631da177e4SLinus Torvalds 
22641da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
22651da177e4SLinus Torvalds 
22661da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
22671da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
22681da177e4SLinus Torvalds 		return;
22691da177e4SLinus Torvalds 	}
22701da177e4SLinus Torvalds 
22711ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
22721da177e4SLinus Torvalds 		struct hci_conn *conn;
22731da177e4SLinus Torvalds 		__u16  handle, count;
22741da177e4SLinus Torvalds 
227583985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
227683985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
22771da177e4SLinus Torvalds 
22781da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2279f4280918SAndrei Emeltchenko 		if (!conn)
2280f4280918SAndrei Emeltchenko 			continue;
2281f4280918SAndrei Emeltchenko 
22821da177e4SLinus Torvalds 		conn->sent -= count;
22831da177e4SLinus Torvalds 
2284f4280918SAndrei Emeltchenko 		switch (conn->type) {
2285f4280918SAndrei Emeltchenko 		case ACL_LINK:
228670f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
228770f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
22881da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2289f4280918SAndrei Emeltchenko 			break;
2290f4280918SAndrei Emeltchenko 
2291f4280918SAndrei Emeltchenko 		case LE_LINK:
22926ed58ec5SVille Tervo 			if (hdev->le_pkts) {
22936ed58ec5SVille Tervo 				hdev->le_cnt += count;
22946ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
22956ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
22966ed58ec5SVille Tervo 			} else {
22976ed58ec5SVille Tervo 				hdev->acl_cnt += count;
22986ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
22996ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
23006ed58ec5SVille Tervo 			}
2301f4280918SAndrei Emeltchenko 			break;
2302f4280918SAndrei Emeltchenko 
2303f4280918SAndrei Emeltchenko 		case SCO_LINK:
230470f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
230570f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
23065b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2307f4280918SAndrei Emeltchenko 			break;
2308f4280918SAndrei Emeltchenko 
2309f4280918SAndrei Emeltchenko 		default:
2310f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2311f4280918SAndrei Emeltchenko 			break;
23121da177e4SLinus Torvalds 		}
23131da177e4SLinus Torvalds 	}
2314a9de9248SMarcel Holtmann 
23153eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
23161da177e4SLinus Torvalds }
23171da177e4SLinus Torvalds 
231804837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
23191da177e4SLinus Torvalds {
2320a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
232104837f64SMarcel Holtmann 	struct hci_conn *conn;
23221da177e4SLinus Torvalds 
23231da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
23241da177e4SLinus Torvalds 
23251da177e4SLinus Torvalds 	hci_dev_lock(hdev);
23261da177e4SLinus Torvalds 
232704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
232804837f64SMarcel Holtmann 	if (conn) {
232904837f64SMarcel Holtmann 		conn->mode = ev->mode;
233004837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
233104837f64SMarcel Holtmann 
233204837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
233304837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
233404837f64SMarcel Holtmann 				conn->power_save = 1;
233504837f64SMarcel Holtmann 			else
233604837f64SMarcel Holtmann 				conn->power_save = 0;
233704837f64SMarcel Holtmann 		}
2338e73439d8SMarcel Holtmann 
2339e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2340e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
234104837f64SMarcel Holtmann 	}
234204837f64SMarcel Holtmann 
234304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
234404837f64SMarcel Holtmann }
234504837f64SMarcel Holtmann 
23461da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
23471da177e4SLinus Torvalds {
2348052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2349052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2350052b30b0SMarcel Holtmann 
2351a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2352052b30b0SMarcel Holtmann 
2353052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2354052b30b0SMarcel Holtmann 
2355052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2356b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2357b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2358b6f98044SWaldemar Rymarkiewicz 
2359b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2360052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2361052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2362052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2363052b30b0SMarcel Holtmann 	}
2364052b30b0SMarcel Holtmann 
236503b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
236603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
236703b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2368582fbe9eSJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->flags)) {
2369a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2370a770bb5aSWaldemar Rymarkiewicz 
2371a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2372a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2373a770bb5aSWaldemar Rymarkiewicz 		else
2374a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2375a770bb5aSWaldemar Rymarkiewicz 
2376744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2377a770bb5aSWaldemar Rymarkiewicz 	}
2378980e1a53SJohan Hedberg 
2379b6f98044SWaldemar Rymarkiewicz unlock:
2380052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
23811da177e4SLinus Torvalds }
23821da177e4SLinus Torvalds 
23831da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
23841da177e4SLinus Torvalds {
238555ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
238655ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
238755ed8ca1SJohan Hedberg 	struct hci_conn *conn;
238855ed8ca1SJohan Hedberg 	struct link_key *key;
238955ed8ca1SJohan Hedberg 
2390a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
239155ed8ca1SJohan Hedberg 
239255ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
239355ed8ca1SJohan Hedberg 		return;
239455ed8ca1SJohan Hedberg 
239555ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
239655ed8ca1SJohan Hedberg 
239755ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
239855ed8ca1SJohan Hedberg 	if (!key) {
239955ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
240055ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
240155ed8ca1SJohan Hedberg 		goto not_found;
240255ed8ca1SJohan Hedberg 	}
240355ed8ca1SJohan Hedberg 
240455ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
240555ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
240655ed8ca1SJohan Hedberg 
2407b6020ba0SWaldemar Rymarkiewicz 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2408b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
240955ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
241055ed8ca1SJohan Hedberg 		goto not_found;
241155ed8ca1SJohan Hedberg 	}
241255ed8ca1SJohan Hedberg 
241355ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
241460b83f57SWaldemar Rymarkiewicz 	if (conn) {
241560b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
241660b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
241760b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
241855ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
241955ed8ca1SJohan Hedberg 			goto not_found;
242055ed8ca1SJohan Hedberg 		}
242155ed8ca1SJohan Hedberg 
242260b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
242360b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
242460b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
242560b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
242660b83f57SWaldemar Rymarkiewicz 			goto not_found;
242760b83f57SWaldemar Rymarkiewicz 		}
242860b83f57SWaldemar Rymarkiewicz 
242960b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
243060b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
243160b83f57SWaldemar Rymarkiewicz 	}
243260b83f57SWaldemar Rymarkiewicz 
243355ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
243455ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
243555ed8ca1SJohan Hedberg 
243655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
243755ed8ca1SJohan Hedberg 
243855ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
243955ed8ca1SJohan Hedberg 
244055ed8ca1SJohan Hedberg 	return;
244155ed8ca1SJohan Hedberg 
244255ed8ca1SJohan Hedberg not_found:
244355ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
244455ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
24451da177e4SLinus Torvalds }
24461da177e4SLinus Torvalds 
24471da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
24481da177e4SLinus Torvalds {
2449052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2450052b30b0SMarcel Holtmann 	struct hci_conn *conn;
245155ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2452052b30b0SMarcel Holtmann 
2453a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2454052b30b0SMarcel Holtmann 
2455052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2456052b30b0SMarcel Holtmann 
2457052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2458052b30b0SMarcel Holtmann 	if (conn) {
2459052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2460052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2461980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
246213d39315SWaldemar Rymarkiewicz 
246313d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
246413d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
246513d39315SWaldemar Rymarkiewicz 
2466052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2467052b30b0SMarcel Holtmann 	}
2468052b30b0SMarcel Holtmann 
246955ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2470d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
247155ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
247255ed8ca1SJohan Hedberg 
2473052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
24741da177e4SLinus Torvalds }
24751da177e4SLinus Torvalds 
247604837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
247704837f64SMarcel Holtmann {
2478a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
247904837f64SMarcel Holtmann 	struct hci_conn *conn;
248004837f64SMarcel Holtmann 
248104837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
248204837f64SMarcel Holtmann 
248304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
248404837f64SMarcel Holtmann 
248504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
24861da177e4SLinus Torvalds 	if (conn && !ev->status) {
24871da177e4SLinus Torvalds 		struct inquiry_entry *ie;
24881da177e4SLinus Torvalds 
2489cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2490cc11b9c1SAndrei Emeltchenko 		if (ie) {
24911da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
24921da177e4SLinus Torvalds 			ie->timestamp = jiffies;
24931da177e4SLinus Torvalds 		}
24941da177e4SLinus Torvalds 	}
24951da177e4SLinus Torvalds 
24961da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
24971da177e4SLinus Torvalds }
24981da177e4SLinus Torvalds 
2499a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2500a8746417SMarcel Holtmann {
2501a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2502a8746417SMarcel Holtmann 	struct hci_conn *conn;
2503a8746417SMarcel Holtmann 
2504a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2505a8746417SMarcel Holtmann 
2506a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2507a8746417SMarcel Holtmann 
2508a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2509a8746417SMarcel Holtmann 	if (conn && !ev->status)
2510a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2511a8746417SMarcel Holtmann 
2512a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2513a8746417SMarcel Holtmann }
2514a8746417SMarcel Holtmann 
251585a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
251685a1e930SMarcel Holtmann {
2517a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
251885a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
251985a1e930SMarcel Holtmann 
252085a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
252185a1e930SMarcel Holtmann 
252285a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
252385a1e930SMarcel Holtmann 
2524cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2525cc11b9c1SAndrei Emeltchenko 	if (ie) {
252685a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
252785a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
252885a1e930SMarcel Holtmann 	}
252985a1e930SMarcel Holtmann 
253085a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
253185a1e930SMarcel Holtmann }
253285a1e930SMarcel Holtmann 
2533a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2534a9de9248SMarcel Holtmann {
2535a9de9248SMarcel Holtmann 	struct inquiry_data data;
2536a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2537a9de9248SMarcel Holtmann 
2538a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2539a9de9248SMarcel Holtmann 
2540a9de9248SMarcel Holtmann 	if (!num_rsp)
2541a9de9248SMarcel Holtmann 		return;
2542a9de9248SMarcel Holtmann 
2543a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2544a9de9248SMarcel Holtmann 
2545a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2546138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2547138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2548a9de9248SMarcel Holtmann 
2549e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2550a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2551a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2552a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2553a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2554a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2555a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2556a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
255741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2558a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
255948264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2560e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2561e17acd40SJohan Hedberg 						NULL);
2562a9de9248SMarcel Holtmann 		}
2563a9de9248SMarcel Holtmann 	} else {
2564a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *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		= 0x00;
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 	}
2581a9de9248SMarcel Holtmann 
2582a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2583a9de9248SMarcel Holtmann }
2584a9de9248SMarcel Holtmann 
2585a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2586a9de9248SMarcel Holtmann {
258741a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
258841a96212SMarcel Holtmann 	struct hci_conn *conn;
258941a96212SMarcel Holtmann 
2590a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
259141a96212SMarcel Holtmann 
259241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
259341a96212SMarcel Holtmann 
259441a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2595ccd556feSJohan Hedberg 	if (!conn)
2596ccd556feSJohan Hedberg 		goto unlock;
2597ccd556feSJohan Hedberg 
2598769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
259941a96212SMarcel Holtmann 		struct inquiry_entry *ie;
260041a96212SMarcel Holtmann 
2601cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2602cc11b9c1SAndrei Emeltchenko 		if (ie)
260341a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
260441a96212SMarcel Holtmann 
260541a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
260641a96212SMarcel Holtmann 	}
260741a96212SMarcel Holtmann 
2608ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2609ccd556feSJohan Hedberg 		goto unlock;
2610ccd556feSJohan Hedberg 
2611127178d2SJohan Hedberg 	if (!ev->status) {
2612127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2613127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2614127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2615127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2616127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2617127178d2SJohan Hedberg 	}
2618392599b9SJohan Hedberg 
2619127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2620769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2621769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2622769be974SMarcel Holtmann 		hci_conn_put(conn);
2623769be974SMarcel Holtmann 	}
2624769be974SMarcel Holtmann 
2625ccd556feSJohan Hedberg unlock:
262641a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2627a9de9248SMarcel Holtmann }
2628a9de9248SMarcel Holtmann 
2629a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2630a9de9248SMarcel Holtmann {
2631b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2632b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2633b6a0dc82SMarcel Holtmann 
2634b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2635b6a0dc82SMarcel Holtmann 
2636b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2637b6a0dc82SMarcel Holtmann 
2638b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
26399dc0a3afSMarcel Holtmann 	if (!conn) {
26409dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
26419dc0a3afSMarcel Holtmann 			goto unlock;
26429dc0a3afSMarcel Holtmann 
26439dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2644b6a0dc82SMarcel Holtmann 		if (!conn)
2645b6a0dc82SMarcel Holtmann 			goto unlock;
2646b6a0dc82SMarcel Holtmann 
26479dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
26489dc0a3afSMarcel Holtmann 	}
26499dc0a3afSMarcel Holtmann 
2650732547f9SMarcel Holtmann 	switch (ev->status) {
2651732547f9SMarcel Holtmann 	case 0x00:
2652732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2653732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2654732547f9SMarcel Holtmann 
26559eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2656732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2657732547f9SMarcel Holtmann 		break;
2658732547f9SMarcel Holtmann 
2659705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2660732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
26611038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2662732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2663732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2664efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2665efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2666efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2667efc7688bSMarcel Holtmann 			goto unlock;
2668efc7688bSMarcel Holtmann 		}
2669732547f9SMarcel Holtmann 		/* fall through */
2670efc7688bSMarcel Holtmann 
2671732547f9SMarcel Holtmann 	default:
2672b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2673732547f9SMarcel Holtmann 		break;
2674732547f9SMarcel Holtmann 	}
2675b6a0dc82SMarcel Holtmann 
2676b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2677b6a0dc82SMarcel Holtmann 	if (ev->status)
2678b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2679b6a0dc82SMarcel Holtmann 
2680b6a0dc82SMarcel Holtmann unlock:
2681b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2682a9de9248SMarcel Holtmann }
2683a9de9248SMarcel Holtmann 
2684a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2685a9de9248SMarcel Holtmann {
2686a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2687a9de9248SMarcel Holtmann }
2688a9de9248SMarcel Holtmann 
268904837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
269004837f64SMarcel Holtmann {
2691a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
269204837f64SMarcel Holtmann 
269304837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
269404837f64SMarcel Holtmann }
269504837f64SMarcel Holtmann 
2696a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2697a9de9248SMarcel Holtmann {
2698a9de9248SMarcel Holtmann 	struct inquiry_data data;
2699a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2700a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2701a9de9248SMarcel Holtmann 
2702a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2703a9de9248SMarcel Holtmann 
2704a9de9248SMarcel Holtmann 	if (!num_rsp)
2705a9de9248SMarcel Holtmann 		return;
2706a9de9248SMarcel Holtmann 
2707a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2708a9de9248SMarcel Holtmann 
2709e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2710a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2711a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2712a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2713a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2714a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2715a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2716a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
271741a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2718a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
271948264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
27204c659c39SJohan Hedberg 				info->dev_class, info->rssi, info->data);
2721a9de9248SMarcel Holtmann 	}
2722a9de9248SMarcel Holtmann 
2723a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2724a9de9248SMarcel Holtmann }
2725a9de9248SMarcel Holtmann 
272617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
272717fa4b9dSJohan Hedberg {
272817fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
272917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
273017fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
273117fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
273217fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
273317fa4b9dSJohan Hedberg 			return 0x02;
273417fa4b9dSJohan Hedberg 		else
273517fa4b9dSJohan Hedberg 			return 0x03;
273617fa4b9dSJohan Hedberg 	}
273717fa4b9dSJohan Hedberg 
273817fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
273917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
274058797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
274117fa4b9dSJohan Hedberg 
274217fa4b9dSJohan Hedberg 	return conn->auth_type;
274317fa4b9dSJohan Hedberg }
274417fa4b9dSJohan Hedberg 
27450493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
27460493684eSMarcel Holtmann {
27470493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
27480493684eSMarcel Holtmann 	struct hci_conn *conn;
27490493684eSMarcel Holtmann 
27500493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
27510493684eSMarcel Holtmann 
27520493684eSMarcel Holtmann 	hci_dev_lock(hdev);
27530493684eSMarcel Holtmann 
27540493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
275503b555e1SJohan Hedberg 	if (!conn)
275603b555e1SJohan Hedberg 		goto unlock;
275703b555e1SJohan Hedberg 
27580493684eSMarcel Holtmann 	hci_conn_hold(conn);
27590493684eSMarcel Holtmann 
276003b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
276103b555e1SJohan Hedberg 		goto unlock;
276203b555e1SJohan Hedberg 
276303b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
276403b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
276517fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
276617fa4b9dSJohan Hedberg 
276717fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
276817fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
27697cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
27707cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
277117fa4b9dSJohan Hedberg 
2772ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2773ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2774ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2775ce85ee13SSzymon Janc 		else
2776ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2777ce85ee13SSzymon Janc 
277817fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
277917fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
278003b555e1SJohan Hedberg 	} else {
278103b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
278203b555e1SJohan Hedberg 
278303b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
27849f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
278503b555e1SJohan Hedberg 
278603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
278703b555e1SJohan Hedberg 							sizeof(cp), &cp);
278803b555e1SJohan Hedberg 	}
278903b555e1SJohan Hedberg 
279003b555e1SJohan Hedberg unlock:
279103b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
279203b555e1SJohan Hedberg }
279303b555e1SJohan Hedberg 
279403b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
279503b555e1SJohan Hedberg {
279603b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
279703b555e1SJohan Hedberg 	struct hci_conn *conn;
279803b555e1SJohan Hedberg 
279903b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
280003b555e1SJohan Hedberg 
280103b555e1SJohan Hedberg 	hci_dev_lock(hdev);
280203b555e1SJohan Hedberg 
280303b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
280403b555e1SJohan Hedberg 	if (!conn)
280503b555e1SJohan Hedberg 		goto unlock;
280603b555e1SJohan Hedberg 
280703b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
280803b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
280903b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
281003b555e1SJohan Hedberg 
281103b555e1SJohan Hedberg unlock:
28120493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
28130493684eSMarcel Holtmann }
28140493684eSMarcel Holtmann 
2815a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2816a5c29683SJohan Hedberg 							struct sk_buff *skb)
2817a5c29683SJohan Hedberg {
2818a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
281955bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
28207a828908SJohan Hedberg 	struct hci_conn *conn;
2821a5c29683SJohan Hedberg 
2822a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
2823a5c29683SJohan Hedberg 
2824a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
2825a5c29683SJohan Hedberg 
28267a828908SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
28277a828908SJohan Hedberg 		goto unlock;
28287a828908SJohan Hedberg 
28297a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
28307a828908SJohan Hedberg 	if (!conn)
28317a828908SJohan Hedberg 		goto unlock;
28327a828908SJohan Hedberg 
28337a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
28347a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
28357a828908SJohan Hedberg 
28367a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
28377a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
28387a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
28397a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
28407a828908SJohan Hedberg 	 * bit set. */
28417a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
28427a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
28437a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
28447a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
28457a828908SJohan Hedberg 		goto unlock;
28467a828908SJohan Hedberg 	}
28477a828908SJohan Hedberg 
28487a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
28497a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
28507a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
285155bc1a37SJohan Hedberg 
285255bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
285355bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
285455bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
285555bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
285655bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
285755bc1a37SJohan Hedberg 			confirm_hint = 1;
285855bc1a37SJohan Hedberg 			goto confirm;
285955bc1a37SJohan Hedberg 		}
286055bc1a37SJohan Hedberg 
28619f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
28629f61656aSJohan Hedberg 						hdev->auto_accept_delay);
28639f61656aSJohan Hedberg 
28649f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
28659f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
28669f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
28679f61656aSJohan Hedberg 			goto unlock;
28689f61656aSJohan Hedberg 		}
28699f61656aSJohan Hedberg 
28707a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
28717a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
28727a828908SJohan Hedberg 		goto unlock;
28737a828908SJohan Hedberg 	}
28747a828908SJohan Hedberg 
287555bc1a37SJohan Hedberg confirm:
2876744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
287755bc1a37SJohan Hedberg 								confirm_hint);
2878a5c29683SJohan Hedberg 
28797a828908SJohan Hedberg unlock:
2880a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
2881a5c29683SJohan Hedberg }
2882a5c29683SJohan Hedberg 
28831143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
28841143d458SBrian Gix 							struct sk_buff *skb)
28851143d458SBrian Gix {
28861143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
28871143d458SBrian Gix 
28881143d458SBrian Gix 	BT_DBG("%s", hdev->name);
28891143d458SBrian Gix 
28901143d458SBrian Gix 	hci_dev_lock(hdev);
28911143d458SBrian Gix 
28921143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
28931143d458SBrian Gix 		mgmt_user_passkey_request(hdev, &ev->bdaddr);
28941143d458SBrian Gix 
28951143d458SBrian Gix 	hci_dev_unlock(hdev);
28961143d458SBrian Gix }
28971143d458SBrian Gix 
28980493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
28990493684eSMarcel Holtmann {
29000493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
29010493684eSMarcel Holtmann 	struct hci_conn *conn;
29020493684eSMarcel Holtmann 
29030493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
29040493684eSMarcel Holtmann 
29050493684eSMarcel Holtmann 	hci_dev_lock(hdev);
29060493684eSMarcel Holtmann 
29070493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
29082a611692SJohan Hedberg 	if (!conn)
29092a611692SJohan Hedberg 		goto unlock;
29102a611692SJohan Hedberg 
29112a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
29122a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
29132a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
29142a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
29152a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
29162a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
2917744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
29182a611692SJohan Hedberg 
29190493684eSMarcel Holtmann 	hci_conn_put(conn);
29200493684eSMarcel Holtmann 
29212a611692SJohan Hedberg unlock:
29220493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
29230493684eSMarcel Holtmann }
29240493684eSMarcel Holtmann 
292541a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
292641a96212SMarcel Holtmann {
292741a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
292841a96212SMarcel Holtmann 	struct inquiry_entry *ie;
292941a96212SMarcel Holtmann 
293041a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
293141a96212SMarcel Holtmann 
293241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
293341a96212SMarcel Holtmann 
2934cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2935cc11b9c1SAndrei Emeltchenko 	if (ie)
293641a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
293741a96212SMarcel Holtmann 
293841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
293941a96212SMarcel Holtmann }
294041a96212SMarcel Holtmann 
29412763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
29422763eda6SSzymon Janc 							struct sk_buff *skb)
29432763eda6SSzymon Janc {
29442763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
29452763eda6SSzymon Janc 	struct oob_data *data;
29462763eda6SSzymon Janc 
29472763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
29482763eda6SSzymon Janc 
29492763eda6SSzymon Janc 	hci_dev_lock(hdev);
29502763eda6SSzymon Janc 
2951e1ba1f15SSzymon Janc 	if (!test_bit(HCI_MGMT, &hdev->flags))
2952e1ba1f15SSzymon Janc 		goto unlock;
2953e1ba1f15SSzymon Janc 
29542763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
29552763eda6SSzymon Janc 	if (data) {
29562763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
29572763eda6SSzymon Janc 
29582763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
29592763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
29602763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
29612763eda6SSzymon Janc 
29622763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
29632763eda6SSzymon Janc 									&cp);
29642763eda6SSzymon Janc 	} else {
29652763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
29662763eda6SSzymon Janc 
29672763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
29682763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
29692763eda6SSzymon Janc 									&cp);
29702763eda6SSzymon Janc 	}
29712763eda6SSzymon Janc 
2972e1ba1f15SSzymon Janc unlock:
29732763eda6SSzymon Janc 	hci_dev_unlock(hdev);
29742763eda6SSzymon Janc }
29752763eda6SSzymon Janc 
2976fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2977fcd89c09SVille Tervo {
2978fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2979fcd89c09SVille Tervo 	struct hci_conn *conn;
2980fcd89c09SVille Tervo 
2981fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
2982fcd89c09SVille Tervo 
2983fcd89c09SVille Tervo 	hci_dev_lock(hdev);
2984fcd89c09SVille Tervo 
2985fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2986b62f328bSVille Tervo 	if (!conn) {
2987b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2988b62f328bSVille Tervo 		if (!conn) {
2989b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
2990b62f328bSVille Tervo 			hci_dev_unlock(hdev);
2991b62f328bSVille Tervo 			return;
2992b62f328bSVille Tervo 		}
299329b7988aSAndre Guedes 
299429b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
2995b62f328bSVille Tervo 	}
2996fcd89c09SVille Tervo 
2997fcd89c09SVille Tervo 	if (ev->status) {
299848264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
299948264f06SJohan Hedberg 						conn->dst_type, ev->status);
3000fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3001fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3002fcd89c09SVille Tervo 		hci_conn_del(conn);
3003fcd89c09SVille Tervo 		goto unlock;
3004fcd89c09SVille Tervo 	}
3005fcd89c09SVille Tervo 
300648264f06SJohan Hedberg 	mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
300783bc71b4SVinicius Costa Gomes 
30087b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3009fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3010fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3011fcd89c09SVille Tervo 
3012fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3013fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3014fcd89c09SVille Tervo 
3015fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3016fcd89c09SVille Tervo 
3017fcd89c09SVille Tervo unlock:
3018fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3019fcd89c09SVille Tervo }
3020fcd89c09SVille Tervo 
30219aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
30229aa04c91SAndre Guedes 						struct sk_buff *skb)
30239aa04c91SAndre Guedes {
3024e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3025e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
30269aa04c91SAndre Guedes 
30279aa04c91SAndre Guedes 	hci_dev_lock(hdev);
30289aa04c91SAndre Guedes 
3029e95beb41SAndre Guedes 	while (num_reports--) {
3030e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3031e95beb41SAndre Guedes 
30329aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
30339aa04c91SAndre Guedes 
3034e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
30359aa04c91SAndre Guedes 	}
30369aa04c91SAndre Guedes 
30379aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
30389aa04c91SAndre Guedes }
30399aa04c91SAndre Guedes 
3040a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3041a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3042a7a595f6SVinicius Costa Gomes {
3043a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3044a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3045bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3046a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3047bea710feSVinicius Costa Gomes 	struct link_key *ltk;
3048a7a595f6SVinicius Costa Gomes 
3049a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3050a7a595f6SVinicius Costa Gomes 
3051a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3052a7a595f6SVinicius Costa Gomes 
3053a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3054bea710feSVinicius Costa Gomes 	if (conn == NULL)
3055bea710feSVinicius Costa Gomes 		goto not_found;
3056a7a595f6SVinicius Costa Gomes 
3057bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3058bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3059bea710feSVinicius Costa Gomes 		goto not_found;
3060bea710feSVinicius Costa Gomes 
3061bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3062a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3063726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
3064a7a595f6SVinicius Costa Gomes 
3065a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3066a7a595f6SVinicius Costa Gomes 
3067a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3068bea710feSVinicius Costa Gomes 
3069bea710feSVinicius Costa Gomes 	return;
3070bea710feSVinicius Costa Gomes 
3071bea710feSVinicius Costa Gomes not_found:
3072bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3073bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3074bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3075a7a595f6SVinicius Costa Gomes }
3076a7a595f6SVinicius Costa Gomes 
3077fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3078fcd89c09SVille Tervo {
3079fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3080fcd89c09SVille Tervo 
3081fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3082fcd89c09SVille Tervo 
3083fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3084fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3085fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3086fcd89c09SVille Tervo 		break;
3087fcd89c09SVille Tervo 
30889aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
30899aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
30909aa04c91SAndre Guedes 		break;
30919aa04c91SAndre Guedes 
3092a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3093a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3094a7a595f6SVinicius Costa Gomes 		break;
3095a7a595f6SVinicius Costa Gomes 
3096fcd89c09SVille Tervo 	default:
3097fcd89c09SVille Tervo 		break;
3098fcd89c09SVille Tervo 	}
3099fcd89c09SVille Tervo }
3100fcd89c09SVille Tervo 
31011da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
31021da177e4SLinus Torvalds {
3103a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3104a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
31051da177e4SLinus Torvalds 
31061da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
31071da177e4SLinus Torvalds 
3108a9de9248SMarcel Holtmann 	switch (event) {
31091da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
31101da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
31111da177e4SLinus Torvalds 		break;
31121da177e4SLinus Torvalds 
31131da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
31141da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
31151da177e4SLinus Torvalds 		break;
31161da177e4SLinus Torvalds 
3117a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3118a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
311921d9e30eSMarcel Holtmann 		break;
312021d9e30eSMarcel Holtmann 
31211da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
31221da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
31231da177e4SLinus Torvalds 		break;
31241da177e4SLinus Torvalds 
31251da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
31261da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
31271da177e4SLinus Torvalds 		break;
31281da177e4SLinus Torvalds 
31291da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
31301da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
31311da177e4SLinus Torvalds 		break;
31321da177e4SLinus Torvalds 
3133a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3134a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3135a9de9248SMarcel Holtmann 		break;
3136a9de9248SMarcel Holtmann 
31371da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
31381da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
31391da177e4SLinus Torvalds 		break;
31401da177e4SLinus Torvalds 
3141a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3142a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3143a9de9248SMarcel Holtmann 		break;
3144a9de9248SMarcel Holtmann 
3145a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3146a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3147a9de9248SMarcel Holtmann 		break;
3148a9de9248SMarcel Holtmann 
3149a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3150a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3151a9de9248SMarcel Holtmann 		break;
3152a9de9248SMarcel Holtmann 
3153a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3154a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3155a9de9248SMarcel Holtmann 		break;
3156a9de9248SMarcel Holtmann 
3157a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3158a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3159a9de9248SMarcel Holtmann 		break;
3160a9de9248SMarcel Holtmann 
3161a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3162a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3163a9de9248SMarcel Holtmann 		break;
3164a9de9248SMarcel Holtmann 
3165a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3166a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3167a9de9248SMarcel Holtmann 		break;
3168a9de9248SMarcel Holtmann 
3169a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3170a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3171a9de9248SMarcel Holtmann 		break;
3172a9de9248SMarcel Holtmann 
3173a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3174a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
31751da177e4SLinus Torvalds 		break;
31761da177e4SLinus Torvalds 
31771da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
31781da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
31791da177e4SLinus Torvalds 		break;
31801da177e4SLinus Torvalds 
31811da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
31821da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
31831da177e4SLinus Torvalds 		break;
31841da177e4SLinus Torvalds 
31851da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
31861da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
31871da177e4SLinus Torvalds 		break;
31881da177e4SLinus Torvalds 
31891da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
31901da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
31911da177e4SLinus Torvalds 		break;
31921da177e4SLinus Torvalds 
3193a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3194a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3195a8746417SMarcel Holtmann 		break;
3196a8746417SMarcel Holtmann 
319785a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
319885a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
319985a1e930SMarcel Holtmann 		break;
320085a1e930SMarcel Holtmann 
3201a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3202a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3203a9de9248SMarcel Holtmann 		break;
3204a9de9248SMarcel Holtmann 
3205a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3206a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3207a9de9248SMarcel Holtmann 		break;
3208a9de9248SMarcel Holtmann 
3209a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3210a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3211a9de9248SMarcel Holtmann 		break;
3212a9de9248SMarcel Holtmann 
3213a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3214a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3215a9de9248SMarcel Holtmann 		break;
3216a9de9248SMarcel Holtmann 
321704837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
321804837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
321904837f64SMarcel Holtmann 		break;
322004837f64SMarcel Holtmann 
3221a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3222a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
32231da177e4SLinus Torvalds 		break;
32241da177e4SLinus Torvalds 
32250493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
32260493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
32270493684eSMarcel Holtmann 		break;
32280493684eSMarcel Holtmann 
322903b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
323003b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
323103b555e1SJohan Hedberg 		break;
323203b555e1SJohan Hedberg 
3233a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3234a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3235a5c29683SJohan Hedberg 		break;
3236a5c29683SJohan Hedberg 
32371143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
32381143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
32391143d458SBrian Gix 		break;
32401143d458SBrian Gix 
32410493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
32420493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
32430493684eSMarcel Holtmann 		break;
32440493684eSMarcel Holtmann 
324541a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
324641a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
324741a96212SMarcel Holtmann 		break;
324841a96212SMarcel Holtmann 
3249fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3250fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3251fcd89c09SVille Tervo 		break;
3252fcd89c09SVille Tervo 
32532763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
32542763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
32552763eda6SSzymon Janc 		break;
32562763eda6SSzymon Janc 
32571da177e4SLinus Torvalds 	default:
3258a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
32591da177e4SLinus Torvalds 		break;
32601da177e4SLinus Torvalds 	}
32611da177e4SLinus Torvalds 
32621da177e4SLinus Torvalds 	kfree_skb(skb);
32631da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
32641da177e4SLinus Torvalds }
32651da177e4SLinus Torvalds 
32661da177e4SLinus Torvalds /* Generate internal stack event */
32671da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
32681da177e4SLinus Torvalds {
32691da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
32701da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
32711da177e4SLinus Torvalds 	struct sk_buff *skb;
32721da177e4SLinus Torvalds 
32731da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
32741da177e4SLinus Torvalds 	if (!skb)
32751da177e4SLinus Torvalds 		return;
32761da177e4SLinus Torvalds 
32771da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
32781da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
32791da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
32801da177e4SLinus Torvalds 
32811da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
32821da177e4SLinus Torvalds 	ev->type = type;
32831da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
32841da177e4SLinus Torvalds 
3285576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3286a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3287576c7d85SMarcel Holtmann 
32880d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
32891da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3290eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
32911da177e4SLinus Torvalds 	kfree_skb(skb);
32921da177e4SLinus Torvalds }
3293e6100a25SAndre Guedes 
3294669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3295e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3296