xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 1e89cffb)
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);
197a9de9248SMarcel Holtmann }
198a9de9248SMarcel Holtmann 
199a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
200a9de9248SMarcel Holtmann {
201a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2021da177e4SLinus Torvalds 	void *sent;
2031da177e4SLinus Torvalds 
204a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2051da177e4SLinus Torvalds 
206a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2071da177e4SLinus Torvalds 	if (!sent)
208a9de9248SMarcel Holtmann 		return;
2091da177e4SLinus Torvalds 
21056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21156e5cb86SJohan Hedberg 
212b312b161SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
213744cf19eSJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
214b312b161SJohan Hedberg 
21556e5cb86SJohan Hedberg 	if (status == 0)
2161f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
21756e5cb86SJohan Hedberg 
21856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
219a9de9248SMarcel Holtmann }
220a9de9248SMarcel Holtmann 
221a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
222a9de9248SMarcel Holtmann {
223a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
224a9de9248SMarcel Holtmann 
225a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
226a9de9248SMarcel Holtmann 
227a9de9248SMarcel Holtmann 	if (rp->status)
228a9de9248SMarcel Holtmann 		return;
229a9de9248SMarcel Holtmann 
2301f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
231a9de9248SMarcel Holtmann }
232a9de9248SMarcel Holtmann 
233a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
234a9de9248SMarcel Holtmann {
235a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
236a9de9248SMarcel Holtmann 	void *sent;
237a9de9248SMarcel Holtmann 
238a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
239a9de9248SMarcel Holtmann 
240a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
241a9de9248SMarcel Holtmann 	if (!sent)
242a9de9248SMarcel Holtmann 		return;
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds 	if (!status) {
245a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
246a9de9248SMarcel Holtmann 
2471da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2481da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2491da177e4SLinus Torvalds 		else
2501da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2511da177e4SLinus Torvalds 	}
252a9de9248SMarcel Holtmann 
25323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
254a9de9248SMarcel Holtmann }
2551da177e4SLinus Torvalds 
256a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
257a9de9248SMarcel Holtmann {
258a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
259a9de9248SMarcel Holtmann 	void *sent;
260a9de9248SMarcel Holtmann 
261a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
262a9de9248SMarcel Holtmann 
263a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2641da177e4SLinus Torvalds 	if (!sent)
265a9de9248SMarcel Holtmann 		return;
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds 	if (!status) {
268a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
269a9de9248SMarcel Holtmann 
2701da177e4SLinus Torvalds 		if (param)
2711da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2721da177e4SLinus Torvalds 		else
2731da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2741da177e4SLinus Torvalds 	}
275a9de9248SMarcel Holtmann 
27623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2771da177e4SLinus Torvalds }
2781da177e4SLinus Torvalds 
279a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
280a9de9248SMarcel Holtmann {
28136f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28236f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
283a9de9248SMarcel Holtmann 	void *sent;
2841da177e4SLinus Torvalds 
285a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
286a9de9248SMarcel Holtmann 
287a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2881da177e4SLinus Torvalds 	if (!sent)
289a9de9248SMarcel Holtmann 		return;
2901da177e4SLinus Torvalds 
29136f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
292a9de9248SMarcel Holtmann 
29356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29456e5cb86SJohan Hedberg 
2952d7cee58SJohan Hedberg 	if (status != 0) {
296744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
2972d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
2982d7cee58SJohan Hedberg 		goto done;
2992d7cee58SJohan Hedberg 	}
3002d7cee58SJohan Hedberg 
3019fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3029fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
303a9de9248SMarcel Holtmann 
30473f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3051da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3069fbcbb45SJohan Hedberg 		if (!old_iscan)
307744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
30816ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
30916ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31016ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31116ab91abSJohan Hedberg 									to);
31216ab91abSJohan Hedberg 		}
3139fbcbb45SJohan Hedberg 	} else if (old_iscan)
314744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3151da177e4SLinus Torvalds 
3169fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3171da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3189fbcbb45SJohan Hedberg 		if (!old_pscan)
319744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3209fbcbb45SJohan Hedberg 	} else if (old_pscan)
321744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
322a9de9248SMarcel Holtmann 
32336f7fc7eSJohan Hedberg done:
32456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
32523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3261da177e4SLinus Torvalds }
3271da177e4SLinus Torvalds 
328a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
329a9de9248SMarcel Holtmann {
330a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
331a9de9248SMarcel Holtmann 
332a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
333a9de9248SMarcel Holtmann 
334a9de9248SMarcel Holtmann 	if (rp->status)
335a9de9248SMarcel Holtmann 		return;
336a9de9248SMarcel Holtmann 
337a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
338a9de9248SMarcel Holtmann 
339a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
340a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
341a9de9248SMarcel Holtmann }
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
344a9de9248SMarcel Holtmann {
345a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
346a9de9248SMarcel Holtmann 	void *sent;
347a9de9248SMarcel Holtmann 
348a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
349a9de9248SMarcel Holtmann 
350f383f275SMarcel Holtmann 	if (status)
351f383f275SMarcel Holtmann 		return;
352f383f275SMarcel Holtmann 
353a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
354a9de9248SMarcel Holtmann 	if (!sent)
355a9de9248SMarcel Holtmann 		return;
356a9de9248SMarcel Holtmann 
357a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
358a9de9248SMarcel Holtmann }
359a9de9248SMarcel Holtmann 
360a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
361a9de9248SMarcel Holtmann {
362a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
363a9de9248SMarcel Holtmann 	__u16 setting;
364a9de9248SMarcel Holtmann 
365a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
366a9de9248SMarcel Holtmann 
367a9de9248SMarcel Holtmann 	if (rp->status)
368a9de9248SMarcel Holtmann 		return;
369a9de9248SMarcel Holtmann 
370a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
371a9de9248SMarcel Holtmann 
372a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
373a9de9248SMarcel Holtmann 		return;
374a9de9248SMarcel Holtmann 
375a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
376a9de9248SMarcel Holtmann 
377a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
378a9de9248SMarcel Holtmann 
379a9de9248SMarcel Holtmann 	if (hdev->notify) {
380a9de9248SMarcel Holtmann 		tasklet_disable(&hdev->tx_task);
381a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
382a9de9248SMarcel Holtmann 		tasklet_enable(&hdev->tx_task);
383a9de9248SMarcel Holtmann 	}
384a9de9248SMarcel Holtmann }
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
387a9de9248SMarcel Holtmann {
388a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
389f383f275SMarcel Holtmann 	__u16 setting;
390a9de9248SMarcel Holtmann 	void *sent;
391a9de9248SMarcel Holtmann 
392a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
393a9de9248SMarcel Holtmann 
394f383f275SMarcel Holtmann 	if (status)
395f383f275SMarcel Holtmann 		return;
396f383f275SMarcel Holtmann 
397a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
398a9de9248SMarcel Holtmann 	if (!sent)
399a9de9248SMarcel Holtmann 		return;
400a9de9248SMarcel Holtmann 
401f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4021da177e4SLinus Torvalds 
403f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
404f383f275SMarcel Holtmann 		return;
405f383f275SMarcel Holtmann 
4061da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4071da177e4SLinus Torvalds 
408a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4091da177e4SLinus Torvalds 
4101da177e4SLinus Torvalds 	if (hdev->notify) {
4111da177e4SLinus Torvalds 		tasklet_disable(&hdev->tx_task);
4121da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4131da177e4SLinus Torvalds 		tasklet_enable(&hdev->tx_task);
4141da177e4SLinus Torvalds 	}
4151da177e4SLinus Torvalds }
4161da177e4SLinus Torvalds 
417a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4181da177e4SLinus Torvalds {
419a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4201da177e4SLinus Torvalds 
421a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4221da177e4SLinus Torvalds 
42323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4241143e5a6SMarcel Holtmann }
4251143e5a6SMarcel Holtmann 
426333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
427333140b5SMarcel Holtmann {
428333140b5SMarcel Holtmann 	struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
429333140b5SMarcel Holtmann 
430333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
431333140b5SMarcel Holtmann 
432333140b5SMarcel Holtmann 	if (rp->status)
433333140b5SMarcel Holtmann 		return;
434333140b5SMarcel Holtmann 
435333140b5SMarcel Holtmann 	hdev->ssp_mode = rp->mode;
436333140b5SMarcel Holtmann }
437333140b5SMarcel Holtmann 
438333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
439333140b5SMarcel Holtmann {
440333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
441333140b5SMarcel Holtmann 	void *sent;
442333140b5SMarcel Holtmann 
443333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
444333140b5SMarcel Holtmann 
445333140b5SMarcel Holtmann 	if (status)
446333140b5SMarcel Holtmann 		return;
447333140b5SMarcel Holtmann 
448333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
449333140b5SMarcel Holtmann 	if (!sent)
450333140b5SMarcel Holtmann 		return;
451333140b5SMarcel Holtmann 
452333140b5SMarcel Holtmann 	hdev->ssp_mode = *((__u8 *) sent);
453333140b5SMarcel Holtmann }
454333140b5SMarcel Holtmann 
455d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
456d5859e22SJohan Hedberg {
457d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
458d5859e22SJohan Hedberg 		return 2;
459d5859e22SJohan Hedberg 
460d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
461d5859e22SJohan Hedberg 		return 1;
462d5859e22SJohan Hedberg 
463d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
464d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
465d5859e22SJohan Hedberg 		return 1;
466d5859e22SJohan Hedberg 
467d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
468d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
469d5859e22SJohan Hedberg 			return 1;
470d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
471d5859e22SJohan Hedberg 			return 1;
472d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
473d5859e22SJohan Hedberg 			return 1;
474d5859e22SJohan Hedberg 	}
475d5859e22SJohan Hedberg 
476d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
477d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
478d5859e22SJohan Hedberg 		return 1;
479d5859e22SJohan Hedberg 
480d5859e22SJohan Hedberg 	return 0;
481d5859e22SJohan Hedberg }
482d5859e22SJohan Hedberg 
483d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
484d5859e22SJohan Hedberg {
485d5859e22SJohan Hedberg 	u8 mode;
486d5859e22SJohan Hedberg 
487d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
488d5859e22SJohan Hedberg 
489d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
490d5859e22SJohan Hedberg }
491d5859e22SJohan Hedberg 
492d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
493d5859e22SJohan Hedberg {
494d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
495d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
496d5859e22SJohan Hedberg 	 * command otherwise */
497d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
498d5859e22SJohan Hedberg 
4996de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5006de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5016de6c18dSVille Tervo 	if (hdev->lmp_ver <= 1)
5026de6c18dSVille Tervo 		return;
5036de6c18dSVille Tervo 
504d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
505d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
506d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
507d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
508d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
509d5859e22SJohan Hedberg 
510d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
511d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
512d5859e22SJohan Hedberg 
513d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
514d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
515d5859e22SJohan Hedberg 
516d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
517d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
518d5859e22SJohan Hedberg 
519d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
520d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
521d5859e22SJohan Hedberg 
522d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
523d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
524d5859e22SJohan Hedberg 
525d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
526d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
527d5859e22SJohan Hedberg 
528d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
529d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
530d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
531d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
532d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
533d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
534d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
535d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
536d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
537d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
538d5859e22SJohan Hedberg 					 * Features Notification */
539d5859e22SJohan Hedberg 	}
540d5859e22SJohan Hedberg 
541d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
542d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
543d5859e22SJohan Hedberg 
544d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
545d5859e22SJohan Hedberg }
546d5859e22SJohan Hedberg 
547e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
548e6100a25SAndre Guedes {
549e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
550e6100a25SAndre Guedes 
551e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
552e6100a25SAndre Guedes 
553e6100a25SAndre Guedes 	if (enable_le) {
554e6100a25SAndre Guedes 		cp.le = 1;
555e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
556e6100a25SAndre Guedes 	}
557e6100a25SAndre Guedes 
558e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
559e6100a25SAndre Guedes }
560e6100a25SAndre Guedes 
561d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
562d5859e22SJohan Hedberg {
563d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
564d5859e22SJohan Hedberg 
565d5859e22SJohan Hedberg 	if (hdev->lmp_ver > 1)
566d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
567d5859e22SJohan Hedberg 
568d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
569d5859e22SJohan Hedberg 		u8 mode = 0x01;
570d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
571d5859e22SJohan Hedberg 	}
572d5859e22SJohan Hedberg 
573d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
574d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
575d5859e22SJohan Hedberg 
576d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
577d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
578971e3a4bSAndre Guedes 
579971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
580971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
581971e3a4bSAndre Guedes 
582971e3a4bSAndre Guedes 		cp.page = 0x01;
583971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
584971e3a4bSAndre Guedes 							sizeof(cp), &cp);
585971e3a4bSAndre Guedes 	}
586e6100a25SAndre Guedes 
587e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
588e6100a25SAndre Guedes 		hci_set_le_support(hdev);
589d5859e22SJohan Hedberg }
590d5859e22SJohan Hedberg 
591a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
592a9de9248SMarcel Holtmann {
593a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5941143e5a6SMarcel Holtmann 
595a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5961143e5a6SMarcel Holtmann 
597a9de9248SMarcel Holtmann 	if (rp->status)
598a9de9248SMarcel Holtmann 		return;
5991143e5a6SMarcel Holtmann 
600a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
601e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
602d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
603e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
604d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6051da177e4SLinus Torvalds 
606a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
607a9de9248SMarcel Holtmann 					hdev->manufacturer,
608a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
609d5859e22SJohan Hedberg 
610d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
611d5859e22SJohan Hedberg 		hci_setup(hdev);
612d5859e22SJohan Hedberg }
613d5859e22SJohan Hedberg 
614d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
615d5859e22SJohan Hedberg {
616d5859e22SJohan Hedberg 	u16 link_policy = 0;
617d5859e22SJohan Hedberg 
618d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
619d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
620d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
621d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
622d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
623d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
624d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
625d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
626d5859e22SJohan Hedberg 
627d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
628d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
629d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6301da177e4SLinus Torvalds }
6311da177e4SLinus Torvalds 
632a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
633a9de9248SMarcel Holtmann {
634a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
635a9de9248SMarcel Holtmann 
636a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
637a9de9248SMarcel Holtmann 
638a9de9248SMarcel Holtmann 	if (rp->status)
639d5859e22SJohan Hedberg 		goto done;
640a9de9248SMarcel Holtmann 
641a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
642d5859e22SJohan Hedberg 
643d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
644d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
645d5859e22SJohan Hedberg 
646d5859e22SJohan Hedberg done:
647d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
648a9de9248SMarcel Holtmann }
649a9de9248SMarcel Holtmann 
650a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
651a9de9248SMarcel Holtmann {
652a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
653a9de9248SMarcel Holtmann 
654a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
655a9de9248SMarcel Holtmann 
656a9de9248SMarcel Holtmann 	if (rp->status)
657a9de9248SMarcel Holtmann 		return;
658a9de9248SMarcel Holtmann 
659a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6601da177e4SLinus Torvalds 
6611da177e4SLinus Torvalds 	/* Adjust default settings according to features
6621da177e4SLinus Torvalds 	 * supported by device. */
663a9de9248SMarcel Holtmann 
6641da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6651da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6661da177e4SLinus Torvalds 
6671da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6681da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6691da177e4SLinus Torvalds 
6705b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6711da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6725b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6735b7f9909SMarcel Holtmann 	}
6741da177e4SLinus Torvalds 
6755b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6761da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6775b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6785b7f9909SMarcel Holtmann 	}
6795b7f9909SMarcel Holtmann 
6805b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6815b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6825b7f9909SMarcel Holtmann 
6835b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6845b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6855b7f9909SMarcel Holtmann 
6865b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6875b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6881da177e4SLinus Torvalds 
689efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
690efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
691efc7688bSMarcel Holtmann 
692efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
693efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
694efc7688bSMarcel Holtmann 
695efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
696efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
697efc7688bSMarcel Holtmann 
698a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
699a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
700a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
701a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
702a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7031da177e4SLinus Torvalds }
7041da177e4SLinus Torvalds 
705971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
706971e3a4bSAndre Guedes 							struct sk_buff *skb)
707971e3a4bSAndre Guedes {
708971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
709971e3a4bSAndre Guedes 
710971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
711971e3a4bSAndre Guedes 
712971e3a4bSAndre Guedes 	if (rp->status)
713971e3a4bSAndre Guedes 		return;
714971e3a4bSAndre Guedes 
715971e3a4bSAndre Guedes 	memcpy(hdev->extfeatures, rp->features, 8);
716971e3a4bSAndre Guedes 
717971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
718971e3a4bSAndre Guedes }
719971e3a4bSAndre Guedes 
7201e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7211e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7221e89cffbSAndrei Emeltchenko {
7231e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7241e89cffbSAndrei Emeltchenko 
7251e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7261e89cffbSAndrei Emeltchenko 
7271e89cffbSAndrei Emeltchenko 	if (rp->status)
7281e89cffbSAndrei Emeltchenko 		return;
7291e89cffbSAndrei Emeltchenko 
7301e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7311e89cffbSAndrei Emeltchenko 
7321e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7331e89cffbSAndrei Emeltchenko }
7341e89cffbSAndrei Emeltchenko 
735a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
736a9de9248SMarcel Holtmann {
737a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
738a9de9248SMarcel Holtmann 
739a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
740a9de9248SMarcel Holtmann 
741a9de9248SMarcel Holtmann 	if (rp->status)
742a9de9248SMarcel Holtmann 		return;
743a9de9248SMarcel Holtmann 
744a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
745a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
746a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
747a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
748da1f5198SMarcel Holtmann 
749da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
750da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
751da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
752da1f5198SMarcel Holtmann 	}
753da1f5198SMarcel Holtmann 
754da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
755da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7561da177e4SLinus Torvalds 
757a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
758a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
759a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7601da177e4SLinus Torvalds }
7611da177e4SLinus Torvalds 
762a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
763a9de9248SMarcel Holtmann {
764a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7651da177e4SLinus Torvalds 
766a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
767a9de9248SMarcel Holtmann 
768a9de9248SMarcel Holtmann 	if (!rp->status)
769a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
770a9de9248SMarcel Holtmann 
77123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
77223bb5763SJohan Hedberg }
77323bb5763SJohan Hedberg 
77423bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
77523bb5763SJohan Hedberg {
77623bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
77723bb5763SJohan Hedberg 
77823bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
77923bb5763SJohan Hedberg 
78023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
7811da177e4SLinus Torvalds }
7821da177e4SLinus Torvalds 
783928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
784928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
785928abaa7SAndrei Emeltchenko {
786928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
787928abaa7SAndrei Emeltchenko 
788928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
789928abaa7SAndrei Emeltchenko 
790928abaa7SAndrei Emeltchenko 	if (rp->status)
791928abaa7SAndrei Emeltchenko 		return;
792928abaa7SAndrei Emeltchenko 
793928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
794928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
795928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
796928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
797928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
798928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
799928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
800928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
801928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
802928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
803928abaa7SAndrei Emeltchenko 
804928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
805928abaa7SAndrei Emeltchenko }
806928abaa7SAndrei Emeltchenko 
807b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
808b0916ea0SJohan Hedberg 							struct sk_buff *skb)
809b0916ea0SJohan Hedberg {
810b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
811b0916ea0SJohan Hedberg 
812b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
813b0916ea0SJohan Hedberg 
814b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
815b0916ea0SJohan Hedberg }
816b0916ea0SJohan Hedberg 
817d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
818d5859e22SJohan Hedberg {
819d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
820d5859e22SJohan Hedberg 
821d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
822d5859e22SJohan Hedberg 
823d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
824d5859e22SJohan Hedberg }
825d5859e22SJohan Hedberg 
826d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
827d5859e22SJohan Hedberg 							struct sk_buff *skb)
828d5859e22SJohan Hedberg {
829d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
830d5859e22SJohan Hedberg 
831d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
832d5859e22SJohan Hedberg 
833d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
834d5859e22SJohan Hedberg }
835d5859e22SJohan Hedberg 
836d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
837d5859e22SJohan Hedberg 							struct sk_buff *skb)
838d5859e22SJohan Hedberg {
839d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
840d5859e22SJohan Hedberg 
841d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
842d5859e22SJohan Hedberg 
843d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
844d5859e22SJohan Hedberg }
845d5859e22SJohan Hedberg 
846d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
847d5859e22SJohan Hedberg {
848d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
849d5859e22SJohan Hedberg 
850d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
851d5859e22SJohan Hedberg 
852d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
853d5859e22SJohan Hedberg }
854d5859e22SJohan Hedberg 
855980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
856980e1a53SJohan Hedberg {
857980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
858980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
859980e1a53SJohan Hedberg 	struct hci_conn *conn;
860980e1a53SJohan Hedberg 
861980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
862980e1a53SJohan Hedberg 
86356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
86456e5cb86SJohan Hedberg 
865980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
866744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
867980e1a53SJohan Hedberg 
868980e1a53SJohan Hedberg 	if (rp->status != 0)
86956e5cb86SJohan Hedberg 		goto unlock;
870980e1a53SJohan Hedberg 
871980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
872980e1a53SJohan Hedberg 	if (!cp)
87356e5cb86SJohan Hedberg 		goto unlock;
874980e1a53SJohan Hedberg 
875980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
876980e1a53SJohan Hedberg 	if (conn)
877980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
87856e5cb86SJohan Hedberg 
87956e5cb86SJohan Hedberg unlock:
88056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
881980e1a53SJohan Hedberg }
882980e1a53SJohan Hedberg 
883980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
884980e1a53SJohan Hedberg {
885980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
886980e1a53SJohan Hedberg 
887980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
888980e1a53SJohan Hedberg 
88956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
89056e5cb86SJohan Hedberg 
891980e1a53SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
892744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
893980e1a53SJohan Hedberg 								rp->status);
89456e5cb86SJohan Hedberg 
89556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
896980e1a53SJohan Hedberg }
89756e5cb86SJohan Hedberg 
8986ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8996ed58ec5SVille Tervo 				       struct sk_buff *skb)
9006ed58ec5SVille Tervo {
9016ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9026ed58ec5SVille Tervo 
9036ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9046ed58ec5SVille Tervo 
9056ed58ec5SVille Tervo 	if (rp->status)
9066ed58ec5SVille Tervo 		return;
9076ed58ec5SVille Tervo 
9086ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9096ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9106ed58ec5SVille Tervo 
9116ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9126ed58ec5SVille Tervo 
9136ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9146ed58ec5SVille Tervo 
9156ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9166ed58ec5SVille Tervo }
917980e1a53SJohan Hedberg 
918a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
919a5c29683SJohan Hedberg {
920a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
921a5c29683SJohan Hedberg 
922a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
923a5c29683SJohan Hedberg 
92456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92556e5cb86SJohan Hedberg 
926a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
927744cf19eSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
928a5c29683SJohan Hedberg 								rp->status);
92956e5cb86SJohan Hedberg 
93056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
931a5c29683SJohan Hedberg }
932a5c29683SJohan Hedberg 
933a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
934a5c29683SJohan Hedberg 							struct sk_buff *skb)
935a5c29683SJohan Hedberg {
936a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
937a5c29683SJohan Hedberg 
938a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
939a5c29683SJohan Hedberg 
94056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
94156e5cb86SJohan Hedberg 
942a5c29683SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->flags))
943744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
944a5c29683SJohan Hedberg 								rp->status);
94556e5cb86SJohan Hedberg 
94656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
947a5c29683SJohan Hedberg }
948a5c29683SJohan Hedberg 
9491143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9501143d458SBrian Gix {
9511143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9521143d458SBrian Gix 
9531143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9541143d458SBrian Gix 
9551143d458SBrian Gix 	hci_dev_lock(hdev);
9561143d458SBrian Gix 
9571143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
9581143d458SBrian Gix 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
9591143d458SBrian Gix 								rp->status);
9601143d458SBrian Gix 
9611143d458SBrian Gix 	hci_dev_unlock(hdev);
9621143d458SBrian Gix }
9631143d458SBrian Gix 
9641143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9651143d458SBrian Gix 							struct sk_buff *skb)
9661143d458SBrian Gix {
9671143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9681143d458SBrian Gix 
9691143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9701143d458SBrian Gix 
9711143d458SBrian Gix 	hci_dev_lock(hdev);
9721143d458SBrian Gix 
9731143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
9741143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
9751143d458SBrian Gix 								rp->status);
9761143d458SBrian Gix 
9771143d458SBrian Gix 	hci_dev_unlock(hdev);
9781143d458SBrian Gix }
9791143d458SBrian Gix 
980c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
981c35938b2SSzymon Janc 							struct sk_buff *skb)
982c35938b2SSzymon Janc {
983c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
984c35938b2SSzymon Janc 
985c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
986c35938b2SSzymon Janc 
98756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
988744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
989c35938b2SSzymon Janc 						rp->randomizer, rp->status);
99056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
991c35938b2SSzymon Janc }
992c35938b2SSzymon Janc 
993eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
994eb9d91f5SAndre Guedes 					struct sk_buff *skb)
995eb9d91f5SAndre Guedes {
996eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
997eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
998eb9d91f5SAndre Guedes 
999eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1000eb9d91f5SAndre Guedes 
1001eb9d91f5SAndre Guedes 	if (status)
1002eb9d91f5SAndre Guedes 		return;
1003eb9d91f5SAndre Guedes 
1004eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1005eb9d91f5SAndre Guedes 	if (!cp)
1006eb9d91f5SAndre Guedes 		return;
1007eb9d91f5SAndre Guedes 
100835815085SAndre Guedes 	if (cp->enable == 0x01) {
100935815085SAndre Guedes 		del_timer(&hdev->adv_timer);
1010a8f13c8cSAndre Guedes 
1011a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1012eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1013a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
101435815085SAndre Guedes 	} else if (cp->enable == 0x00) {
101535815085SAndre Guedes 		mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
101635815085SAndre Guedes 	}
1017eb9d91f5SAndre Guedes }
1018eb9d91f5SAndre Guedes 
1019a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1020a7a595f6SVinicius Costa Gomes {
1021a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1022a7a595f6SVinicius Costa Gomes 
1023a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1024a7a595f6SVinicius Costa Gomes 
1025a7a595f6SVinicius Costa Gomes 	if (rp->status)
1026a7a595f6SVinicius Costa Gomes 		return;
1027a7a595f6SVinicius Costa Gomes 
1028a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1029a7a595f6SVinicius Costa Gomes }
1030a7a595f6SVinicius Costa Gomes 
1031a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1032a7a595f6SVinicius Costa Gomes {
1033a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1034a7a595f6SVinicius Costa Gomes 
1035a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1036a7a595f6SVinicius Costa Gomes 
1037a7a595f6SVinicius Costa Gomes 	if (rp->status)
1038a7a595f6SVinicius Costa Gomes 		return;
1039a7a595f6SVinicius Costa Gomes 
1040a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1041a7a595f6SVinicius Costa Gomes }
1042a7a595f6SVinicius Costa Gomes 
1043f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1044f9b49306SAndre Guedes 							struct sk_buff *skb)
1045f9b49306SAndre Guedes {
1046f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1047f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1048f9b49306SAndre Guedes 
1049f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1050f9b49306SAndre Guedes 
1051f9b49306SAndre Guedes 	if (status)
1052f9b49306SAndre Guedes 		return;
1053f9b49306SAndre Guedes 
1054f9b49306SAndre Guedes 	cp.page = 0x01;
1055f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1056f9b49306SAndre Guedes }
1057f9b49306SAndre Guedes 
1058a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1059a9de9248SMarcel Holtmann {
1060a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1061a9de9248SMarcel Holtmann 
1062a9de9248SMarcel Holtmann 	if (status) {
106323bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1064a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
106556e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1066164a6e78SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->flags))
10677a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
106856e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1069314b2381SJohan Hedberg 		return;
1070314b2381SJohan Hedberg 	}
1071314b2381SJohan Hedberg 
107289352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
107389352e7dSAndre Guedes 
107456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1075744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 1);
107656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1077a9de9248SMarcel Holtmann }
1078a9de9248SMarcel Holtmann 
10791da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
10801da177e4SLinus Torvalds {
1081a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
10821da177e4SLinus Torvalds 	struct hci_conn *conn;
10831da177e4SLinus Torvalds 
1084a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1085a9de9248SMarcel Holtmann 
1086a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
10871da177e4SLinus Torvalds 	if (!cp)
10881da177e4SLinus Torvalds 		return;
10891da177e4SLinus Torvalds 
10901da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10911da177e4SLinus Torvalds 
10921da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
10931da177e4SLinus Torvalds 
1094a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
10951da177e4SLinus Torvalds 
10961da177e4SLinus Torvalds 	if (status) {
10971da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
10984c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
10991da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11001da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11011da177e4SLinus Torvalds 				hci_conn_del(conn);
11024c67bc74SMarcel Holtmann 			} else
11034c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11041da177e4SLinus Torvalds 		}
11051da177e4SLinus Torvalds 	} else {
11061da177e4SLinus Torvalds 		if (!conn) {
11071da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11081da177e4SLinus Torvalds 			if (conn) {
11091da177e4SLinus Torvalds 				conn->out = 1;
11101da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11111da177e4SLinus Torvalds 			} else
1112893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11131da177e4SLinus Torvalds 		}
11141da177e4SLinus Torvalds 	}
11151da177e4SLinus Torvalds 
11161da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11171da177e4SLinus Torvalds }
11181da177e4SLinus Torvalds 
1119a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11201da177e4SLinus Torvalds {
1121a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11221da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11231da177e4SLinus Torvalds 	__u16 handle;
11241da177e4SLinus Torvalds 
1125b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1126b6a0dc82SMarcel Holtmann 
1127a9de9248SMarcel Holtmann 	if (!status)
1128a9de9248SMarcel Holtmann 		return;
1129a9de9248SMarcel Holtmann 
1130a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11311da177e4SLinus Torvalds 	if (!cp)
1132a9de9248SMarcel Holtmann 		return;
11331da177e4SLinus Torvalds 
11341da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11351da177e4SLinus Torvalds 
1136a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
11371da177e4SLinus Torvalds 
11381da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11391da177e4SLinus Torvalds 
11401da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11415a08ecceSAndrei Emeltchenko 	if (acl) {
11425a08ecceSAndrei Emeltchenko 		sco = acl->link;
11435a08ecceSAndrei Emeltchenko 		if (sco) {
11441da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11451da177e4SLinus Torvalds 
11461da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11471da177e4SLinus Torvalds 			hci_conn_del(sco);
11481da177e4SLinus Torvalds 		}
11495a08ecceSAndrei Emeltchenko 	}
11501da177e4SLinus Torvalds 
11511da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11521da177e4SLinus Torvalds }
11531da177e4SLinus Torvalds 
1154f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1155f8558555SMarcel Holtmann {
1156f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1157f8558555SMarcel Holtmann 	struct hci_conn *conn;
1158f8558555SMarcel Holtmann 
1159f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1160f8558555SMarcel Holtmann 
1161f8558555SMarcel Holtmann 	if (!status)
1162f8558555SMarcel Holtmann 		return;
1163f8558555SMarcel Holtmann 
1164f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1165f8558555SMarcel Holtmann 	if (!cp)
1166f8558555SMarcel Holtmann 		return;
1167f8558555SMarcel Holtmann 
1168f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1169f8558555SMarcel Holtmann 
1170f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1171f8558555SMarcel Holtmann 	if (conn) {
1172f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1173f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1174f8558555SMarcel Holtmann 			hci_conn_put(conn);
1175f8558555SMarcel Holtmann 		}
1176f8558555SMarcel Holtmann 	}
1177f8558555SMarcel Holtmann 
1178f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1179f8558555SMarcel Holtmann }
1180f8558555SMarcel Holtmann 
1181f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1182f8558555SMarcel Holtmann {
1183f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1184f8558555SMarcel Holtmann 	struct hci_conn *conn;
1185f8558555SMarcel Holtmann 
1186f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1187f8558555SMarcel Holtmann 
1188f8558555SMarcel Holtmann 	if (!status)
1189f8558555SMarcel Holtmann 		return;
1190f8558555SMarcel Holtmann 
1191f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1192f8558555SMarcel Holtmann 	if (!cp)
1193f8558555SMarcel Holtmann 		return;
1194f8558555SMarcel Holtmann 
1195f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1196f8558555SMarcel Holtmann 
1197f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1198f8558555SMarcel Holtmann 	if (conn) {
1199f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1200f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1201f8558555SMarcel Holtmann 			hci_conn_put(conn);
1202f8558555SMarcel Holtmann 		}
1203f8558555SMarcel Holtmann 	}
1204f8558555SMarcel Holtmann 
1205f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1206f8558555SMarcel Holtmann }
1207f8558555SMarcel Holtmann 
1208127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1209392599b9SJohan Hedberg 							struct hci_conn *conn)
1210392599b9SJohan Hedberg {
1211392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1212392599b9SJohan Hedberg 		return 0;
1213392599b9SJohan Hedberg 
1214765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1215392599b9SJohan Hedberg 		return 0;
1216392599b9SJohan Hedberg 
1217392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1218e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1219392599b9SJohan Hedberg 	if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
1220e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1221e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1222392599b9SJohan Hedberg 		return 0;
1223392599b9SJohan Hedberg 
1224392599b9SJohan Hedberg 	return 1;
1225392599b9SJohan Hedberg }
1226392599b9SJohan Hedberg 
1227a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
12281da177e4SLinus Torvalds {
1229127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1230127178d2SJohan Hedberg 	struct hci_conn *conn;
1231127178d2SJohan Hedberg 
1232a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1233127178d2SJohan Hedberg 
1234127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1235127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1236127178d2SJohan Hedberg 	if (!status)
1237127178d2SJohan Hedberg 		return;
1238127178d2SJohan Hedberg 
1239127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1240127178d2SJohan Hedberg 	if (!cp)
1241127178d2SJohan Hedberg 		return;
1242127178d2SJohan Hedberg 
1243127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1244127178d2SJohan Hedberg 
1245127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
124679c6c70cSJohan Hedberg 	if (!conn)
124779c6c70cSJohan Hedberg 		goto unlock;
124879c6c70cSJohan Hedberg 
124979c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
125079c6c70cSJohan Hedberg 		goto unlock;
125179c6c70cSJohan Hedberg 
125279c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1253127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1254127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1255127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1256127178d2SJohan Hedberg 	}
1257127178d2SJohan Hedberg 
125879c6c70cSJohan Hedberg unlock:
1259127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1260a9de9248SMarcel Holtmann }
12611da177e4SLinus Torvalds 
1262769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1263769be974SMarcel Holtmann {
1264769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1265769be974SMarcel Holtmann 	struct hci_conn *conn;
1266769be974SMarcel Holtmann 
1267769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1268769be974SMarcel Holtmann 
1269769be974SMarcel Holtmann 	if (!status)
1270769be974SMarcel Holtmann 		return;
1271769be974SMarcel Holtmann 
1272769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1273769be974SMarcel Holtmann 	if (!cp)
1274769be974SMarcel Holtmann 		return;
1275769be974SMarcel Holtmann 
1276769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1277769be974SMarcel Holtmann 
1278769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1279769be974SMarcel Holtmann 	if (conn) {
1280769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1281769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1282769be974SMarcel Holtmann 			hci_conn_put(conn);
1283769be974SMarcel Holtmann 		}
1284769be974SMarcel Holtmann 	}
1285769be974SMarcel Holtmann 
1286769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1287769be974SMarcel Holtmann }
1288769be974SMarcel Holtmann 
1289769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1290769be974SMarcel Holtmann {
1291769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1292769be974SMarcel Holtmann 	struct hci_conn *conn;
1293769be974SMarcel Holtmann 
1294769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1295769be974SMarcel Holtmann 
1296769be974SMarcel Holtmann 	if (!status)
1297769be974SMarcel Holtmann 		return;
1298769be974SMarcel Holtmann 
1299769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1300769be974SMarcel Holtmann 	if (!cp)
1301769be974SMarcel Holtmann 		return;
1302769be974SMarcel Holtmann 
1303769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1304769be974SMarcel Holtmann 
1305769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1306769be974SMarcel Holtmann 	if (conn) {
1307769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1308769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1309769be974SMarcel Holtmann 			hci_conn_put(conn);
1310769be974SMarcel Holtmann 		}
1311769be974SMarcel Holtmann 	}
1312769be974SMarcel Holtmann 
1313769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1314769be974SMarcel Holtmann }
1315769be974SMarcel Holtmann 
1316a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1317a9de9248SMarcel Holtmann {
1318b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1319b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1320b6a0dc82SMarcel Holtmann 	__u16 handle;
1321b6a0dc82SMarcel Holtmann 
1322a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1323b6a0dc82SMarcel Holtmann 
1324b6a0dc82SMarcel Holtmann 	if (!status)
1325b6a0dc82SMarcel Holtmann 		return;
1326b6a0dc82SMarcel Holtmann 
1327b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1328b6a0dc82SMarcel Holtmann 	if (!cp)
1329b6a0dc82SMarcel Holtmann 		return;
1330b6a0dc82SMarcel Holtmann 
1331b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1332b6a0dc82SMarcel Holtmann 
1333b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1334b6a0dc82SMarcel Holtmann 
1335b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1336b6a0dc82SMarcel Holtmann 
1337b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
13385a08ecceSAndrei Emeltchenko 	if (acl) {
13395a08ecceSAndrei Emeltchenko 		sco = acl->link;
13405a08ecceSAndrei Emeltchenko 		if (sco) {
1341b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1342b6a0dc82SMarcel Holtmann 
1343b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1344b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1345b6a0dc82SMarcel Holtmann 		}
13465a08ecceSAndrei Emeltchenko 	}
1347b6a0dc82SMarcel Holtmann 
1348b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1349a9de9248SMarcel Holtmann }
1350a9de9248SMarcel Holtmann 
1351a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1352a9de9248SMarcel Holtmann {
1353a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
135404837f64SMarcel Holtmann 	struct hci_conn *conn;
135504837f64SMarcel Holtmann 
1356a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1357a9de9248SMarcel Holtmann 
1358a9de9248SMarcel Holtmann 	if (!status)
1359a9de9248SMarcel Holtmann 		return;
1360a9de9248SMarcel Holtmann 
1361a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
136204837f64SMarcel Holtmann 	if (!cp)
1363a9de9248SMarcel Holtmann 		return;
136404837f64SMarcel Holtmann 
136504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
136604837f64SMarcel Holtmann 
136704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1368e73439d8SMarcel Holtmann 	if (conn) {
136904837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
137004837f64SMarcel Holtmann 
1371e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1372e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1373e73439d8SMarcel Holtmann 	}
1374e73439d8SMarcel Holtmann 
137504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
137604837f64SMarcel Holtmann }
137704837f64SMarcel Holtmann 
1378a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1379a9de9248SMarcel Holtmann {
1380a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
138104837f64SMarcel Holtmann 	struct hci_conn *conn;
138204837f64SMarcel Holtmann 
1383a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1384a9de9248SMarcel Holtmann 
1385a9de9248SMarcel Holtmann 	if (!status)
1386a9de9248SMarcel Holtmann 		return;
1387a9de9248SMarcel Holtmann 
1388a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
138904837f64SMarcel Holtmann 	if (!cp)
1390a9de9248SMarcel Holtmann 		return;
139104837f64SMarcel Holtmann 
139204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
139304837f64SMarcel Holtmann 
139404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1395e73439d8SMarcel Holtmann 	if (conn) {
139604837f64SMarcel Holtmann 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
139704837f64SMarcel Holtmann 
1398e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1399e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1400e73439d8SMarcel Holtmann 	}
1401e73439d8SMarcel Holtmann 
140204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
140304837f64SMarcel Holtmann }
140404837f64SMarcel Holtmann 
1405fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1406fcd89c09SVille Tervo {
1407fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1408fcd89c09SVille Tervo 	struct hci_conn *conn;
1409fcd89c09SVille Tervo 
1410fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1411fcd89c09SVille Tervo 
1412fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1413fcd89c09SVille Tervo 	if (!cp)
1414fcd89c09SVille Tervo 		return;
1415fcd89c09SVille Tervo 
1416fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1417fcd89c09SVille Tervo 
1418fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1419fcd89c09SVille Tervo 
1420fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1421fcd89c09SVille Tervo 		conn);
1422fcd89c09SVille Tervo 
1423fcd89c09SVille Tervo 	if (status) {
1424fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1425fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1426fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1427fcd89c09SVille Tervo 			hci_conn_del(conn);
1428fcd89c09SVille Tervo 		}
1429fcd89c09SVille Tervo 	} else {
1430fcd89c09SVille Tervo 		if (!conn) {
1431fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
143229b7988aSAndre Guedes 			if (conn) {
143329b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1434fcd89c09SVille Tervo 				conn->out = 1;
143529b7988aSAndre Guedes 			} else {
1436fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1437fcd89c09SVille Tervo 			}
1438fcd89c09SVille Tervo 		}
143929b7988aSAndre Guedes 	}
1440fcd89c09SVille Tervo 
1441fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1442fcd89c09SVille Tervo }
1443fcd89c09SVille Tervo 
1444a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1445a7a595f6SVinicius Costa Gomes {
1446a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1447a7a595f6SVinicius Costa Gomes }
1448a7a595f6SVinicius Costa Gomes 
14491da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14501da177e4SLinus Torvalds {
14511da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
14521da177e4SLinus Torvalds 
14531da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
14541da177e4SLinus Torvalds 
145523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
14566bd57416SMarcel Holtmann 
1457a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
145889352e7dSAndre Guedes 
145989352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
146089352e7dSAndre Guedes 		return;
146189352e7dSAndre Guedes 
146256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1463744cf19eSJohan Hedberg 	mgmt_discovering(hdev, 0);
146456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
14651da177e4SLinus Torvalds }
14661da177e4SLinus Torvalds 
14671da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
14681da177e4SLinus Torvalds {
146945bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1470a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
14711da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
14721da177e4SLinus Torvalds 
14731da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
14741da177e4SLinus Torvalds 
147545bb4bf0SMarcel Holtmann 	if (!num_rsp)
147645bb4bf0SMarcel Holtmann 		return;
147745bb4bf0SMarcel Holtmann 
14781da177e4SLinus Torvalds 	hci_dev_lock(hdev);
147945bb4bf0SMarcel Holtmann 
1480e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
14811da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
14821da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
14831da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
14841da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
14851da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
14861da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
14871da177e4SLinus Torvalds 		data.rssi		= 0x00;
148841a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
14891da177e4SLinus Torvalds 		hci_inquiry_cache_update(hdev, &data);
149048264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
14914c659c39SJohan Hedberg 						info->dev_class, 0, NULL);
14921da177e4SLinus Torvalds 	}
149345bb4bf0SMarcel Holtmann 
14941da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14951da177e4SLinus Torvalds }
14961da177e4SLinus Torvalds 
1497a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
14981da177e4SLinus Torvalds {
1499a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1500a9de9248SMarcel Holtmann 	struct hci_conn *conn;
15011da177e4SLinus Torvalds 
1502a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
150345bb4bf0SMarcel Holtmann 
15041da177e4SLinus Torvalds 	hci_dev_lock(hdev);
150545bb4bf0SMarcel Holtmann 
1506a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
15079499237aSMarcel Holtmann 	if (!conn) {
15089499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
15099499237aSMarcel Holtmann 			goto unlock;
15109499237aSMarcel Holtmann 
15119499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1512a9de9248SMarcel Holtmann 		if (!conn)
1513a9de9248SMarcel Holtmann 			goto unlock;
151445bb4bf0SMarcel Holtmann 
15159499237aSMarcel Holtmann 		conn->type = SCO_LINK;
15169499237aSMarcel Holtmann 	}
15179499237aSMarcel Holtmann 
1518a9de9248SMarcel Holtmann 	if (!ev->status) {
1519a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1520769be974SMarcel Holtmann 
1521769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1522769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1523769be974SMarcel Holtmann 			hci_conn_hold(conn);
1524052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
152548264f06SJohan Hedberg 			mgmt_connected(hdev, &ev->bdaddr, conn->type,
152648264f06SJohan Hedberg 							conn->dst_type);
1527769be974SMarcel Holtmann 		} else
1528a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1529a9de9248SMarcel Holtmann 
15309eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
15317d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
15327d0db0a3SMarcel Holtmann 
1533a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1534a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1535a9de9248SMarcel Holtmann 
1536a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1537a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1538a9de9248SMarcel Holtmann 
1539a9de9248SMarcel Holtmann 		/* Get remote features */
1540a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1541a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1542a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1543769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1544769be974SMarcel Holtmann 							sizeof(cp), &cp);
154545bb4bf0SMarcel Holtmann 		}
1546a9de9248SMarcel Holtmann 
1547a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1548a8746417SMarcel Holtmann 		if (!conn->out && hdev->hci_ver < 3) {
1549a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1550a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1551a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1552a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1553a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1554a9de9248SMarcel Holtmann 		}
155517d5c04cSJohan Hedberg 	} else {
1556a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
155717d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1558744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
155948264f06SJohan Hedberg 						conn->dst_type, ev->status);
156017d5c04cSJohan Hedberg 	}
156145bb4bf0SMarcel Holtmann 
1562e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1563e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
156445bb4bf0SMarcel Holtmann 
1565769be974SMarcel Holtmann 	if (ev->status) {
1566a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1567a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1568c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1569c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1570a9de9248SMarcel Holtmann 
1571a9de9248SMarcel Holtmann unlock:
15721da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1573a9de9248SMarcel Holtmann 
1574a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
15751da177e4SLinus Torvalds }
15761da177e4SLinus Torvalds 
15771da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
15781da177e4SLinus Torvalds {
1579a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
15801da177e4SLinus Torvalds 	int mask = hdev->link_mode;
15811da177e4SLinus Torvalds 
1582a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
15831da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
15841da177e4SLinus Torvalds 
15851da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
15861da177e4SLinus Torvalds 
1587138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1588138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
15891da177e4SLinus Torvalds 		/* Connection accepted */
1590c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
15911da177e4SLinus Torvalds 		struct hci_conn *conn;
15921da177e4SLinus Torvalds 
15931da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1594b6a0dc82SMarcel Holtmann 
1595cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1596cc11b9c1SAndrei Emeltchenko 		if (ie)
1597c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1598c7bdd502SMarcel Holtmann 
15991da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16001da177e4SLinus Torvalds 		if (!conn) {
1601cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1602cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1603893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
16041da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
16051da177e4SLinus Torvalds 				return;
16061da177e4SLinus Torvalds 			}
16071da177e4SLinus Torvalds 		}
1608b6a0dc82SMarcel Holtmann 
16091da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
16101da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1611b6a0dc82SMarcel Holtmann 
16121da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
16131da177e4SLinus Torvalds 
1614b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1615b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1616b6a0dc82SMarcel Holtmann 
16171da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
16181da177e4SLinus Torvalds 
16191da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
16201da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
16211da177e4SLinus Torvalds 			else
16221da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
16231da177e4SLinus Torvalds 
1624b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1625b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1626b6a0dc82SMarcel Holtmann 		} else {
1627b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1628b6a0dc82SMarcel Holtmann 
1629b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1630a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1631b6a0dc82SMarcel Holtmann 
1632b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1633b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1634b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1635b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1636b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1637b6a0dc82SMarcel Holtmann 
1638b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1639b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1640b6a0dc82SMarcel Holtmann 		}
16411da177e4SLinus Torvalds 	} else {
16421da177e4SLinus Torvalds 		/* Connection rejected */
16431da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
16441da177e4SLinus Torvalds 
16451da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
16469f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1647a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
16481da177e4SLinus Torvalds 	}
16491da177e4SLinus Torvalds }
16501da177e4SLinus Torvalds 
16511da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16521da177e4SLinus Torvalds {
1653a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
165404837f64SMarcel Holtmann 	struct hci_conn *conn;
16551da177e4SLinus Torvalds 
16561da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
16571da177e4SLinus Torvalds 
16581da177e4SLinus Torvalds 	hci_dev_lock(hdev);
16591da177e4SLinus Torvalds 
166004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1661f7520543SJohan Hedberg 	if (!conn)
1662f7520543SJohan Hedberg 		goto unlock;
1663f7520543SJohan Hedberg 
166437d9ef76SJohan Hedberg 	if (ev->status == 0)
16651da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
16667d0db0a3SMarcel Holtmann 
166737d9ef76SJohan Hedberg 	if (conn->type == ACL_LINK || conn->type == LE_LINK) {
166837d9ef76SJohan Hedberg 		if (ev->status != 0)
166937d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
167037d9ef76SJohan Hedberg 		else
167148264f06SJohan Hedberg 			mgmt_disconnected(hdev, &conn->dst, conn->type,
167248264f06SJohan Hedberg 							conn->dst_type);
167337d9ef76SJohan Hedberg 	}
1674f7520543SJohan Hedberg 
167537d9ef76SJohan Hedberg 	if (ev->status == 0) {
16762950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
16771da177e4SLinus Torvalds 		hci_conn_del(conn);
167837d9ef76SJohan Hedberg 	}
16791da177e4SLinus Torvalds 
1680f7520543SJohan Hedberg unlock:
16811da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16821da177e4SLinus Torvalds }
16831da177e4SLinus Torvalds 
1684a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1685a9de9248SMarcel Holtmann {
1686a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1687a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1688a9de9248SMarcel Holtmann 
1689a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1690a9de9248SMarcel Holtmann 
1691a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1692a9de9248SMarcel Holtmann 
1693a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1694d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1695d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1696d7556e20SWaldemar Rymarkiewicz 
1697765c2a96SJohan Hedberg 	if (!ev->status) {
169819f8def0SWaldemar Rymarkiewicz 		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
1699d7556e20SWaldemar Rymarkiewicz 				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
1700d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
170119f8def0SWaldemar Rymarkiewicz 		} else {
1702a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1703765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
170419f8def0SWaldemar Rymarkiewicz 		}
17052a611692SJohan Hedberg 	} else {
1706744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
17072a611692SJohan Hedberg 	}
1708a9de9248SMarcel Holtmann 
1709a9de9248SMarcel Holtmann 	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
171019f8def0SWaldemar Rymarkiewicz 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1711a9de9248SMarcel Holtmann 
1712f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1713d7556e20SWaldemar Rymarkiewicz 		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
1714f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1715f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1716f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1717d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1718d7556e20SWaldemar Rymarkiewicz 									&cp);
1719f8558555SMarcel Holtmann 		} else {
1720f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1721f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1722f8558555SMarcel Holtmann 			hci_conn_put(conn);
1723f8558555SMarcel Holtmann 		}
1724052b30b0SMarcel Holtmann 	} else {
1725a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1726a9de9248SMarcel Holtmann 
1727052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1728052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1729052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1730052b30b0SMarcel Holtmann 	}
1731052b30b0SMarcel Holtmann 
1732a9de9248SMarcel Holtmann 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1733a9de9248SMarcel Holtmann 		if (!ev->status) {
1734a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1735f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1736f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1737d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1738d7556e20SWaldemar Rymarkiewicz 									&cp);
1739a9de9248SMarcel Holtmann 		} else {
1740a9de9248SMarcel Holtmann 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1741a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1742a9de9248SMarcel Holtmann 		}
1743a9de9248SMarcel Holtmann 	}
1744a9de9248SMarcel Holtmann 
1745d7556e20SWaldemar Rymarkiewicz unlock:
1746a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1747a9de9248SMarcel Holtmann }
1748a9de9248SMarcel Holtmann 
1749a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1750a9de9248SMarcel Holtmann {
1751127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1752127178d2SJohan Hedberg 	struct hci_conn *conn;
1753127178d2SJohan Hedberg 
1754a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1755a9de9248SMarcel Holtmann 
1756a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1757127178d2SJohan Hedberg 
1758127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1759127178d2SJohan Hedberg 
1760a88a9652SJohan Hedberg 	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
1761744cf19eSJohan Hedberg 		mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
1762a88a9652SJohan Hedberg 
1763127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
176479c6c70cSJohan Hedberg 	if (!conn)
176579c6c70cSJohan Hedberg 		goto unlock;
176679c6c70cSJohan Hedberg 
176779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
176879c6c70cSJohan Hedberg 		goto unlock;
176979c6c70cSJohan Hedberg 
177079c6c70cSJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1771127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1772127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1773127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1774127178d2SJohan Hedberg 	}
1775127178d2SJohan Hedberg 
177679c6c70cSJohan Hedberg unlock:
1777127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1778a9de9248SMarcel Holtmann }
1779a9de9248SMarcel Holtmann 
1780a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1781a9de9248SMarcel Holtmann {
1782a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1783a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1784a9de9248SMarcel Holtmann 
1785a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1786a9de9248SMarcel Holtmann 
1787a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1788a9de9248SMarcel Holtmann 
1789a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1790a9de9248SMarcel Holtmann 	if (conn) {
1791a9de9248SMarcel Holtmann 		if (!ev->status) {
1792ae293196SMarcel Holtmann 			if (ev->encrypt) {
1793ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1794ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1795a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1796da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1797ae293196SMarcel Holtmann 			} else
1798a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1799a9de9248SMarcel Holtmann 		}
1800a9de9248SMarcel Holtmann 
1801a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
1802a9de9248SMarcel Holtmann 
1803f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1804f8558555SMarcel Holtmann 			if (!ev->status)
1805f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1806f8558555SMarcel Holtmann 
1807f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1808f8558555SMarcel Holtmann 			hci_conn_put(conn);
1809f8558555SMarcel Holtmann 		} else
1810a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1811a9de9248SMarcel Holtmann 	}
1812a9de9248SMarcel Holtmann 
1813a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1814a9de9248SMarcel Holtmann }
1815a9de9248SMarcel Holtmann 
1816a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1817a9de9248SMarcel Holtmann {
1818a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1819a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1820a9de9248SMarcel Holtmann 
1821a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1822a9de9248SMarcel Holtmann 
1823a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1824a9de9248SMarcel Holtmann 
1825a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1826a9de9248SMarcel Holtmann 	if (conn) {
1827a9de9248SMarcel Holtmann 		if (!ev->status)
1828a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1829a9de9248SMarcel Holtmann 
1830a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
1831a9de9248SMarcel Holtmann 
1832a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1833a9de9248SMarcel Holtmann 	}
1834a9de9248SMarcel Holtmann 
1835a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1836a9de9248SMarcel Holtmann }
1837a9de9248SMarcel Holtmann 
1838a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
1839a9de9248SMarcel Holtmann {
1840a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
1841a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1842a9de9248SMarcel Holtmann 
1843a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1844a9de9248SMarcel Holtmann 
1845a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1846a9de9248SMarcel Holtmann 
1847a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1848ccd556feSJohan Hedberg 	if (!conn)
1849ccd556feSJohan Hedberg 		goto unlock;
1850ccd556feSJohan Hedberg 
1851769be974SMarcel Holtmann 	if (!ev->status)
1852a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
1853a9de9248SMarcel Holtmann 
1854ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
1855ccd556feSJohan Hedberg 		goto unlock;
1856ccd556feSJohan Hedberg 
1857ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
1858769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
1859769be974SMarcel Holtmann 		cp.handle = ev->handle;
1860769be974SMarcel Holtmann 		cp.page = 0x01;
1861ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
1862769be974SMarcel Holtmann 							sizeof(cp), &cp);
1863392599b9SJohan Hedberg 		goto unlock;
1864392599b9SJohan Hedberg 	}
1865392599b9SJohan Hedberg 
1866127178d2SJohan Hedberg 	if (!ev->status) {
1867127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
1868127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
1869127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
1870127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
1871127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
1872127178d2SJohan Hedberg 	}
1873392599b9SJohan Hedberg 
1874127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
1875769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
1876769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1877769be974SMarcel Holtmann 		hci_conn_put(conn);
1878769be974SMarcel Holtmann 	}
1879769be974SMarcel Holtmann 
1880ccd556feSJohan Hedberg unlock:
1881a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1882a9de9248SMarcel Holtmann }
1883a9de9248SMarcel Holtmann 
1884a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
1885a9de9248SMarcel Holtmann {
1886a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1887a9de9248SMarcel Holtmann }
1888a9de9248SMarcel Holtmann 
1889a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1890a9de9248SMarcel Holtmann {
1891a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1892a9de9248SMarcel Holtmann }
1893a9de9248SMarcel Holtmann 
1894a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1895a9de9248SMarcel Holtmann {
1896a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
1897a9de9248SMarcel Holtmann 	__u16 opcode;
1898a9de9248SMarcel Holtmann 
1899a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
1900a9de9248SMarcel Holtmann 
1901a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
1902a9de9248SMarcel Holtmann 
1903a9de9248SMarcel Holtmann 	switch (opcode) {
1904a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
1905a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
1906a9de9248SMarcel Holtmann 		break;
1907a9de9248SMarcel Holtmann 
1908a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
1909a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
1910a9de9248SMarcel Holtmann 		break;
1911a9de9248SMarcel Holtmann 
1912a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
1913a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
1914a9de9248SMarcel Holtmann 		break;
1915a9de9248SMarcel Holtmann 
1916a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
1917a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
1918a9de9248SMarcel Holtmann 		break;
1919a9de9248SMarcel Holtmann 
1920e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
1921e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
1922e4e8e37cSMarcel Holtmann 		break;
1923e4e8e37cSMarcel Holtmann 
1924a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
1925a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
1926a9de9248SMarcel Holtmann 		break;
1927a9de9248SMarcel Holtmann 
1928e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
1929e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
1930e4e8e37cSMarcel Holtmann 		break;
1931e4e8e37cSMarcel Holtmann 
1932e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
1933e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
1934e4e8e37cSMarcel Holtmann 		break;
1935e4e8e37cSMarcel Holtmann 
1936a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
1937a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
1938a9de9248SMarcel Holtmann 		break;
1939a9de9248SMarcel Holtmann 
1940a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
1941a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
1942a9de9248SMarcel Holtmann 		break;
1943a9de9248SMarcel Holtmann 
1944a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
1945a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
1946a9de9248SMarcel Holtmann 		break;
1947a9de9248SMarcel Holtmann 
1948a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
1949a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
1950a9de9248SMarcel Holtmann 		break;
1951a9de9248SMarcel Holtmann 
1952a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
1953a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
1954a9de9248SMarcel Holtmann 		break;
1955a9de9248SMarcel Holtmann 
1956a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
1957a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
1958a9de9248SMarcel Holtmann 		break;
1959a9de9248SMarcel Holtmann 
1960a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
1961a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
1962a9de9248SMarcel Holtmann 		break;
1963a9de9248SMarcel Holtmann 
1964a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
1965a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
1966a9de9248SMarcel Holtmann 		break;
1967a9de9248SMarcel Holtmann 
1968a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
1969a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
1970a9de9248SMarcel Holtmann 		break;
1971a9de9248SMarcel Holtmann 
1972a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
1973a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
1974a9de9248SMarcel Holtmann 		break;
1975a9de9248SMarcel Holtmann 
1976a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
1977a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
1978a9de9248SMarcel Holtmann 		break;
1979a9de9248SMarcel Holtmann 
1980333140b5SMarcel Holtmann 	case HCI_OP_READ_SSP_MODE:
1981333140b5SMarcel Holtmann 		hci_cc_read_ssp_mode(hdev, skb);
1982333140b5SMarcel Holtmann 		break;
1983333140b5SMarcel Holtmann 
1984333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
1985333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
1986333140b5SMarcel Holtmann 		break;
1987333140b5SMarcel Holtmann 
1988a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
1989a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
1990a9de9248SMarcel Holtmann 		break;
1991a9de9248SMarcel Holtmann 
1992a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
1993a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
1994a9de9248SMarcel Holtmann 		break;
1995a9de9248SMarcel Holtmann 
1996a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
1997a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
1998a9de9248SMarcel Holtmann 		break;
1999a9de9248SMarcel Holtmann 
2000971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2001971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2002971e3a4bSAndre Guedes 		break;
2003971e3a4bSAndre Guedes 
2004a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2005a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2006a9de9248SMarcel Holtmann 		break;
2007a9de9248SMarcel Holtmann 
2008a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2009a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2010a9de9248SMarcel Holtmann 		break;
2011a9de9248SMarcel Holtmann 
201223bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
201323bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
201423bb5763SJohan Hedberg 		break;
201523bb5763SJohan Hedberg 
20161e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
20171e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
20181e89cffbSAndrei Emeltchenko 		break;
20191e89cffbSAndrei Emeltchenko 
2020928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2021928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2022928abaa7SAndrei Emeltchenko 		break;
2023928abaa7SAndrei Emeltchenko 
2024b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2025b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2026b0916ea0SJohan Hedberg 		break;
2027b0916ea0SJohan Hedberg 
2028d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2029d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2030d5859e22SJohan Hedberg 		break;
2031d5859e22SJohan Hedberg 
2032d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2033d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2034d5859e22SJohan Hedberg 		break;
2035d5859e22SJohan Hedberg 
2036d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2037d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2038d5859e22SJohan Hedberg 		break;
2039d5859e22SJohan Hedberg 
2040d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2041d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2042d5859e22SJohan Hedberg 		break;
2043d5859e22SJohan Hedberg 
2044980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2045980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2046980e1a53SJohan Hedberg 		break;
2047980e1a53SJohan Hedberg 
2048980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2049980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2050980e1a53SJohan Hedberg 		break;
2051980e1a53SJohan Hedberg 
2052c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2053c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2054c35938b2SSzymon Janc 		break;
2055c35938b2SSzymon Janc 
20566ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
20576ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
20586ed58ec5SVille Tervo 		break;
20596ed58ec5SVille Tervo 
2060a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2061a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2062a5c29683SJohan Hedberg 		break;
2063a5c29683SJohan Hedberg 
2064a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2065a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2066a5c29683SJohan Hedberg 		break;
2067a5c29683SJohan Hedberg 
20681143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
20691143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
20701143d458SBrian Gix 		break;
20711143d458SBrian Gix 
20721143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
20731143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
20741143d458SBrian Gix 		break;
20751143d458SBrian Gix 
2076eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2077eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2078eb9d91f5SAndre Guedes 		break;
2079eb9d91f5SAndre Guedes 
2080a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2081a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2082a7a595f6SVinicius Costa Gomes 		break;
2083a7a595f6SVinicius Costa Gomes 
2084a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2085a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2086a7a595f6SVinicius Costa Gomes 		break;
2087a7a595f6SVinicius Costa Gomes 
2088f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2089f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2090f9b49306SAndre Guedes 		break;
2091f9b49306SAndre Guedes 
2092a9de9248SMarcel Holtmann 	default:
2093a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2094a9de9248SMarcel Holtmann 		break;
2095a9de9248SMarcel Holtmann 	}
2096a9de9248SMarcel Holtmann 
20976bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
20986bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
20996bd32326SVille Tervo 
2100a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2101a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2102a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2103c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2104a9de9248SMarcel Holtmann 	}
2105a9de9248SMarcel Holtmann }
2106a9de9248SMarcel Holtmann 
2107a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2108a9de9248SMarcel Holtmann {
2109a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2110a9de9248SMarcel Holtmann 	__u16 opcode;
2111a9de9248SMarcel Holtmann 
2112a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2113a9de9248SMarcel Holtmann 
2114a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2115a9de9248SMarcel Holtmann 
2116a9de9248SMarcel Holtmann 	switch (opcode) {
2117a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2118a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2119a9de9248SMarcel Holtmann 		break;
2120a9de9248SMarcel Holtmann 
2121a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2122a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2123a9de9248SMarcel Holtmann 		break;
2124a9de9248SMarcel Holtmann 
2125a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2126a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2127a9de9248SMarcel Holtmann 		break;
2128a9de9248SMarcel Holtmann 
2129f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2130f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2131f8558555SMarcel Holtmann 		break;
2132f8558555SMarcel Holtmann 
2133f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2134f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2135f8558555SMarcel Holtmann 		break;
2136f8558555SMarcel Holtmann 
2137a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2138a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2139a9de9248SMarcel Holtmann 		break;
2140a9de9248SMarcel Holtmann 
2141769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2142769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2143769be974SMarcel Holtmann 		break;
2144769be974SMarcel Holtmann 
2145769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2146769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2147769be974SMarcel Holtmann 		break;
2148769be974SMarcel Holtmann 
2149a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2150a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2151a9de9248SMarcel Holtmann 		break;
2152a9de9248SMarcel Holtmann 
2153a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2154a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2155a9de9248SMarcel Holtmann 		break;
2156a9de9248SMarcel Holtmann 
2157a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2158a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2159a9de9248SMarcel Holtmann 		break;
2160a9de9248SMarcel Holtmann 
21618962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
21628962ee74SJohan Hedberg 		if (ev->status != 0)
216337d9ef76SJohan Hedberg 			mgmt_disconnect_failed(hdev, NULL, ev->status);
21648962ee74SJohan Hedberg 		break;
21658962ee74SJohan Hedberg 
2166fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2167fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2168fcd89c09SVille Tervo 		break;
2169fcd89c09SVille Tervo 
2170a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2171a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2172a7a595f6SVinicius Costa Gomes 		break;
2173a7a595f6SVinicius Costa Gomes 
2174a9de9248SMarcel Holtmann 	default:
2175a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2176a9de9248SMarcel Holtmann 		break;
2177a9de9248SMarcel Holtmann 	}
2178a9de9248SMarcel Holtmann 
21796bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
21806bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
21816bd32326SVille Tervo 
218210572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2183a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2184a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2185c78ae283SMarcel Holtmann 			tasklet_schedule(&hdev->cmd_task);
2186a9de9248SMarcel Holtmann 	}
2187a9de9248SMarcel Holtmann }
2188a9de9248SMarcel Holtmann 
2189a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2190a9de9248SMarcel Holtmann {
2191a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2192a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2193a9de9248SMarcel Holtmann 
2194a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2195a9de9248SMarcel Holtmann 
2196a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2197a9de9248SMarcel Holtmann 
2198a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2199a9de9248SMarcel Holtmann 	if (conn) {
2200a9de9248SMarcel Holtmann 		if (!ev->status) {
2201a9de9248SMarcel Holtmann 			if (ev->role)
2202a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2203a9de9248SMarcel Holtmann 			else
2204a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2205a9de9248SMarcel Holtmann 		}
2206a9de9248SMarcel Holtmann 
2207a9de9248SMarcel Holtmann 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
2208a9de9248SMarcel Holtmann 
2209a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2210a9de9248SMarcel Holtmann 	}
2211a9de9248SMarcel Holtmann 
2212a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2213a9de9248SMarcel Holtmann }
2214a9de9248SMarcel Holtmann 
22151da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
22161da177e4SLinus Torvalds {
2217a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
22181ebb9252SMarcel Holtmann 	__le16 *ptr;
22191da177e4SLinus Torvalds 	int i;
22201da177e4SLinus Torvalds 
22211da177e4SLinus Torvalds 	skb_pull(skb, sizeof(*ev));
22221da177e4SLinus Torvalds 
22231da177e4SLinus Torvalds 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
22241da177e4SLinus Torvalds 
22251da177e4SLinus Torvalds 	if (skb->len < ev->num_hndl * 4) {
22261da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
22271da177e4SLinus Torvalds 		return;
22281da177e4SLinus Torvalds 	}
22291da177e4SLinus Torvalds 
22301da177e4SLinus Torvalds 	tasklet_disable(&hdev->tx_task);
22311da177e4SLinus Torvalds 
22321ebb9252SMarcel Holtmann 	for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
22331da177e4SLinus Torvalds 		struct hci_conn *conn;
22341da177e4SLinus Torvalds 		__u16  handle, count;
22351da177e4SLinus Torvalds 
223683985319SHarvey Harrison 		handle = get_unaligned_le16(ptr++);
223783985319SHarvey Harrison 		count  = get_unaligned_le16(ptr++);
22381da177e4SLinus Torvalds 
22391da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
22401da177e4SLinus Torvalds 		if (conn) {
22411da177e4SLinus Torvalds 			conn->sent -= count;
22421da177e4SLinus Torvalds 
22435b7f9909SMarcel Holtmann 			if (conn->type == ACL_LINK) {
224470f23020SAndrei Emeltchenko 				hdev->acl_cnt += count;
224570f23020SAndrei Emeltchenko 				if (hdev->acl_cnt > hdev->acl_pkts)
22461da177e4SLinus Torvalds 					hdev->acl_cnt = hdev->acl_pkts;
22476ed58ec5SVille Tervo 			} else if (conn->type == LE_LINK) {
22486ed58ec5SVille Tervo 				if (hdev->le_pkts) {
22496ed58ec5SVille Tervo 					hdev->le_cnt += count;
22506ed58ec5SVille Tervo 					if (hdev->le_cnt > hdev->le_pkts)
22516ed58ec5SVille Tervo 						hdev->le_cnt = hdev->le_pkts;
22526ed58ec5SVille Tervo 				} else {
22536ed58ec5SVille Tervo 					hdev->acl_cnt += count;
22546ed58ec5SVille Tervo 					if (hdev->acl_cnt > hdev->acl_pkts)
22556ed58ec5SVille Tervo 						hdev->acl_cnt = hdev->acl_pkts;
22566ed58ec5SVille Tervo 				}
22575b7f9909SMarcel Holtmann 			} else {
225870f23020SAndrei Emeltchenko 				hdev->sco_cnt += count;
225970f23020SAndrei Emeltchenko 				if (hdev->sco_cnt > hdev->sco_pkts)
22605b7f9909SMarcel Holtmann 					hdev->sco_cnt = hdev->sco_pkts;
22611da177e4SLinus Torvalds 			}
22621da177e4SLinus Torvalds 		}
22631da177e4SLinus Torvalds 	}
2264a9de9248SMarcel Holtmann 
2265c78ae283SMarcel Holtmann 	tasklet_schedule(&hdev->tx_task);
22661da177e4SLinus Torvalds 
22671da177e4SLinus Torvalds 	tasklet_enable(&hdev->tx_task);
22681da177e4SLinus Torvalds }
22691da177e4SLinus Torvalds 
227004837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
22711da177e4SLinus Torvalds {
2272a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
227304837f64SMarcel Holtmann 	struct hci_conn *conn;
22741da177e4SLinus Torvalds 
22751da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
22761da177e4SLinus Torvalds 
22771da177e4SLinus Torvalds 	hci_dev_lock(hdev);
22781da177e4SLinus Torvalds 
227904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
228004837f64SMarcel Holtmann 	if (conn) {
228104837f64SMarcel Holtmann 		conn->mode = ev->mode;
228204837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
228304837f64SMarcel Holtmann 
228404837f64SMarcel Holtmann 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
228504837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
228604837f64SMarcel Holtmann 				conn->power_save = 1;
228704837f64SMarcel Holtmann 			else
228804837f64SMarcel Holtmann 				conn->power_save = 0;
228904837f64SMarcel Holtmann 		}
2290e73439d8SMarcel Holtmann 
2291e73439d8SMarcel Holtmann 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
2292e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
229304837f64SMarcel Holtmann 	}
229404837f64SMarcel Holtmann 
229504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
229604837f64SMarcel Holtmann }
229704837f64SMarcel Holtmann 
22981da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
22991da177e4SLinus Torvalds {
2300052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2301052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2302052b30b0SMarcel Holtmann 
2303a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2304052b30b0SMarcel Holtmann 
2305052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2306052b30b0SMarcel Holtmann 
2307052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2308b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2309b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2310b6f98044SWaldemar Rymarkiewicz 
2311b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2312052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2313052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2314052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2315052b30b0SMarcel Holtmann 	}
2316052b30b0SMarcel Holtmann 
231703b555e1SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
231803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
231903b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2320582fbe9eSJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->flags)) {
2321a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2322a770bb5aSWaldemar Rymarkiewicz 
2323a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2324a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2325a770bb5aSWaldemar Rymarkiewicz 		else
2326a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2327a770bb5aSWaldemar Rymarkiewicz 
2328744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2329a770bb5aSWaldemar Rymarkiewicz 	}
2330980e1a53SJohan Hedberg 
2331b6f98044SWaldemar Rymarkiewicz unlock:
2332052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
23331da177e4SLinus Torvalds }
23341da177e4SLinus Torvalds 
23351da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
23361da177e4SLinus Torvalds {
233755ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
233855ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
233955ed8ca1SJohan Hedberg 	struct hci_conn *conn;
234055ed8ca1SJohan Hedberg 	struct link_key *key;
234155ed8ca1SJohan Hedberg 
2342a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
234355ed8ca1SJohan Hedberg 
234455ed8ca1SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
234555ed8ca1SJohan Hedberg 		return;
234655ed8ca1SJohan Hedberg 
234755ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
234855ed8ca1SJohan Hedberg 
234955ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
235055ed8ca1SJohan Hedberg 	if (!key) {
235155ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
235255ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
235355ed8ca1SJohan Hedberg 		goto not_found;
235455ed8ca1SJohan Hedberg 	}
235555ed8ca1SJohan Hedberg 
235655ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
235755ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
235855ed8ca1SJohan Hedberg 
2359b6020ba0SWaldemar Rymarkiewicz 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
2360b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
236155ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
236255ed8ca1SJohan Hedberg 		goto not_found;
236355ed8ca1SJohan Hedberg 	}
236455ed8ca1SJohan Hedberg 
236555ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
236660b83f57SWaldemar Rymarkiewicz 	if (conn) {
236760b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
236860b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
236960b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
237055ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
237155ed8ca1SJohan Hedberg 			goto not_found;
237255ed8ca1SJohan Hedberg 		}
237355ed8ca1SJohan Hedberg 
237460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
237560b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
237660b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
237760b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
237860b83f57SWaldemar Rymarkiewicz 			goto not_found;
237960b83f57SWaldemar Rymarkiewicz 		}
238060b83f57SWaldemar Rymarkiewicz 
238160b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
238260b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
238360b83f57SWaldemar Rymarkiewicz 	}
238460b83f57SWaldemar Rymarkiewicz 
238555ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
238655ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
238755ed8ca1SJohan Hedberg 
238855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
238955ed8ca1SJohan Hedberg 
239055ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
239155ed8ca1SJohan Hedberg 
239255ed8ca1SJohan Hedberg 	return;
239355ed8ca1SJohan Hedberg 
239455ed8ca1SJohan Hedberg not_found:
239555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
239655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
23971da177e4SLinus Torvalds }
23981da177e4SLinus Torvalds 
23991da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
24001da177e4SLinus Torvalds {
2401052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2402052b30b0SMarcel Holtmann 	struct hci_conn *conn;
240355ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2404052b30b0SMarcel Holtmann 
2405a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2406052b30b0SMarcel Holtmann 
2407052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2408052b30b0SMarcel Holtmann 
2409052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2410052b30b0SMarcel Holtmann 	if (conn) {
2411052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2412052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2413980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
241413d39315SWaldemar Rymarkiewicz 
241513d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
241613d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
241713d39315SWaldemar Rymarkiewicz 
2418052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2419052b30b0SMarcel Holtmann 	}
2420052b30b0SMarcel Holtmann 
242155ed8ca1SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
2422d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
242355ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
242455ed8ca1SJohan Hedberg 
2425052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
24261da177e4SLinus Torvalds }
24271da177e4SLinus Torvalds 
242804837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
242904837f64SMarcel Holtmann {
2430a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
243104837f64SMarcel Holtmann 	struct hci_conn *conn;
243204837f64SMarcel Holtmann 
243304837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
243404837f64SMarcel Holtmann 
243504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
243604837f64SMarcel Holtmann 
243704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
24381da177e4SLinus Torvalds 	if (conn && !ev->status) {
24391da177e4SLinus Torvalds 		struct inquiry_entry *ie;
24401da177e4SLinus Torvalds 
2441cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2442cc11b9c1SAndrei Emeltchenko 		if (ie) {
24431da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
24441da177e4SLinus Torvalds 			ie->timestamp = jiffies;
24451da177e4SLinus Torvalds 		}
24461da177e4SLinus Torvalds 	}
24471da177e4SLinus Torvalds 
24481da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
24491da177e4SLinus Torvalds }
24501da177e4SLinus Torvalds 
2451a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2452a8746417SMarcel Holtmann {
2453a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2454a8746417SMarcel Holtmann 	struct hci_conn *conn;
2455a8746417SMarcel Holtmann 
2456a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2457a8746417SMarcel Holtmann 
2458a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2459a8746417SMarcel Holtmann 
2460a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2461a8746417SMarcel Holtmann 	if (conn && !ev->status)
2462a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2463a8746417SMarcel Holtmann 
2464a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2465a8746417SMarcel Holtmann }
2466a8746417SMarcel Holtmann 
246785a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
246885a1e930SMarcel Holtmann {
2469a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
247085a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
247185a1e930SMarcel Holtmann 
247285a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
247385a1e930SMarcel Holtmann 
247485a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
247585a1e930SMarcel Holtmann 
2476cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2477cc11b9c1SAndrei Emeltchenko 	if (ie) {
247885a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
247985a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
248085a1e930SMarcel Holtmann 	}
248185a1e930SMarcel Holtmann 
248285a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
248385a1e930SMarcel Holtmann }
248485a1e930SMarcel Holtmann 
2485a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2486a9de9248SMarcel Holtmann {
2487a9de9248SMarcel Holtmann 	struct inquiry_data data;
2488a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2489a9de9248SMarcel Holtmann 
2490a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2491a9de9248SMarcel Holtmann 
2492a9de9248SMarcel Holtmann 	if (!num_rsp)
2493a9de9248SMarcel Holtmann 		return;
2494a9de9248SMarcel Holtmann 
2495a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2496a9de9248SMarcel Holtmann 
2497a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2498138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2499138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2500a9de9248SMarcel Holtmann 
2501e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2502a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2503a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2504a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2505a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2506a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2507a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2508a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
250941a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2510a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
251148264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2512e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2513e17acd40SJohan Hedberg 						NULL);
2514a9de9248SMarcel Holtmann 		}
2515a9de9248SMarcel Holtmann 	} else {
2516a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2517a9de9248SMarcel Holtmann 
2518e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2519a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2520a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2521a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2522a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2523a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2524a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2525a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
252641a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
2527a9de9248SMarcel Holtmann 			hci_inquiry_cache_update(hdev, &data);
252848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2529e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2530e17acd40SJohan Hedberg 						NULL);
2531a9de9248SMarcel Holtmann 		}
2532a9de9248SMarcel Holtmann 	}
2533a9de9248SMarcel Holtmann 
2534a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2535a9de9248SMarcel Holtmann }
2536a9de9248SMarcel Holtmann 
2537a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2538a9de9248SMarcel Holtmann {
253941a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
254041a96212SMarcel Holtmann 	struct hci_conn *conn;
254141a96212SMarcel Holtmann 
2542a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
254341a96212SMarcel Holtmann 
254441a96212SMarcel Holtmann 	hci_dev_lock(hdev);
254541a96212SMarcel Holtmann 
254641a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2547ccd556feSJohan Hedberg 	if (!conn)
2548ccd556feSJohan Hedberg 		goto unlock;
2549ccd556feSJohan Hedberg 
2550769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
255141a96212SMarcel Holtmann 		struct inquiry_entry *ie;
255241a96212SMarcel Holtmann 
2553cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2554cc11b9c1SAndrei Emeltchenko 		if (ie)
255541a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
255641a96212SMarcel Holtmann 
255741a96212SMarcel Holtmann 		conn->ssp_mode = (ev->features[0] & 0x01);
255841a96212SMarcel Holtmann 	}
255941a96212SMarcel Holtmann 
2560ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2561ccd556feSJohan Hedberg 		goto unlock;
2562ccd556feSJohan Hedberg 
2563127178d2SJohan Hedberg 	if (!ev->status) {
2564127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2565127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2566127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2567127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2568127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2569127178d2SJohan Hedberg 	}
2570392599b9SJohan Hedberg 
2571127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2572769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2573769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2574769be974SMarcel Holtmann 		hci_conn_put(conn);
2575769be974SMarcel Holtmann 	}
2576769be974SMarcel Holtmann 
2577ccd556feSJohan Hedberg unlock:
257841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2579a9de9248SMarcel Holtmann }
2580a9de9248SMarcel Holtmann 
2581a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2582a9de9248SMarcel Holtmann {
2583b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2584b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2585b6a0dc82SMarcel Holtmann 
2586b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2587b6a0dc82SMarcel Holtmann 
2588b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2589b6a0dc82SMarcel Holtmann 
2590b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
25919dc0a3afSMarcel Holtmann 	if (!conn) {
25929dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
25939dc0a3afSMarcel Holtmann 			goto unlock;
25949dc0a3afSMarcel Holtmann 
25959dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2596b6a0dc82SMarcel Holtmann 		if (!conn)
2597b6a0dc82SMarcel Holtmann 			goto unlock;
2598b6a0dc82SMarcel Holtmann 
25999dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
26009dc0a3afSMarcel Holtmann 	}
26019dc0a3afSMarcel Holtmann 
2602732547f9SMarcel Holtmann 	switch (ev->status) {
2603732547f9SMarcel Holtmann 	case 0x00:
2604732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2605732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2606732547f9SMarcel Holtmann 
26079eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2608732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2609732547f9SMarcel Holtmann 		break;
2610732547f9SMarcel Holtmann 
2611705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2612732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
26131038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2614732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2615732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2616efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2617efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2618efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2619efc7688bSMarcel Holtmann 			goto unlock;
2620efc7688bSMarcel Holtmann 		}
2621732547f9SMarcel Holtmann 		/* fall through */
2622efc7688bSMarcel Holtmann 
2623732547f9SMarcel Holtmann 	default:
2624b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2625732547f9SMarcel Holtmann 		break;
2626732547f9SMarcel Holtmann 	}
2627b6a0dc82SMarcel Holtmann 
2628b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2629b6a0dc82SMarcel Holtmann 	if (ev->status)
2630b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2631b6a0dc82SMarcel Holtmann 
2632b6a0dc82SMarcel Holtmann unlock:
2633b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2634a9de9248SMarcel Holtmann }
2635a9de9248SMarcel Holtmann 
2636a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2637a9de9248SMarcel Holtmann {
2638a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2639a9de9248SMarcel Holtmann }
2640a9de9248SMarcel Holtmann 
264104837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
264204837f64SMarcel Holtmann {
2643a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
264404837f64SMarcel Holtmann 
264504837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
264604837f64SMarcel Holtmann }
264704837f64SMarcel Holtmann 
2648a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2649a9de9248SMarcel Holtmann {
2650a9de9248SMarcel Holtmann 	struct inquiry_data data;
2651a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2652a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2653a9de9248SMarcel Holtmann 
2654a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2655a9de9248SMarcel Holtmann 
2656a9de9248SMarcel Holtmann 	if (!num_rsp)
2657a9de9248SMarcel Holtmann 		return;
2658a9de9248SMarcel Holtmann 
2659a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2660a9de9248SMarcel Holtmann 
2661e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2662a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2663a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2664a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2665a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2666a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2667a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2668a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
266941a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2670a9de9248SMarcel Holtmann 		hci_inquiry_cache_update(hdev, &data);
267148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
26724c659c39SJohan Hedberg 				info->dev_class, info->rssi, info->data);
2673a9de9248SMarcel Holtmann 	}
2674a9de9248SMarcel Holtmann 
2675a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2676a9de9248SMarcel Holtmann }
2677a9de9248SMarcel Holtmann 
267817fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
267917fa4b9dSJohan Hedberg {
268017fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
268117fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
268217fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
268317fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
268417fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
268517fa4b9dSJohan Hedberg 			return 0x02;
268617fa4b9dSJohan Hedberg 		else
268717fa4b9dSJohan Hedberg 			return 0x03;
268817fa4b9dSJohan Hedberg 	}
268917fa4b9dSJohan Hedberg 
269017fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
269117fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
269258797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
269317fa4b9dSJohan Hedberg 
269417fa4b9dSJohan Hedberg 	return conn->auth_type;
269517fa4b9dSJohan Hedberg }
269617fa4b9dSJohan Hedberg 
26970493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26980493684eSMarcel Holtmann {
26990493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
27000493684eSMarcel Holtmann 	struct hci_conn *conn;
27010493684eSMarcel Holtmann 
27020493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
27030493684eSMarcel Holtmann 
27040493684eSMarcel Holtmann 	hci_dev_lock(hdev);
27050493684eSMarcel Holtmann 
27060493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
270703b555e1SJohan Hedberg 	if (!conn)
270803b555e1SJohan Hedberg 		goto unlock;
270903b555e1SJohan Hedberg 
27100493684eSMarcel Holtmann 	hci_conn_hold(conn);
27110493684eSMarcel Holtmann 
271203b555e1SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
271303b555e1SJohan Hedberg 		goto unlock;
271403b555e1SJohan Hedberg 
271503b555e1SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
271603b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
271717fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
271817fa4b9dSJohan Hedberg 
271917fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
272017fa4b9dSJohan Hedberg 		cp.capability = conn->io_capability;
27217cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
27227cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
272317fa4b9dSJohan Hedberg 
2724ce85ee13SSzymon Janc 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
2725ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
2726ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
2727ce85ee13SSzymon Janc 		else
2728ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
2729ce85ee13SSzymon Janc 
273017fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
273117fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
273203b555e1SJohan Hedberg 	} else {
273303b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
273403b555e1SJohan Hedberg 
273503b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
27369f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
273703b555e1SJohan Hedberg 
273803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
273903b555e1SJohan Hedberg 							sizeof(cp), &cp);
274003b555e1SJohan Hedberg 	}
274103b555e1SJohan Hedberg 
274203b555e1SJohan Hedberg unlock:
274303b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
274403b555e1SJohan Hedberg }
274503b555e1SJohan Hedberg 
274603b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
274703b555e1SJohan Hedberg {
274803b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
274903b555e1SJohan Hedberg 	struct hci_conn *conn;
275003b555e1SJohan Hedberg 
275103b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
275203b555e1SJohan Hedberg 
275303b555e1SJohan Hedberg 	hci_dev_lock(hdev);
275403b555e1SJohan Hedberg 
275503b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
275603b555e1SJohan Hedberg 	if (!conn)
275703b555e1SJohan Hedberg 		goto unlock;
275803b555e1SJohan Hedberg 
275903b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
276003b555e1SJohan Hedberg 	conn->remote_oob = ev->oob_data;
276103b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
276203b555e1SJohan Hedberg 
276303b555e1SJohan Hedberg unlock:
27640493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
27650493684eSMarcel Holtmann }
27660493684eSMarcel Holtmann 
2767a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
2768a5c29683SJohan Hedberg 							struct sk_buff *skb)
2769a5c29683SJohan Hedberg {
2770a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
277155bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
27727a828908SJohan Hedberg 	struct hci_conn *conn;
2773a5c29683SJohan Hedberg 
2774a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
2775a5c29683SJohan Hedberg 
2776a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
2777a5c29683SJohan Hedberg 
27787a828908SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->flags))
27797a828908SJohan Hedberg 		goto unlock;
27807a828908SJohan Hedberg 
27817a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
27827a828908SJohan Hedberg 	if (!conn)
27837a828908SJohan Hedberg 		goto unlock;
27847a828908SJohan Hedberg 
27857a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
27867a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
27877a828908SJohan Hedberg 
27887a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
27897a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
27907a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
27917a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
27927a828908SJohan Hedberg 	 * bit set. */
27937a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
27947a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
27957a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
27967a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
27977a828908SJohan Hedberg 		goto unlock;
27987a828908SJohan Hedberg 	}
27997a828908SJohan Hedberg 
28007a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
28017a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
28027a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
280355bc1a37SJohan Hedberg 
280455bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
280555bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
280655bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
280755bc1a37SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
280855bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
280955bc1a37SJohan Hedberg 			confirm_hint = 1;
281055bc1a37SJohan Hedberg 			goto confirm;
281155bc1a37SJohan Hedberg 		}
281255bc1a37SJohan Hedberg 
28139f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
28149f61656aSJohan Hedberg 						hdev->auto_accept_delay);
28159f61656aSJohan Hedberg 
28169f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
28179f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
28189f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
28199f61656aSJohan Hedberg 			goto unlock;
28209f61656aSJohan Hedberg 		}
28219f61656aSJohan Hedberg 
28227a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
28237a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
28247a828908SJohan Hedberg 		goto unlock;
28257a828908SJohan Hedberg 	}
28267a828908SJohan Hedberg 
282755bc1a37SJohan Hedberg confirm:
2828744cf19eSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
282955bc1a37SJohan Hedberg 								confirm_hint);
2830a5c29683SJohan Hedberg 
28317a828908SJohan Hedberg unlock:
2832a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
2833a5c29683SJohan Hedberg }
2834a5c29683SJohan Hedberg 
28351143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
28361143d458SBrian Gix 							struct sk_buff *skb)
28371143d458SBrian Gix {
28381143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
28391143d458SBrian Gix 
28401143d458SBrian Gix 	BT_DBG("%s", hdev->name);
28411143d458SBrian Gix 
28421143d458SBrian Gix 	hci_dev_lock(hdev);
28431143d458SBrian Gix 
28441143d458SBrian Gix 	if (test_bit(HCI_MGMT, &hdev->flags))
28451143d458SBrian Gix 		mgmt_user_passkey_request(hdev, &ev->bdaddr);
28461143d458SBrian Gix 
28471143d458SBrian Gix 	hci_dev_unlock(hdev);
28481143d458SBrian Gix }
28491143d458SBrian Gix 
28500493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
28510493684eSMarcel Holtmann {
28520493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
28530493684eSMarcel Holtmann 	struct hci_conn *conn;
28540493684eSMarcel Holtmann 
28550493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
28560493684eSMarcel Holtmann 
28570493684eSMarcel Holtmann 	hci_dev_lock(hdev);
28580493684eSMarcel Holtmann 
28590493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
28602a611692SJohan Hedberg 	if (!conn)
28612a611692SJohan Hedberg 		goto unlock;
28622a611692SJohan Hedberg 
28632a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
28642a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
28652a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
28662a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
28672a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
28682a611692SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
2869744cf19eSJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, ev->status);
28702a611692SJohan Hedberg 
28710493684eSMarcel Holtmann 	hci_conn_put(conn);
28720493684eSMarcel Holtmann 
28732a611692SJohan Hedberg unlock:
28740493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
28750493684eSMarcel Holtmann }
28760493684eSMarcel Holtmann 
287741a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
287841a96212SMarcel Holtmann {
287941a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
288041a96212SMarcel Holtmann 	struct inquiry_entry *ie;
288141a96212SMarcel Holtmann 
288241a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
288341a96212SMarcel Holtmann 
288441a96212SMarcel Holtmann 	hci_dev_lock(hdev);
288541a96212SMarcel Holtmann 
2886cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2887cc11b9c1SAndrei Emeltchenko 	if (ie)
288841a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
288941a96212SMarcel Holtmann 
289041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
289141a96212SMarcel Holtmann }
289241a96212SMarcel Holtmann 
28932763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
28942763eda6SSzymon Janc 							struct sk_buff *skb)
28952763eda6SSzymon Janc {
28962763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
28972763eda6SSzymon Janc 	struct oob_data *data;
28982763eda6SSzymon Janc 
28992763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
29002763eda6SSzymon Janc 
29012763eda6SSzymon Janc 	hci_dev_lock(hdev);
29022763eda6SSzymon Janc 
2903e1ba1f15SSzymon Janc 	if (!test_bit(HCI_MGMT, &hdev->flags))
2904e1ba1f15SSzymon Janc 		goto unlock;
2905e1ba1f15SSzymon Janc 
29062763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
29072763eda6SSzymon Janc 	if (data) {
29082763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
29092763eda6SSzymon Janc 
29102763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
29112763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
29122763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
29132763eda6SSzymon Janc 
29142763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
29152763eda6SSzymon Janc 									&cp);
29162763eda6SSzymon Janc 	} else {
29172763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
29182763eda6SSzymon Janc 
29192763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
29202763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
29212763eda6SSzymon Janc 									&cp);
29222763eda6SSzymon Janc 	}
29232763eda6SSzymon Janc 
2924e1ba1f15SSzymon Janc unlock:
29252763eda6SSzymon Janc 	hci_dev_unlock(hdev);
29262763eda6SSzymon Janc }
29272763eda6SSzymon Janc 
2928fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2929fcd89c09SVille Tervo {
2930fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2931fcd89c09SVille Tervo 	struct hci_conn *conn;
2932fcd89c09SVille Tervo 
2933fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
2934fcd89c09SVille Tervo 
2935fcd89c09SVille Tervo 	hci_dev_lock(hdev);
2936fcd89c09SVille Tervo 
2937fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2938b62f328bSVille Tervo 	if (!conn) {
2939b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
2940b62f328bSVille Tervo 		if (!conn) {
2941b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
2942b62f328bSVille Tervo 			hci_dev_unlock(hdev);
2943b62f328bSVille Tervo 			return;
2944b62f328bSVille Tervo 		}
294529b7988aSAndre Guedes 
294629b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
2947b62f328bSVille Tervo 	}
2948fcd89c09SVille Tervo 
2949fcd89c09SVille Tervo 	if (ev->status) {
295048264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
295148264f06SJohan Hedberg 						conn->dst_type, ev->status);
2952fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
2953fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
2954fcd89c09SVille Tervo 		hci_conn_del(conn);
2955fcd89c09SVille Tervo 		goto unlock;
2956fcd89c09SVille Tervo 	}
2957fcd89c09SVille Tervo 
295848264f06SJohan Hedberg 	mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
295983bc71b4SVinicius Costa Gomes 
29607b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
2961fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
2962fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
2963fcd89c09SVille Tervo 
2964fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
2965fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
2966fcd89c09SVille Tervo 
2967fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
2968fcd89c09SVille Tervo 
2969fcd89c09SVille Tervo unlock:
2970fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
2971fcd89c09SVille Tervo }
2972fcd89c09SVille Tervo 
29739aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
29749aa04c91SAndre Guedes 						struct sk_buff *skb)
29759aa04c91SAndre Guedes {
2976e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
2977e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
29789aa04c91SAndre Guedes 
29799aa04c91SAndre Guedes 	hci_dev_lock(hdev);
29809aa04c91SAndre Guedes 
2981e95beb41SAndre Guedes 	while (num_reports--) {
2982e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
2983e95beb41SAndre Guedes 
29849aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
29859aa04c91SAndre Guedes 
2986e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
29879aa04c91SAndre Guedes 	}
29889aa04c91SAndre Guedes 
29899aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
29909aa04c91SAndre Guedes }
29919aa04c91SAndre Guedes 
2992a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
2993a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
2994a7a595f6SVinicius Costa Gomes {
2995a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
2996a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
2997bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
2998a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
2999bea710feSVinicius Costa Gomes 	struct link_key *ltk;
3000a7a595f6SVinicius Costa Gomes 
3001a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3002a7a595f6SVinicius Costa Gomes 
3003a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3004a7a595f6SVinicius Costa Gomes 
3005a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3006bea710feSVinicius Costa Gomes 	if (conn == NULL)
3007bea710feSVinicius Costa Gomes 		goto not_found;
3008a7a595f6SVinicius Costa Gomes 
3009bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3010bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3011bea710feSVinicius Costa Gomes 		goto not_found;
3012bea710feSVinicius Costa Gomes 
3013bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3014a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3015726b4ffcSVinicius Costa Gomes 	conn->pin_length = ltk->pin_len;
3016a7a595f6SVinicius Costa Gomes 
3017a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3018a7a595f6SVinicius Costa Gomes 
3019a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3020bea710feSVinicius Costa Gomes 
3021bea710feSVinicius Costa Gomes 	return;
3022bea710feSVinicius Costa Gomes 
3023bea710feSVinicius Costa Gomes not_found:
3024bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3025bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3026bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3027a7a595f6SVinicius Costa Gomes }
3028a7a595f6SVinicius Costa Gomes 
3029fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3030fcd89c09SVille Tervo {
3031fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3032fcd89c09SVille Tervo 
3033fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3034fcd89c09SVille Tervo 
3035fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3036fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3037fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3038fcd89c09SVille Tervo 		break;
3039fcd89c09SVille Tervo 
30409aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
30419aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
30429aa04c91SAndre Guedes 		break;
30439aa04c91SAndre Guedes 
3044a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3045a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3046a7a595f6SVinicius Costa Gomes 		break;
3047a7a595f6SVinicius Costa Gomes 
3048fcd89c09SVille Tervo 	default:
3049fcd89c09SVille Tervo 		break;
3050fcd89c09SVille Tervo 	}
3051fcd89c09SVille Tervo }
3052fcd89c09SVille Tervo 
30531da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
30541da177e4SLinus Torvalds {
3055a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3056a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
30571da177e4SLinus Torvalds 
30581da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
30591da177e4SLinus Torvalds 
3060a9de9248SMarcel Holtmann 	switch (event) {
30611da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
30621da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
30631da177e4SLinus Torvalds 		break;
30641da177e4SLinus Torvalds 
30651da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
30661da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
30671da177e4SLinus Torvalds 		break;
30681da177e4SLinus Torvalds 
3069a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3070a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
307121d9e30eSMarcel Holtmann 		break;
307221d9e30eSMarcel Holtmann 
30731da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
30741da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
30751da177e4SLinus Torvalds 		break;
30761da177e4SLinus Torvalds 
30771da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
30781da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
30791da177e4SLinus Torvalds 		break;
30801da177e4SLinus Torvalds 
30811da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
30821da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
30831da177e4SLinus Torvalds 		break;
30841da177e4SLinus Torvalds 
3085a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3086a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3087a9de9248SMarcel Holtmann 		break;
3088a9de9248SMarcel Holtmann 
30891da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
30901da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
30911da177e4SLinus Torvalds 		break;
30921da177e4SLinus Torvalds 
3093a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3094a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3095a9de9248SMarcel Holtmann 		break;
3096a9de9248SMarcel Holtmann 
3097a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3098a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3099a9de9248SMarcel Holtmann 		break;
3100a9de9248SMarcel Holtmann 
3101a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3102a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3103a9de9248SMarcel Holtmann 		break;
3104a9de9248SMarcel Holtmann 
3105a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3106a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3107a9de9248SMarcel Holtmann 		break;
3108a9de9248SMarcel Holtmann 
3109a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3110a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3111a9de9248SMarcel Holtmann 		break;
3112a9de9248SMarcel Holtmann 
3113a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3114a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3115a9de9248SMarcel Holtmann 		break;
3116a9de9248SMarcel Holtmann 
3117a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3118a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3119a9de9248SMarcel Holtmann 		break;
3120a9de9248SMarcel Holtmann 
3121a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3122a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3123a9de9248SMarcel Holtmann 		break;
3124a9de9248SMarcel Holtmann 
3125a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3126a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
31271da177e4SLinus Torvalds 		break;
31281da177e4SLinus Torvalds 
31291da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
31301da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
31311da177e4SLinus Torvalds 		break;
31321da177e4SLinus Torvalds 
31331da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
31341da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
31351da177e4SLinus Torvalds 		break;
31361da177e4SLinus Torvalds 
31371da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
31381da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
31391da177e4SLinus Torvalds 		break;
31401da177e4SLinus Torvalds 
31411da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
31421da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
31431da177e4SLinus Torvalds 		break;
31441da177e4SLinus Torvalds 
3145a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3146a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3147a8746417SMarcel Holtmann 		break;
3148a8746417SMarcel Holtmann 
314985a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
315085a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
315185a1e930SMarcel Holtmann 		break;
315285a1e930SMarcel Holtmann 
3153a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3154a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3155a9de9248SMarcel Holtmann 		break;
3156a9de9248SMarcel Holtmann 
3157a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3158a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3159a9de9248SMarcel Holtmann 		break;
3160a9de9248SMarcel Holtmann 
3161a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3162a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3163a9de9248SMarcel Holtmann 		break;
3164a9de9248SMarcel Holtmann 
3165a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3166a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3167a9de9248SMarcel Holtmann 		break;
3168a9de9248SMarcel Holtmann 
316904837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
317004837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
317104837f64SMarcel Holtmann 		break;
317204837f64SMarcel Holtmann 
3173a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3174a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
31751da177e4SLinus Torvalds 		break;
31761da177e4SLinus Torvalds 
31770493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
31780493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
31790493684eSMarcel Holtmann 		break;
31800493684eSMarcel Holtmann 
318103b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
318203b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
318303b555e1SJohan Hedberg 		break;
318403b555e1SJohan Hedberg 
3185a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3186a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3187a5c29683SJohan Hedberg 		break;
3188a5c29683SJohan Hedberg 
31891143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
31901143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
31911143d458SBrian Gix 		break;
31921143d458SBrian Gix 
31930493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
31940493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
31950493684eSMarcel Holtmann 		break;
31960493684eSMarcel Holtmann 
319741a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
319841a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
319941a96212SMarcel Holtmann 		break;
320041a96212SMarcel Holtmann 
3201fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3202fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3203fcd89c09SVille Tervo 		break;
3204fcd89c09SVille Tervo 
32052763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
32062763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
32072763eda6SSzymon Janc 		break;
32082763eda6SSzymon Janc 
32091da177e4SLinus Torvalds 	default:
3210a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
32111da177e4SLinus Torvalds 		break;
32121da177e4SLinus Torvalds 	}
32131da177e4SLinus Torvalds 
32141da177e4SLinus Torvalds 	kfree_skb(skb);
32151da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
32161da177e4SLinus Torvalds }
32171da177e4SLinus Torvalds 
32181da177e4SLinus Torvalds /* Generate internal stack event */
32191da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
32201da177e4SLinus Torvalds {
32211da177e4SLinus Torvalds 	struct hci_event_hdr *hdr;
32221da177e4SLinus Torvalds 	struct hci_ev_stack_internal *ev;
32231da177e4SLinus Torvalds 	struct sk_buff *skb;
32241da177e4SLinus Torvalds 
32251da177e4SLinus Torvalds 	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
32261da177e4SLinus Torvalds 	if (!skb)
32271da177e4SLinus Torvalds 		return;
32281da177e4SLinus Torvalds 
32291da177e4SLinus Torvalds 	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
32301da177e4SLinus Torvalds 	hdr->evt  = HCI_EV_STACK_INTERNAL;
32311da177e4SLinus Torvalds 	hdr->plen = sizeof(*ev) + dlen;
32321da177e4SLinus Torvalds 
32331da177e4SLinus Torvalds 	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
32341da177e4SLinus Torvalds 	ev->type = type;
32351da177e4SLinus Torvalds 	memcpy(ev->data, data, dlen);
32361da177e4SLinus Torvalds 
3237576c7d85SMarcel Holtmann 	bt_cb(skb)->incoming = 1;
3238a61bbcf2SPatrick McHardy 	__net_timestamp(skb);
3239576c7d85SMarcel Holtmann 
32400d48d939SMarcel Holtmann 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
32411da177e4SLinus Torvalds 	skb->dev = (void *) hdev;
3242eec8d2bcSJohan Hedberg 	hci_send_to_sock(hdev, skb, NULL);
32431da177e4SLinus Torvalds 	kfree_skb(skb);
32441da177e4SLinus Torvalds }
3245e6100a25SAndre Guedes 
3246669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644);
3247e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support");
3248