xref: /openbmc/linux/net/bluetooth/hci_event.c (revision db99b5fc)
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 <net/sock.h>
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds #include <asm/system.h>
4170f23020SAndrei Emeltchenko #include <linux/uaccess.h>
421da177e4SLinus Torvalds #include <asm/unaligned.h>
431da177e4SLinus Torvalds 
441da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
451da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds /* Handle HCI Event packets */
481da177e4SLinus Torvalds 
49a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
501da177e4SLinus Torvalds {
51a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
521da177e4SLinus Torvalds 
53a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
541da177e4SLinus Torvalds 
55e6d465cbSAndre Guedes 	if (status) {
56e6d465cbSAndre Guedes 		hci_dev_lock(hdev);
57e6d465cbSAndre Guedes 		mgmt_stop_discovery_failed(hdev, status);
58e6d465cbSAndre Guedes 		hci_dev_unlock(hdev);
59a9de9248SMarcel Holtmann 		return;
60e6d465cbSAndre Guedes 	}
611da177e4SLinus Torvalds 
6289352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
6389352e7dSAndre Guedes 
6456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
65ff9ef578SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
6656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
67a9de9248SMarcel Holtmann 
6823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
69a9de9248SMarcel Holtmann 
70a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
711da177e4SLinus Torvalds }
726bd57416SMarcel Holtmann 
73a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
741da177e4SLinus Torvalds {
75a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
76a9de9248SMarcel Holtmann 
77a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
78a9de9248SMarcel Holtmann 
79a9de9248SMarcel Holtmann 	if (status)
80a9de9248SMarcel Holtmann 		return;
81a9de9248SMarcel Holtmann 
82a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
83a9de9248SMarcel Holtmann }
84a9de9248SMarcel Holtmann 
85a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
86a9de9248SMarcel Holtmann {
87a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
88a9de9248SMarcel Holtmann }
89a9de9248SMarcel Holtmann 
90a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
91a9de9248SMarcel Holtmann {
92a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
931da177e4SLinus Torvalds 	struct hci_conn *conn;
941da177e4SLinus Torvalds 
95a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
961da177e4SLinus Torvalds 
97a9de9248SMarcel Holtmann 	if (rp->status)
98a9de9248SMarcel Holtmann 		return;
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1011da177e4SLinus Torvalds 
102a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1031da177e4SLinus Torvalds 	if (conn) {
104a9de9248SMarcel Holtmann 		if (rp->role)
1051da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1061da177e4SLinus Torvalds 		else
1071da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1081da177e4SLinus Torvalds 	}
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
111a9de9248SMarcel Holtmann }
1121da177e4SLinus Torvalds 
113e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
114e4e8e37cSMarcel Holtmann {
115e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
116e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
117e4e8e37cSMarcel Holtmann 
118e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
119e4e8e37cSMarcel Holtmann 
120e4e8e37cSMarcel Holtmann 	if (rp->status)
121e4e8e37cSMarcel Holtmann 		return;
122e4e8e37cSMarcel Holtmann 
123e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
124e4e8e37cSMarcel Holtmann 
125e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
126e4e8e37cSMarcel Holtmann 	if (conn)
127e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
128e4e8e37cSMarcel Holtmann 
129e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
130e4e8e37cSMarcel Holtmann }
131e4e8e37cSMarcel Holtmann 
132a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
133a9de9248SMarcel Holtmann {
134a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
135a9de9248SMarcel Holtmann 	struct hci_conn *conn;
136a9de9248SMarcel Holtmann 	void *sent;
137a9de9248SMarcel Holtmann 
138a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
139a9de9248SMarcel Holtmann 
140a9de9248SMarcel Holtmann 	if (rp->status)
141a9de9248SMarcel Holtmann 		return;
142a9de9248SMarcel Holtmann 
143a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14404837f64SMarcel Holtmann 	if (!sent)
145a9de9248SMarcel Holtmann 		return;
14604837f64SMarcel Holtmann 
14704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14804837f64SMarcel Holtmann 
149a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
150e4e8e37cSMarcel Holtmann 	if (conn)
15183985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15204837f64SMarcel Holtmann 
15304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1541da177e4SLinus Torvalds }
1551da177e4SLinus Torvalds 
156e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
157e4e8e37cSMarcel Holtmann {
158e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
159e4e8e37cSMarcel Holtmann 
160e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
161e4e8e37cSMarcel Holtmann 
162e4e8e37cSMarcel Holtmann 	if (rp->status)
163e4e8e37cSMarcel Holtmann 		return;
164e4e8e37cSMarcel Holtmann 
165e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
166e4e8e37cSMarcel Holtmann }
167e4e8e37cSMarcel Holtmann 
168e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
169e4e8e37cSMarcel Holtmann {
170e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
171e4e8e37cSMarcel Holtmann 	void *sent;
172e4e8e37cSMarcel Holtmann 
173e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
174e4e8e37cSMarcel Holtmann 
175e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
176e4e8e37cSMarcel Holtmann 	if (!sent)
177e4e8e37cSMarcel Holtmann 		return;
178e4e8e37cSMarcel Holtmann 
179e4e8e37cSMarcel Holtmann 	if (!status)
180e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
181e4e8e37cSMarcel Holtmann 
18223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
183e4e8e37cSMarcel Holtmann }
184e4e8e37cSMarcel Holtmann 
185a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1861da177e4SLinus Torvalds {
187a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
188a9de9248SMarcel Holtmann 
189a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
190a9de9248SMarcel Holtmann 
19110572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19210572132SGustavo F. Padovan 
19323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
194d23264a8SAndre Guedes 
195a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
196a297e97cSJohan Hedberg 	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN));
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 
21256e5cb86SJohan Hedberg 	if (status == 0)
2131f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
21456e5cb86SJohan Hedberg 
215f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
216f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
217f51d5b24SJohan 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 
230db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2311f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
232a9de9248SMarcel Holtmann }
233a9de9248SMarcel Holtmann 
234a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
235a9de9248SMarcel Holtmann {
236a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
237a9de9248SMarcel Holtmann 	void *sent;
238a9de9248SMarcel Holtmann 
239a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
240a9de9248SMarcel Holtmann 
241a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
242a9de9248SMarcel Holtmann 	if (!sent)
243a9de9248SMarcel Holtmann 		return;
2441da177e4SLinus Torvalds 
2451da177e4SLinus Torvalds 	if (!status) {
246a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
247a9de9248SMarcel Holtmann 
2481da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2491da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2501da177e4SLinus Torvalds 		else
2511da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2521da177e4SLinus Torvalds 	}
253a9de9248SMarcel Holtmann 
25433ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
25533ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
25633ef95edSJohan Hedberg 
25723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
258a9de9248SMarcel Holtmann }
2591da177e4SLinus Torvalds 
260a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
261a9de9248SMarcel Holtmann {
262a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
263a9de9248SMarcel Holtmann 	void *sent;
264a9de9248SMarcel Holtmann 
265a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
266a9de9248SMarcel Holtmann 
267a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2681da177e4SLinus Torvalds 	if (!sent)
269a9de9248SMarcel Holtmann 		return;
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds 	if (!status) {
272a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
273a9de9248SMarcel Holtmann 
2741da177e4SLinus Torvalds 		if (param)
2751da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2761da177e4SLinus Torvalds 		else
2771da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2781da177e4SLinus Torvalds 	}
279a9de9248SMarcel Holtmann 
28023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2811da177e4SLinus Torvalds }
2821da177e4SLinus Torvalds 
283a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
284a9de9248SMarcel Holtmann {
28536f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28636f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
287a9de9248SMarcel Holtmann 	void *sent;
2881da177e4SLinus Torvalds 
289a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
290a9de9248SMarcel Holtmann 
291a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2921da177e4SLinus Torvalds 	if (!sent)
293a9de9248SMarcel Holtmann 		return;
2941da177e4SLinus Torvalds 
29536f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
296a9de9248SMarcel Holtmann 
29756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29856e5cb86SJohan Hedberg 
2992d7cee58SJohan Hedberg 	if (status != 0) {
300744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3012d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3022d7cee58SJohan Hedberg 		goto done;
3032d7cee58SJohan Hedberg 	}
3042d7cee58SJohan Hedberg 
3059fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3069fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
307a9de9248SMarcel Holtmann 
30873f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3091da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3109fbcbb45SJohan Hedberg 		if (!old_iscan)
311744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31216ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
31316ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31416ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31516ab91abSJohan Hedberg 									to);
31616ab91abSJohan Hedberg 		}
3179fbcbb45SJohan Hedberg 	} else if (old_iscan)
318744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3191da177e4SLinus Torvalds 
3209fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3211da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3229fbcbb45SJohan Hedberg 		if (!old_pscan)
323744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3249fbcbb45SJohan Hedberg 	} else if (old_pscan)
325744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
326a9de9248SMarcel Holtmann 
32736f7fc7eSJohan Hedberg done:
32856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
32923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
332a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
333a9de9248SMarcel Holtmann {
334a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
335a9de9248SMarcel Holtmann 
336a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
337a9de9248SMarcel Holtmann 
338a9de9248SMarcel Holtmann 	if (rp->status)
339a9de9248SMarcel Holtmann 		return;
340a9de9248SMarcel Holtmann 
341a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
344a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
345a9de9248SMarcel Holtmann }
346a9de9248SMarcel Holtmann 
347a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
348a9de9248SMarcel Holtmann {
349a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
350a9de9248SMarcel Holtmann 	void *sent;
351a9de9248SMarcel Holtmann 
352a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
353a9de9248SMarcel Holtmann 
354a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
355a9de9248SMarcel Holtmann 	if (!sent)
356a9de9248SMarcel Holtmann 		return;
357a9de9248SMarcel Holtmann 
3587f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3597f9a903cSMarcel Holtmann 
3607f9a903cSMarcel Holtmann 	if (status == 0)
361a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3627f9a903cSMarcel Holtmann 
3637f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3647f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3657f9a903cSMarcel Holtmann 
3667f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
367a9de9248SMarcel Holtmann }
368a9de9248SMarcel Holtmann 
369a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
370a9de9248SMarcel Holtmann {
371a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
372a9de9248SMarcel Holtmann 	__u16 setting;
373a9de9248SMarcel Holtmann 
374a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
375a9de9248SMarcel Holtmann 
376a9de9248SMarcel Holtmann 	if (rp->status)
377a9de9248SMarcel Holtmann 		return;
378a9de9248SMarcel Holtmann 
379a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
380a9de9248SMarcel Holtmann 
381a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
382a9de9248SMarcel Holtmann 		return;
383a9de9248SMarcel Holtmann 
384a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
387a9de9248SMarcel Holtmann 
3883c54711cSGustavo F. Padovan 	if (hdev->notify)
389a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
390a9de9248SMarcel Holtmann }
391a9de9248SMarcel Holtmann 
392a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
393a9de9248SMarcel Holtmann {
394a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
395f383f275SMarcel Holtmann 	__u16 setting;
396a9de9248SMarcel Holtmann 	void *sent;
397a9de9248SMarcel Holtmann 
398a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
399a9de9248SMarcel Holtmann 
400f383f275SMarcel Holtmann 	if (status)
401f383f275SMarcel Holtmann 		return;
402f383f275SMarcel Holtmann 
403a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
404a9de9248SMarcel Holtmann 	if (!sent)
405a9de9248SMarcel Holtmann 		return;
406a9de9248SMarcel Holtmann 
407f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4081da177e4SLinus Torvalds 
409f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
410f383f275SMarcel Holtmann 		return;
411f383f275SMarcel Holtmann 
4121da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4131da177e4SLinus Torvalds 
414a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4151da177e4SLinus Torvalds 
4163c54711cSGustavo F. Padovan 	if (hdev->notify)
4171da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4181da177e4SLinus Torvalds }
4191da177e4SLinus Torvalds 
420a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4211da177e4SLinus Torvalds {
422a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4231da177e4SLinus Torvalds 
424a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4251da177e4SLinus Torvalds 
42623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4271143e5a6SMarcel Holtmann }
4281143e5a6SMarcel Holtmann 
429333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
430333140b5SMarcel Holtmann {
431333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
432333140b5SMarcel Holtmann 	void *sent;
433333140b5SMarcel Holtmann 
434333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
435333140b5SMarcel Holtmann 
436333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
437333140b5SMarcel Holtmann 	if (!sent)
438333140b5SMarcel Holtmann 		return;
439333140b5SMarcel Holtmann 
440c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
441c0ecddc2SJohan Hedberg 		mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
442c0ecddc2SJohan Hedberg 	else if (!status) {
44384bde9d6SJohan Hedberg 		if (*((u8 *) sent))
44484bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
44584bde9d6SJohan Hedberg 		else
44684bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
447c0ecddc2SJohan Hedberg 	}
448333140b5SMarcel Holtmann }
449333140b5SMarcel Holtmann 
450d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
451d5859e22SJohan Hedberg {
452d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
453d5859e22SJohan Hedberg 		return 2;
454d5859e22SJohan Hedberg 
455d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
456d5859e22SJohan Hedberg 		return 1;
457d5859e22SJohan Hedberg 
458d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
459d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
460d5859e22SJohan Hedberg 		return 1;
461d5859e22SJohan Hedberg 
462d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
463d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
464d5859e22SJohan Hedberg 			return 1;
465d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
466d5859e22SJohan Hedberg 			return 1;
467d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
468d5859e22SJohan Hedberg 			return 1;
469d5859e22SJohan Hedberg 	}
470d5859e22SJohan Hedberg 
471d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
472d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
473d5859e22SJohan Hedberg 		return 1;
474d5859e22SJohan Hedberg 
475d5859e22SJohan Hedberg 	return 0;
476d5859e22SJohan Hedberg }
477d5859e22SJohan Hedberg 
478d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
479d5859e22SJohan Hedberg {
480d5859e22SJohan Hedberg 	u8 mode;
481d5859e22SJohan Hedberg 
482d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
483d5859e22SJohan Hedberg 
484d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
485d5859e22SJohan Hedberg }
486d5859e22SJohan Hedberg 
487d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
488d5859e22SJohan Hedberg {
489d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
490d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
491d5859e22SJohan Hedberg 	 * command otherwise */
492d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
493d5859e22SJohan Hedberg 
4946de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
4956de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
4965a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
4976de6c18dSVille Tervo 		return;
4986de6c18dSVille Tervo 
499d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
500d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
501d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
502d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
503d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
504d5859e22SJohan Hedberg 
505d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
506d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
507d5859e22SJohan Hedberg 
508d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
509d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
510d5859e22SJohan Hedberg 
511d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
512d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
513d5859e22SJohan Hedberg 
514d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
515d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
516d5859e22SJohan Hedberg 
517d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
518d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
519d5859e22SJohan Hedberg 
520d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
521d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
522d5859e22SJohan Hedberg 
523d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
524d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
525d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
526d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
527d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
528d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
529d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
530d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
531d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
532d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
533d5859e22SJohan Hedberg 					 * Features Notification */
534d5859e22SJohan Hedberg 	}
535d5859e22SJohan Hedberg 
536d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
537d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
538d5859e22SJohan Hedberg 
539d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
540d5859e22SJohan Hedberg }
541d5859e22SJohan Hedberg 
542e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
543e6100a25SAndre Guedes {
544e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
545e6100a25SAndre Guedes 
546e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
547e6100a25SAndre Guedes 
54806199cf8SJohan Hedberg 	if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
549e6100a25SAndre Guedes 		cp.le = 1;
550e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
551e6100a25SAndre Guedes 	}
552e6100a25SAndre Guedes 
553e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
554e6100a25SAndre Guedes }
555e6100a25SAndre Guedes 
556d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
557d5859e22SJohan Hedberg {
558e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
559e61ef499SAndrei Emeltchenko 		return;
560e61ef499SAndrei Emeltchenko 
561d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
562d5859e22SJohan Hedberg 
563d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
564d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
565d5859e22SJohan Hedberg 
56654d04dbbSJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
56754d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
568d5859e22SJohan Hedberg 			u8 mode = 0x01;
56954d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
57054d04dbbSJohan Hedberg 							sizeof(mode), &mode);
57154d04dbbSJohan Hedberg 		} else {
57254d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
57354d04dbbSJohan Hedberg 
57454d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
57554d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
57654d04dbbSJohan Hedberg 
57754d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
57854d04dbbSJohan Hedberg 		}
579d5859e22SJohan Hedberg 	}
580d5859e22SJohan Hedberg 
581d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
582d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
583d5859e22SJohan Hedberg 
584d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
585d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
586971e3a4bSAndre Guedes 
587971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
588971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
589971e3a4bSAndre Guedes 
590971e3a4bSAndre Guedes 		cp.page = 0x01;
591971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
592971e3a4bSAndre Guedes 							sizeof(cp), &cp);
593971e3a4bSAndre Guedes 	}
594e6100a25SAndre Guedes 
59547990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
59647990ea0SJohan Hedberg 		u8 enable = 1;
59747990ea0SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
59847990ea0SJohan Hedberg 						sizeof(enable), &enable);
59947990ea0SJohan Hedberg 	}
60047990ea0SJohan Hedberg 
601e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
602e6100a25SAndre Guedes 		hci_set_le_support(hdev);
603d5859e22SJohan Hedberg }
604d5859e22SJohan Hedberg 
605a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
606a9de9248SMarcel Holtmann {
607a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6081143e5a6SMarcel Holtmann 
609a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
6101143e5a6SMarcel Holtmann 
611a9de9248SMarcel Holtmann 	if (rp->status)
612a9de9248SMarcel Holtmann 		return;
6131143e5a6SMarcel Holtmann 
614a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
615e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
616d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
617e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
618d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6191da177e4SLinus Torvalds 
620a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
621a9de9248SMarcel Holtmann 					hdev->manufacturer,
622a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
623d5859e22SJohan Hedberg 
624d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
625d5859e22SJohan Hedberg 		hci_setup(hdev);
626d5859e22SJohan Hedberg }
627d5859e22SJohan Hedberg 
628d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
629d5859e22SJohan Hedberg {
630d5859e22SJohan Hedberg 	u16 link_policy = 0;
631d5859e22SJohan Hedberg 
632d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
633d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
634d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
635d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
636d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
637d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
638d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
639d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
640d5859e22SJohan Hedberg 
641d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
642d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
643d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6441da177e4SLinus Torvalds }
6451da177e4SLinus Torvalds 
646a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
647a9de9248SMarcel Holtmann {
648a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
649a9de9248SMarcel Holtmann 
650a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
651a9de9248SMarcel Holtmann 
652a9de9248SMarcel Holtmann 	if (rp->status)
653d5859e22SJohan Hedberg 		goto done;
654a9de9248SMarcel Holtmann 
655a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
656d5859e22SJohan Hedberg 
657d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
658d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
659d5859e22SJohan Hedberg 
660d5859e22SJohan Hedberg done:
661d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
662a9de9248SMarcel Holtmann }
663a9de9248SMarcel Holtmann 
664a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
665a9de9248SMarcel Holtmann {
666a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
667a9de9248SMarcel Holtmann 
668a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
669a9de9248SMarcel Holtmann 
670a9de9248SMarcel Holtmann 	if (rp->status)
671a9de9248SMarcel Holtmann 		return;
672a9de9248SMarcel Holtmann 
673a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6741da177e4SLinus Torvalds 
6751da177e4SLinus Torvalds 	/* Adjust default settings according to features
6761da177e4SLinus Torvalds 	 * supported by device. */
677a9de9248SMarcel Holtmann 
6781da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6791da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6801da177e4SLinus Torvalds 
6811da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6821da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6831da177e4SLinus Torvalds 
6845b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6851da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6865b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6875b7f9909SMarcel Holtmann 	}
6881da177e4SLinus Torvalds 
6895b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6901da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6915b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6925b7f9909SMarcel Holtmann 	}
6935b7f9909SMarcel Holtmann 
6945b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6955b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6965b7f9909SMarcel Holtmann 
6975b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6985b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6995b7f9909SMarcel Holtmann 
7005b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
7015b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
7021da177e4SLinus Torvalds 
703efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
704efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
705efc7688bSMarcel Holtmann 
706efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
707efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
708efc7688bSMarcel Holtmann 
709efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
710efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
711efc7688bSMarcel Holtmann 
712a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
713a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
714a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
715a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
716a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7171da177e4SLinus Torvalds }
7181da177e4SLinus Torvalds 
719971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
720971e3a4bSAndre Guedes 							struct sk_buff *skb)
721971e3a4bSAndre Guedes {
722971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
723971e3a4bSAndre Guedes 
724971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
725971e3a4bSAndre Guedes 
726971e3a4bSAndre Guedes 	if (rp->status)
727971e3a4bSAndre Guedes 		return;
728971e3a4bSAndre Guedes 
729b5b32b65SAndre Guedes 	switch (rp->page) {
730b5b32b65SAndre Guedes 	case 0:
731b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
732b5b32b65SAndre Guedes 		break;
733b5b32b65SAndre Guedes 	case 1:
73459e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
735b5b32b65SAndre Guedes 		break;
736b5b32b65SAndre Guedes 	}
737971e3a4bSAndre Guedes 
738971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
739971e3a4bSAndre Guedes }
740971e3a4bSAndre Guedes 
7411e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7421e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7431e89cffbSAndrei Emeltchenko {
7441e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7451e89cffbSAndrei Emeltchenko 
7461e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7471e89cffbSAndrei Emeltchenko 
7481e89cffbSAndrei Emeltchenko 	if (rp->status)
7491e89cffbSAndrei Emeltchenko 		return;
7501e89cffbSAndrei Emeltchenko 
7511e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7521e89cffbSAndrei Emeltchenko 
7531e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7541e89cffbSAndrei Emeltchenko }
7551e89cffbSAndrei Emeltchenko 
756a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
757a9de9248SMarcel Holtmann {
758a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
759a9de9248SMarcel Holtmann 
760a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
761a9de9248SMarcel Holtmann 
762a9de9248SMarcel Holtmann 	if (rp->status)
763a9de9248SMarcel Holtmann 		return;
764a9de9248SMarcel Holtmann 
765a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
766a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
767a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
768a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
769da1f5198SMarcel Holtmann 
770da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
771da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
772da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
773da1f5198SMarcel Holtmann 	}
774da1f5198SMarcel Holtmann 
775da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
776da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7771da177e4SLinus Torvalds 
778a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
779a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
780a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7811da177e4SLinus Torvalds }
7821da177e4SLinus Torvalds 
783a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
784a9de9248SMarcel Holtmann {
785a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7861da177e4SLinus Torvalds 
787a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
788a9de9248SMarcel Holtmann 
789a9de9248SMarcel Holtmann 	if (!rp->status)
790a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
791a9de9248SMarcel Holtmann 
79223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
79323bb5763SJohan Hedberg }
79423bb5763SJohan Hedberg 
795350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
796350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
797350ee4cfSAndrei Emeltchenko {
798350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
799350ee4cfSAndrei Emeltchenko 
800350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
801350ee4cfSAndrei Emeltchenko 
802350ee4cfSAndrei Emeltchenko 	if (rp->status)
803350ee4cfSAndrei Emeltchenko 		return;
804350ee4cfSAndrei Emeltchenko 
805350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
806350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
807350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
808350ee4cfSAndrei Emeltchenko 
809350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
810350ee4cfSAndrei Emeltchenko 
811350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
812350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
813350ee4cfSAndrei Emeltchenko 
814350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
815350ee4cfSAndrei Emeltchenko }
816350ee4cfSAndrei Emeltchenko 
81723bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
81823bb5763SJohan Hedberg {
81923bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
82023bb5763SJohan Hedberg 
82123bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
82223bb5763SJohan Hedberg 
82323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8241da177e4SLinus Torvalds }
8251da177e4SLinus Torvalds 
826928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
827928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
828928abaa7SAndrei Emeltchenko {
829928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
830928abaa7SAndrei Emeltchenko 
831928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
832928abaa7SAndrei Emeltchenko 
833928abaa7SAndrei Emeltchenko 	if (rp->status)
834928abaa7SAndrei Emeltchenko 		return;
835928abaa7SAndrei Emeltchenko 
836928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
837928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
838928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
839928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
840928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
841928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
842928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
843928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
844928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
845928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
846928abaa7SAndrei Emeltchenko 
847928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
848928abaa7SAndrei Emeltchenko }
849928abaa7SAndrei Emeltchenko 
850b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
851b0916ea0SJohan Hedberg 							struct sk_buff *skb)
852b0916ea0SJohan Hedberg {
853b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
854b0916ea0SJohan Hedberg 
855b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
856b0916ea0SJohan Hedberg 
857b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
858b0916ea0SJohan Hedberg }
859b0916ea0SJohan Hedberg 
860d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
861d5859e22SJohan Hedberg {
862d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
863d5859e22SJohan Hedberg 
864d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
865d5859e22SJohan Hedberg 
866d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
867d5859e22SJohan Hedberg }
868d5859e22SJohan Hedberg 
869d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
870d5859e22SJohan Hedberg 							struct sk_buff *skb)
871d5859e22SJohan Hedberg {
872d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
873d5859e22SJohan Hedberg 
874d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
875d5859e22SJohan Hedberg 
876d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
877d5859e22SJohan Hedberg }
878d5859e22SJohan Hedberg 
879d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
880d5859e22SJohan Hedberg 							struct sk_buff *skb)
881d5859e22SJohan Hedberg {
882d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
883d5859e22SJohan Hedberg 
884d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
885d5859e22SJohan Hedberg 
886d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
887d5859e22SJohan Hedberg }
888d5859e22SJohan Hedberg 
889d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
890d5859e22SJohan Hedberg {
891d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
892d5859e22SJohan Hedberg 
893d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
894d5859e22SJohan Hedberg 
895d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
896d5859e22SJohan Hedberg }
897d5859e22SJohan Hedberg 
898980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
899980e1a53SJohan Hedberg {
900980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
901980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
902980e1a53SJohan Hedberg 	struct hci_conn *conn;
903980e1a53SJohan Hedberg 
904980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
905980e1a53SJohan Hedberg 
90656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
90756e5cb86SJohan Hedberg 
908a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
909744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
910980e1a53SJohan Hedberg 
911980e1a53SJohan Hedberg 	if (rp->status != 0)
91256e5cb86SJohan Hedberg 		goto unlock;
913980e1a53SJohan Hedberg 
914980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
915980e1a53SJohan Hedberg 	if (!cp)
91656e5cb86SJohan Hedberg 		goto unlock;
917980e1a53SJohan Hedberg 
918980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
919980e1a53SJohan Hedberg 	if (conn)
920980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
92156e5cb86SJohan Hedberg 
92256e5cb86SJohan Hedberg unlock:
92356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
924980e1a53SJohan Hedberg }
925980e1a53SJohan Hedberg 
926980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
927980e1a53SJohan Hedberg {
928980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
929980e1a53SJohan Hedberg 
930980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
931980e1a53SJohan Hedberg 
93256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
93356e5cb86SJohan Hedberg 
934a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
935744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
936980e1a53SJohan Hedberg 								rp->status);
93756e5cb86SJohan Hedberg 
93856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
939980e1a53SJohan Hedberg }
94056e5cb86SJohan Hedberg 
9416ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9426ed58ec5SVille Tervo 				       struct sk_buff *skb)
9436ed58ec5SVille Tervo {
9446ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9456ed58ec5SVille Tervo 
9466ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9476ed58ec5SVille Tervo 
9486ed58ec5SVille Tervo 	if (rp->status)
9496ed58ec5SVille Tervo 		return;
9506ed58ec5SVille Tervo 
9516ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9526ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9536ed58ec5SVille Tervo 
9546ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9556ed58ec5SVille Tervo 
9566ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9576ed58ec5SVille Tervo 
9586ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9596ed58ec5SVille Tervo }
960980e1a53SJohan Hedberg 
961a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
962a5c29683SJohan Hedberg {
963a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
964a5c29683SJohan Hedberg 
965a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
966a5c29683SJohan Hedberg 
96756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96856e5cb86SJohan Hedberg 
969a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
970272d90dfSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
971272d90dfSJohan Hedberg 								0, rp->status);
97256e5cb86SJohan Hedberg 
97356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
974a5c29683SJohan Hedberg }
975a5c29683SJohan Hedberg 
976a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
977a5c29683SJohan Hedberg 							struct sk_buff *skb)
978a5c29683SJohan Hedberg {
979a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
980a5c29683SJohan Hedberg 
981a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
982a5c29683SJohan Hedberg 
98356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
98456e5cb86SJohan Hedberg 
985a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
986744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
987272d90dfSJohan Hedberg 								ACL_LINK, 0,
988a5c29683SJohan Hedberg 								rp->status);
98956e5cb86SJohan Hedberg 
99056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
991a5c29683SJohan Hedberg }
992a5c29683SJohan Hedberg 
9931143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9941143d458SBrian Gix {
9951143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9961143d458SBrian Gix 
9971143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9981143d458SBrian Gix 
9991143d458SBrian Gix 	hci_dev_lock(hdev);
10001143d458SBrian Gix 
1001a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1002272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1003272d90dfSJohan Hedberg 								0, rp->status);
10041143d458SBrian Gix 
10051143d458SBrian Gix 	hci_dev_unlock(hdev);
10061143d458SBrian Gix }
10071143d458SBrian Gix 
10081143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10091143d458SBrian Gix 							struct sk_buff *skb)
10101143d458SBrian Gix {
10111143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10121143d458SBrian Gix 
10131143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10141143d458SBrian Gix 
10151143d458SBrian Gix 	hci_dev_lock(hdev);
10161143d458SBrian Gix 
1017a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10181143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
1019272d90dfSJohan Hedberg 								ACL_LINK, 0,
10201143d458SBrian Gix 								rp->status);
10211143d458SBrian Gix 
10221143d458SBrian Gix 	hci_dev_unlock(hdev);
10231143d458SBrian Gix }
10241143d458SBrian Gix 
1025c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1026c35938b2SSzymon Janc 							struct sk_buff *skb)
1027c35938b2SSzymon Janc {
1028c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1029c35938b2SSzymon Janc 
1030c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1031c35938b2SSzymon Janc 
103256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1033744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1034c35938b2SSzymon Janc 						rp->randomizer, rp->status);
103556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1036c35938b2SSzymon Janc }
1037c35938b2SSzymon Janc 
103807f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
103907f7fa5dSAndre Guedes {
104007f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
104107f7fa5dSAndre Guedes 
104207f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
10437ba8b4beSAndre Guedes 
10447ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
10453fd24153SAndre Guedes 
10463fd24153SAndre Guedes 	if (status) {
10473fd24153SAndre Guedes 		hci_dev_lock(hdev);
10483fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
10493fd24153SAndre Guedes 		hci_dev_unlock(hdev);
10503fd24153SAndre Guedes 		return;
10513fd24153SAndre Guedes 	}
105207f7fa5dSAndre Guedes }
105307f7fa5dSAndre Guedes 
1054eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1055eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1056eb9d91f5SAndre Guedes {
1057eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1058eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1059eb9d91f5SAndre Guedes 
1060eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1061eb9d91f5SAndre Guedes 
1062eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1063eb9d91f5SAndre Guedes 	if (!cp)
1064eb9d91f5SAndre Guedes 		return;
1065eb9d91f5SAndre Guedes 
106668a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
106768a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
10687ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
10697ba8b4beSAndre Guedes 
10703fd24153SAndre Guedes 		if (status) {
10713fd24153SAndre Guedes 			hci_dev_lock(hdev);
10723fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
10733fd24153SAndre Guedes 			hci_dev_unlock(hdev);
10747ba8b4beSAndre Guedes 			return;
10753fd24153SAndre Guedes 		}
10767ba8b4beSAndre Guedes 
1077d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1078d23264a8SAndre Guedes 
1079db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1080a8f13c8cSAndre Guedes 
1081a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1082eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1083343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1084a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
108568a8aea4SAndrei Emeltchenko 		break;
108668a8aea4SAndrei Emeltchenko 
108768a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
10887ba8b4beSAndre Guedes 		if (status)
10897ba8b4beSAndre Guedes 			return;
10907ba8b4beSAndre Guedes 
1091d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1092d23264a8SAndre Guedes 
10935e0452c0SAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
10945e0452c0SAndre Guedes 
10955e0452c0SAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
10965e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
10975e0452c0SAndre Guedes 		} else {
1098c599008fSAndre Guedes 			hci_dev_lock(hdev);
1099c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1100c599008fSAndre Guedes 			hci_dev_unlock(hdev);
11015e0452c0SAndre Guedes 		}
1102c599008fSAndre Guedes 
110368a8aea4SAndrei Emeltchenko 		break;
110468a8aea4SAndrei Emeltchenko 
110568a8aea4SAndrei Emeltchenko 	default:
110668a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
110768a8aea4SAndrei Emeltchenko 		break;
110835815085SAndre Guedes 	}
1109eb9d91f5SAndre Guedes }
1110eb9d91f5SAndre Guedes 
1111a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1112a7a595f6SVinicius Costa Gomes {
1113a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1114a7a595f6SVinicius Costa Gomes 
1115a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1116a7a595f6SVinicius Costa Gomes 
1117a7a595f6SVinicius Costa Gomes 	if (rp->status)
1118a7a595f6SVinicius Costa Gomes 		return;
1119a7a595f6SVinicius Costa Gomes 
1120a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1121a7a595f6SVinicius Costa Gomes }
1122a7a595f6SVinicius Costa Gomes 
1123a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1124a7a595f6SVinicius Costa Gomes {
1125a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1126a7a595f6SVinicius Costa Gomes 
1127a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1128a7a595f6SVinicius Costa Gomes 
1129a7a595f6SVinicius Costa Gomes 	if (rp->status)
1130a7a595f6SVinicius Costa Gomes 		return;
1131a7a595f6SVinicius Costa Gomes 
1132a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1133a7a595f6SVinicius Costa Gomes }
1134a7a595f6SVinicius Costa Gomes 
1135f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1136f9b49306SAndre Guedes 							struct sk_buff *skb)
1137f9b49306SAndre Guedes {
1138f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
113906199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1140f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1141f9b49306SAndre Guedes 
1142f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1143f9b49306SAndre Guedes 
114406199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
114506199cf8SJohan Hedberg 	if (sent && test_bit(HCI_MGMT, &hdev->dev_flags))
114606199cf8SJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
114706199cf8SJohan Hedberg 
1148f9b49306SAndre Guedes 	if (status)
1149f9b49306SAndre Guedes 		return;
1150f9b49306SAndre Guedes 
1151f9b49306SAndre Guedes 	cp.page = 0x01;
1152f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1153f9b49306SAndre Guedes }
1154f9b49306SAndre Guedes 
1155a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1156a9de9248SMarcel Holtmann {
1157a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1158a9de9248SMarcel Holtmann 
1159a9de9248SMarcel Holtmann 	if (status) {
116023bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1161a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
116256e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1163a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11647a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
116556e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1166314b2381SJohan Hedberg 		return;
1167314b2381SJohan Hedberg 	}
1168314b2381SJohan Hedberg 
116989352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
117089352e7dSAndre Guedes 
117156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1172343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
117356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1174a9de9248SMarcel Holtmann }
1175a9de9248SMarcel Holtmann 
11761da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11771da177e4SLinus Torvalds {
1178a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11791da177e4SLinus Torvalds 	struct hci_conn *conn;
11801da177e4SLinus Torvalds 
1181a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1182a9de9248SMarcel Holtmann 
1183a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11841da177e4SLinus Torvalds 	if (!cp)
11851da177e4SLinus Torvalds 		return;
11861da177e4SLinus Torvalds 
11871da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11881da177e4SLinus Torvalds 
11891da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11901da177e4SLinus Torvalds 
1191a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds 	if (status) {
11941da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11954c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11961da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11971da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11981da177e4SLinus Torvalds 				hci_conn_del(conn);
11994c67bc74SMarcel Holtmann 			} else
12004c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
12011da177e4SLinus Torvalds 		}
12021da177e4SLinus Torvalds 	} else {
12031da177e4SLinus Torvalds 		if (!conn) {
12041da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
12051da177e4SLinus Torvalds 			if (conn) {
1206a0c808b3SJohan Hedberg 				conn->out = true;
12071da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
12081da177e4SLinus Torvalds 			} else
1209893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12101da177e4SLinus Torvalds 		}
12111da177e4SLinus Torvalds 	}
12121da177e4SLinus Torvalds 
12131da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12141da177e4SLinus Torvalds }
12151da177e4SLinus Torvalds 
1216a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12171da177e4SLinus Torvalds {
1218a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12191da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12201da177e4SLinus Torvalds 	__u16 handle;
12211da177e4SLinus Torvalds 
1222b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1223b6a0dc82SMarcel Holtmann 
1224a9de9248SMarcel Holtmann 	if (!status)
1225a9de9248SMarcel Holtmann 		return;
1226a9de9248SMarcel Holtmann 
1227a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12281da177e4SLinus Torvalds 	if (!cp)
1229a9de9248SMarcel Holtmann 		return;
12301da177e4SLinus Torvalds 
12311da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12321da177e4SLinus Torvalds 
1233a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
12341da177e4SLinus Torvalds 
12351da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12361da177e4SLinus Torvalds 
12371da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12385a08ecceSAndrei Emeltchenko 	if (acl) {
12395a08ecceSAndrei Emeltchenko 		sco = acl->link;
12405a08ecceSAndrei Emeltchenko 		if (sco) {
12411da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12421da177e4SLinus Torvalds 
12431da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12441da177e4SLinus Torvalds 			hci_conn_del(sco);
12451da177e4SLinus Torvalds 		}
12465a08ecceSAndrei Emeltchenko 	}
12471da177e4SLinus Torvalds 
12481da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12491da177e4SLinus Torvalds }
12501da177e4SLinus Torvalds 
1251f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1252f8558555SMarcel Holtmann {
1253f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1254f8558555SMarcel Holtmann 	struct hci_conn *conn;
1255f8558555SMarcel Holtmann 
1256f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1257f8558555SMarcel Holtmann 
1258f8558555SMarcel Holtmann 	if (!status)
1259f8558555SMarcel Holtmann 		return;
1260f8558555SMarcel Holtmann 
1261f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1262f8558555SMarcel Holtmann 	if (!cp)
1263f8558555SMarcel Holtmann 		return;
1264f8558555SMarcel Holtmann 
1265f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1266f8558555SMarcel Holtmann 
1267f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1268f8558555SMarcel Holtmann 	if (conn) {
1269f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1270f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1271f8558555SMarcel Holtmann 			hci_conn_put(conn);
1272f8558555SMarcel Holtmann 		}
1273f8558555SMarcel Holtmann 	}
1274f8558555SMarcel Holtmann 
1275f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1276f8558555SMarcel Holtmann }
1277f8558555SMarcel Holtmann 
1278f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1279f8558555SMarcel Holtmann {
1280f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1281f8558555SMarcel Holtmann 	struct hci_conn *conn;
1282f8558555SMarcel Holtmann 
1283f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1284f8558555SMarcel Holtmann 
1285f8558555SMarcel Holtmann 	if (!status)
1286f8558555SMarcel Holtmann 		return;
1287f8558555SMarcel Holtmann 
1288f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1289f8558555SMarcel Holtmann 	if (!cp)
1290f8558555SMarcel Holtmann 		return;
1291f8558555SMarcel Holtmann 
1292f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1293f8558555SMarcel Holtmann 
1294f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1295f8558555SMarcel Holtmann 	if (conn) {
1296f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1297f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1298f8558555SMarcel Holtmann 			hci_conn_put(conn);
1299f8558555SMarcel Holtmann 		}
1300f8558555SMarcel Holtmann 	}
1301f8558555SMarcel Holtmann 
1302f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1303f8558555SMarcel Holtmann }
1304f8558555SMarcel Holtmann 
1305127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1306392599b9SJohan Hedberg 							struct hci_conn *conn)
1307392599b9SJohan Hedberg {
1308392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1309392599b9SJohan Hedberg 		return 0;
1310392599b9SJohan Hedberg 
1311765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1312392599b9SJohan Hedberg 		return 0;
1313392599b9SJohan Hedberg 
1314392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1315e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1316aa64a8b5SJohan Hedberg 	if (!hci_conn_ssp_enabled(conn) &&
1317e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1318e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1319392599b9SJohan Hedberg 		return 0;
1320392599b9SJohan Hedberg 
1321392599b9SJohan Hedberg 	return 1;
1322392599b9SJohan Hedberg }
1323392599b9SJohan Hedberg 
132430dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
132530dc78e1SJohan Hedberg {
132630dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
132730dc78e1SJohan Hedberg 
132830dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
132930dc78e1SJohan Hedberg 
133030dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
133130dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
133230dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
133330dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
133430dc78e1SJohan Hedberg 
133530dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
133630dc78e1SJohan Hedberg }
133730dc78e1SJohan Hedberg 
1338b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
133930dc78e1SJohan Hedberg {
134030dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
134130dc78e1SJohan Hedberg 	struct inquiry_entry *e;
134230dc78e1SJohan Hedberg 
1343b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1344b644ba33SJohan Hedberg 		return false;
1345b644ba33SJohan Hedberg 
1346b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1347b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1348b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1349b644ba33SJohan Hedberg 		return true;
1350b644ba33SJohan Hedberg 	}
1351b644ba33SJohan Hedberg 
1352b644ba33SJohan Hedberg 	return false;
1353b644ba33SJohan Hedberg }
1354b644ba33SJohan Hedberg 
1355b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1356b644ba33SJohan Hedberg 					bdaddr_t *bdaddr, u8 *name, u8 name_len)
1357b644ba33SJohan Hedberg {
1358b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1359b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1360b644ba33SJohan Hedberg 
1361b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
1362b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00,
1363b644ba33SJohan Hedberg 					name, name_len, conn->dev_class);
1364b644ba33SJohan Hedberg 
1365b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1366b644ba33SJohan Hedberg 		return;
1367b644ba33SJohan Hedberg 
136830dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
136930dc78e1SJohan Hedberg 		goto discov_complete;
137030dc78e1SJohan Hedberg 
137130dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
137230dc78e1SJohan Hedberg 		return;
137330dc78e1SJohan Hedberg 
137430dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
137530dc78e1SJohan Hedberg 	if (e) {
137630dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
137730dc78e1SJohan Hedberg 		list_del(&e->list);
1378b644ba33SJohan Hedberg 		if (name)
1379b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1380b644ba33SJohan Hedberg 					e->data.rssi, name, name_len);
138130dc78e1SJohan Hedberg 	}
138230dc78e1SJohan Hedberg 
1383b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
138430dc78e1SJohan Hedberg 		return;
138530dc78e1SJohan Hedberg 
138630dc78e1SJohan Hedberg discov_complete:
138730dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
138830dc78e1SJohan Hedberg }
138930dc78e1SJohan Hedberg 
1390a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13911da177e4SLinus Torvalds {
1392127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1393127178d2SJohan Hedberg 	struct hci_conn *conn;
1394127178d2SJohan Hedberg 
1395a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1396127178d2SJohan Hedberg 
1397127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1398127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1399127178d2SJohan Hedberg 	if (!status)
1400127178d2SJohan Hedberg 		return;
1401127178d2SJohan Hedberg 
1402127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1403127178d2SJohan Hedberg 	if (!cp)
1404127178d2SJohan Hedberg 		return;
1405127178d2SJohan Hedberg 
1406127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1407127178d2SJohan Hedberg 
1408127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1409b644ba33SJohan Hedberg 
1410b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1411b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1412b644ba33SJohan Hedberg 
141379c6c70cSJohan Hedberg 	if (!conn)
141479c6c70cSJohan Hedberg 		goto unlock;
141579c6c70cSJohan Hedberg 
141679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
141779c6c70cSJohan Hedberg 		goto unlock;
141879c6c70cSJohan Hedberg 
141951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1420127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1421127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1422127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1423127178d2SJohan Hedberg 	}
1424127178d2SJohan Hedberg 
142579c6c70cSJohan Hedberg unlock:
1426127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1427a9de9248SMarcel Holtmann }
14281da177e4SLinus Torvalds 
1429769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1430769be974SMarcel Holtmann {
1431769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1432769be974SMarcel Holtmann 	struct hci_conn *conn;
1433769be974SMarcel Holtmann 
1434769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1435769be974SMarcel Holtmann 
1436769be974SMarcel Holtmann 	if (!status)
1437769be974SMarcel Holtmann 		return;
1438769be974SMarcel Holtmann 
1439769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1440769be974SMarcel Holtmann 	if (!cp)
1441769be974SMarcel Holtmann 		return;
1442769be974SMarcel Holtmann 
1443769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1444769be974SMarcel Holtmann 
1445769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1446769be974SMarcel Holtmann 	if (conn) {
1447769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1448769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1449769be974SMarcel Holtmann 			hci_conn_put(conn);
1450769be974SMarcel Holtmann 		}
1451769be974SMarcel Holtmann 	}
1452769be974SMarcel Holtmann 
1453769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1454769be974SMarcel Holtmann }
1455769be974SMarcel Holtmann 
1456769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1457769be974SMarcel Holtmann {
1458769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1459769be974SMarcel Holtmann 	struct hci_conn *conn;
1460769be974SMarcel Holtmann 
1461769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1462769be974SMarcel Holtmann 
1463769be974SMarcel Holtmann 	if (!status)
1464769be974SMarcel Holtmann 		return;
1465769be974SMarcel Holtmann 
1466769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1467769be974SMarcel Holtmann 	if (!cp)
1468769be974SMarcel Holtmann 		return;
1469769be974SMarcel Holtmann 
1470769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1471769be974SMarcel Holtmann 
1472769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1473769be974SMarcel Holtmann 	if (conn) {
1474769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1475769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1476769be974SMarcel Holtmann 			hci_conn_put(conn);
1477769be974SMarcel Holtmann 		}
1478769be974SMarcel Holtmann 	}
1479769be974SMarcel Holtmann 
1480769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1481769be974SMarcel Holtmann }
1482769be974SMarcel Holtmann 
1483a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1484a9de9248SMarcel Holtmann {
1485b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1486b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1487b6a0dc82SMarcel Holtmann 	__u16 handle;
1488b6a0dc82SMarcel Holtmann 
1489a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1490b6a0dc82SMarcel Holtmann 
1491b6a0dc82SMarcel Holtmann 	if (!status)
1492b6a0dc82SMarcel Holtmann 		return;
1493b6a0dc82SMarcel Holtmann 
1494b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1495b6a0dc82SMarcel Holtmann 	if (!cp)
1496b6a0dc82SMarcel Holtmann 		return;
1497b6a0dc82SMarcel Holtmann 
1498b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1499b6a0dc82SMarcel Holtmann 
1500b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1501b6a0dc82SMarcel Holtmann 
1502b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1503b6a0dc82SMarcel Holtmann 
1504b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15055a08ecceSAndrei Emeltchenko 	if (acl) {
15065a08ecceSAndrei Emeltchenko 		sco = acl->link;
15075a08ecceSAndrei Emeltchenko 		if (sco) {
1508b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1509b6a0dc82SMarcel Holtmann 
1510b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1511b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1512b6a0dc82SMarcel Holtmann 		}
15135a08ecceSAndrei Emeltchenko 	}
1514b6a0dc82SMarcel Holtmann 
1515b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1516a9de9248SMarcel Holtmann }
1517a9de9248SMarcel Holtmann 
1518a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1519a9de9248SMarcel Holtmann {
1520a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
152104837f64SMarcel Holtmann 	struct hci_conn *conn;
152204837f64SMarcel Holtmann 
1523a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1524a9de9248SMarcel Holtmann 
1525a9de9248SMarcel Holtmann 	if (!status)
1526a9de9248SMarcel Holtmann 		return;
1527a9de9248SMarcel Holtmann 
1528a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
152904837f64SMarcel Holtmann 	if (!cp)
1530a9de9248SMarcel Holtmann 		return;
153104837f64SMarcel Holtmann 
153204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
153304837f64SMarcel Holtmann 
153404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1535e73439d8SMarcel Holtmann 	if (conn) {
153651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
153704837f64SMarcel Holtmann 
153851a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1539e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1540e73439d8SMarcel Holtmann 	}
1541e73439d8SMarcel Holtmann 
154204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
154304837f64SMarcel Holtmann }
154404837f64SMarcel Holtmann 
1545a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1546a9de9248SMarcel Holtmann {
1547a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
154804837f64SMarcel Holtmann 	struct hci_conn *conn;
154904837f64SMarcel Holtmann 
1550a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1551a9de9248SMarcel Holtmann 
1552a9de9248SMarcel Holtmann 	if (!status)
1553a9de9248SMarcel Holtmann 		return;
1554a9de9248SMarcel Holtmann 
1555a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
155604837f64SMarcel Holtmann 	if (!cp)
1557a9de9248SMarcel Holtmann 		return;
155804837f64SMarcel Holtmann 
155904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
156004837f64SMarcel Holtmann 
156104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1562e73439d8SMarcel Holtmann 	if (conn) {
156351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
156404837f64SMarcel Holtmann 
156551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1566e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1567e73439d8SMarcel Holtmann 	}
1568e73439d8SMarcel Holtmann 
156904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
157004837f64SMarcel Holtmann }
157104837f64SMarcel Holtmann 
157288c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
157388c3df13SJohan Hedberg {
157488c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
157588c3df13SJohan Hedberg 	struct hci_conn *conn;
157688c3df13SJohan Hedberg 
157788c3df13SJohan Hedberg 	if (!status)
157888c3df13SJohan Hedberg 		return;
157988c3df13SJohan Hedberg 
158088c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
158188c3df13SJohan Hedberg 	if (!cp)
158288c3df13SJohan Hedberg 		return;
158388c3df13SJohan Hedberg 
158488c3df13SJohan Hedberg 	hci_dev_lock(hdev);
158588c3df13SJohan Hedberg 
158688c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
158788c3df13SJohan Hedberg 	if (conn)
158888c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
158988c3df13SJohan Hedberg 						conn->dst_type, status);
159088c3df13SJohan Hedberg 
159188c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
159288c3df13SJohan Hedberg }
159388c3df13SJohan Hedberg 
1594fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1595fcd89c09SVille Tervo {
1596fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1597fcd89c09SVille Tervo 	struct hci_conn *conn;
1598fcd89c09SVille Tervo 
1599fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1600fcd89c09SVille Tervo 
1601fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1602fcd89c09SVille Tervo 	if (!cp)
1603fcd89c09SVille Tervo 		return;
1604fcd89c09SVille Tervo 
1605fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1606fcd89c09SVille Tervo 
1607fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1608fcd89c09SVille Tervo 
1609fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1610fcd89c09SVille Tervo 		conn);
1611fcd89c09SVille Tervo 
1612fcd89c09SVille Tervo 	if (status) {
1613fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1614fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1615fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1616fcd89c09SVille Tervo 			hci_conn_del(conn);
1617fcd89c09SVille Tervo 		}
1618fcd89c09SVille Tervo 	} else {
1619fcd89c09SVille Tervo 		if (!conn) {
1620fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
162129b7988aSAndre Guedes 			if (conn) {
162229b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1623a0c808b3SJohan Hedberg 				conn->out = true;
162429b7988aSAndre Guedes 			} else {
1625fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1626fcd89c09SVille Tervo 			}
1627fcd89c09SVille Tervo 		}
162829b7988aSAndre Guedes 	}
1629fcd89c09SVille Tervo 
1630fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1631fcd89c09SVille Tervo }
1632fcd89c09SVille Tervo 
1633a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1634a7a595f6SVinicius Costa Gomes {
1635a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1636a7a595f6SVinicius Costa Gomes }
1637a7a595f6SVinicius Costa Gomes 
16381da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16391da177e4SLinus Torvalds {
16401da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
164130dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
164230dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16431da177e4SLinus Torvalds 
16441da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
16451da177e4SLinus Torvalds 
164623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16476bd57416SMarcel Holtmann 
1648a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
164989352e7dSAndre Guedes 
165089352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
165189352e7dSAndre Guedes 		return;
165289352e7dSAndre Guedes 
1653a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
165430dc78e1SJohan Hedberg 		return;
165530dc78e1SJohan Hedberg 
165656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
165730dc78e1SJohan Hedberg 
1658343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
165930dc78e1SJohan Hedberg 		goto unlock;
166030dc78e1SJohan Hedberg 
166130dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1662ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
166330dc78e1SJohan Hedberg 		goto unlock;
166430dc78e1SJohan Hedberg 	}
166530dc78e1SJohan Hedberg 
166630dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
166730dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
166830dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
166930dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
167030dc78e1SJohan Hedberg 	} else {
167130dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
167230dc78e1SJohan Hedberg 	}
167330dc78e1SJohan Hedberg 
167430dc78e1SJohan Hedberg unlock:
167556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16761da177e4SLinus Torvalds }
16771da177e4SLinus Torvalds 
16781da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16791da177e4SLinus Torvalds {
168045bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1681a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16821da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16831da177e4SLinus Torvalds 
16841da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16851da177e4SLinus Torvalds 
168645bb4bf0SMarcel Holtmann 	if (!num_rsp)
168745bb4bf0SMarcel Holtmann 		return;
168845bb4bf0SMarcel Holtmann 
16891da177e4SLinus Torvalds 	hci_dev_lock(hdev);
169045bb4bf0SMarcel Holtmann 
1691e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
16923175405bSJohan Hedberg 		bool name_known;
16933175405bSJohan Hedberg 
16941da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16951da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16961da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16971da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16981da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16991da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17001da177e4SLinus Torvalds 		data.rssi		= 0x00;
170141a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17023175405bSJohan Hedberg 
17033175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false);
170448264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
17057d262f86SAndre Guedes 					info->dev_class, 0, !name_known,
17067d262f86SAndre Guedes 					NULL, 0);
17071da177e4SLinus Torvalds 	}
170845bb4bf0SMarcel Holtmann 
17091da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17101da177e4SLinus Torvalds }
17111da177e4SLinus Torvalds 
1712a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17131da177e4SLinus Torvalds {
1714a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1715a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17161da177e4SLinus Torvalds 
1717a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
171845bb4bf0SMarcel Holtmann 
17191da177e4SLinus Torvalds 	hci_dev_lock(hdev);
172045bb4bf0SMarcel Holtmann 
1721a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17229499237aSMarcel Holtmann 	if (!conn) {
17239499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17249499237aSMarcel Holtmann 			goto unlock;
17259499237aSMarcel Holtmann 
17269499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1727a9de9248SMarcel Holtmann 		if (!conn)
1728a9de9248SMarcel Holtmann 			goto unlock;
172945bb4bf0SMarcel Holtmann 
17309499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17319499237aSMarcel Holtmann 	}
17329499237aSMarcel Holtmann 
1733a9de9248SMarcel Holtmann 	if (!ev->status) {
1734a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1735769be974SMarcel Holtmann 
1736769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1737769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1738769be974SMarcel Holtmann 			hci_conn_hold(conn);
1739052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1740769be974SMarcel Holtmann 		} else
1741a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1742a9de9248SMarcel Holtmann 
17439eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
17447d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17457d0db0a3SMarcel Holtmann 
1746a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1747a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1748a9de9248SMarcel Holtmann 
1749a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1750a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1751a9de9248SMarcel Holtmann 
1752a9de9248SMarcel Holtmann 		/* Get remote features */
1753a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1754a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1755a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1756769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1757769be974SMarcel Holtmann 							sizeof(cp), &cp);
175845bb4bf0SMarcel Holtmann 		}
1759a9de9248SMarcel Holtmann 
1760a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1761d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1762a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1763a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1764a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1765a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1766a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1767a9de9248SMarcel Holtmann 		}
176817d5c04cSJohan Hedberg 	} else {
1769a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
177017d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1771744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
177248264f06SJohan Hedberg 						conn->dst_type, ev->status);
177317d5c04cSJohan Hedberg 	}
177445bb4bf0SMarcel Holtmann 
1775e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1776e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
177745bb4bf0SMarcel Holtmann 
1778769be974SMarcel Holtmann 	if (ev->status) {
1779a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1780a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1781c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1782c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1783a9de9248SMarcel Holtmann 
1784a9de9248SMarcel Holtmann unlock:
17851da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1786a9de9248SMarcel Holtmann 
1787a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
17881da177e4SLinus Torvalds }
17891da177e4SLinus Torvalds 
17901da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17911da177e4SLinus Torvalds {
1792a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17931da177e4SLinus Torvalds 	int mask = hdev->link_mode;
17941da177e4SLinus Torvalds 
1795a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
17961da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
17971da177e4SLinus Torvalds 
17981da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
17991da177e4SLinus Torvalds 
1800138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1801138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
18021da177e4SLinus Torvalds 		/* Connection accepted */
1803c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
18041da177e4SLinus Torvalds 		struct hci_conn *conn;
18051da177e4SLinus Torvalds 
18061da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1807b6a0dc82SMarcel Holtmann 
1808cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1809cc11b9c1SAndrei Emeltchenko 		if (ie)
1810c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1811c7bdd502SMarcel Holtmann 
18121da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
18131da177e4SLinus Torvalds 		if (!conn) {
1814cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1815cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1816893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
18171da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
18181da177e4SLinus Torvalds 				return;
18191da177e4SLinus Torvalds 			}
18201da177e4SLinus Torvalds 		}
1821b6a0dc82SMarcel Holtmann 
18221da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
18231da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1824b6a0dc82SMarcel Holtmann 
18251da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
18261da177e4SLinus Torvalds 
1827b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1828b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1829b6a0dc82SMarcel Holtmann 
18301da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
18311da177e4SLinus Torvalds 
18321da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
18331da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
18341da177e4SLinus Torvalds 			else
18351da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
18361da177e4SLinus Torvalds 
1837b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1838b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1839b6a0dc82SMarcel Holtmann 		} else {
1840b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1841b6a0dc82SMarcel Holtmann 
1842b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1843a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1844b6a0dc82SMarcel Holtmann 
1845b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1846b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1847b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1848b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1849b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1850b6a0dc82SMarcel Holtmann 
1851b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1852b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1853b6a0dc82SMarcel Holtmann 		}
18541da177e4SLinus Torvalds 	} else {
18551da177e4SLinus Torvalds 		/* Connection rejected */
18561da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18571da177e4SLinus Torvalds 
18581da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18599f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1860a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18611da177e4SLinus Torvalds 	}
18621da177e4SLinus Torvalds }
18631da177e4SLinus Torvalds 
18641da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18651da177e4SLinus Torvalds {
1866a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
186704837f64SMarcel Holtmann 	struct hci_conn *conn;
18681da177e4SLinus Torvalds 
18691da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
18701da177e4SLinus Torvalds 
18711da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18721da177e4SLinus Torvalds 
187304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1874f7520543SJohan Hedberg 	if (!conn)
1875f7520543SJohan Hedberg 		goto unlock;
1876f7520543SJohan Hedberg 
187737d9ef76SJohan Hedberg 	if (ev->status == 0)
18781da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18797d0db0a3SMarcel Holtmann 
1880b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1881b644ba33SJohan Hedberg 			(conn->type == ACL_LINK || conn->type == LE_LINK)) {
188237d9ef76SJohan Hedberg 		if (ev->status != 0)
188388c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
188488c3df13SJohan Hedberg 						conn->dst_type, ev->status);
188537d9ef76SJohan Hedberg 		else
1886afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
188748264f06SJohan Hedberg 							conn->dst_type);
188837d9ef76SJohan Hedberg 	}
1889f7520543SJohan Hedberg 
189037d9ef76SJohan Hedberg 	if (ev->status == 0) {
18912950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
18921da177e4SLinus Torvalds 		hci_conn_del(conn);
189337d9ef76SJohan Hedberg 	}
18941da177e4SLinus Torvalds 
1895f7520543SJohan Hedberg unlock:
18961da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18971da177e4SLinus Torvalds }
18981da177e4SLinus Torvalds 
1899a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1900a9de9248SMarcel Holtmann {
1901a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1902a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1903a9de9248SMarcel Holtmann 
1904a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1905a9de9248SMarcel Holtmann 
1906a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1907a9de9248SMarcel Holtmann 
1908a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1909d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1910d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1911d7556e20SWaldemar Rymarkiewicz 
1912765c2a96SJohan Hedberg 	if (!ev->status) {
1913aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
191451a8efd7SJohan Hedberg 				test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1915d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
191619f8def0SWaldemar Rymarkiewicz 		} else {
1917a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1918765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
191919f8def0SWaldemar Rymarkiewicz 		}
19202a611692SJohan Hedberg 	} else {
1921bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1922bab73cb6SJohan Hedberg 								ev->status);
19232a611692SJohan Hedberg 	}
1924a9de9248SMarcel Holtmann 
192551a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
192651a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1927a9de9248SMarcel Holtmann 
1928f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1929aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1930f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1931f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1932f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1933d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1934d7556e20SWaldemar Rymarkiewicz 									&cp);
1935f8558555SMarcel Holtmann 		} else {
1936f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1937f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1938f8558555SMarcel Holtmann 			hci_conn_put(conn);
1939f8558555SMarcel Holtmann 		}
1940052b30b0SMarcel Holtmann 	} else {
1941a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1942a9de9248SMarcel Holtmann 
1943052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1944052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1945052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1946052b30b0SMarcel Holtmann 	}
1947052b30b0SMarcel Holtmann 
194851a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1949a9de9248SMarcel Holtmann 		if (!ev->status) {
1950a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1951f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1952f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1953d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1954d7556e20SWaldemar Rymarkiewicz 									&cp);
1955a9de9248SMarcel Holtmann 		} else {
195651a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1957a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1958a9de9248SMarcel Holtmann 		}
1959a9de9248SMarcel Holtmann 	}
1960a9de9248SMarcel Holtmann 
1961d7556e20SWaldemar Rymarkiewicz unlock:
1962a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1963a9de9248SMarcel Holtmann }
1964a9de9248SMarcel Holtmann 
1965a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1966a9de9248SMarcel Holtmann {
1967127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1968127178d2SJohan Hedberg 	struct hci_conn *conn;
1969127178d2SJohan Hedberg 
1970a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1971a9de9248SMarcel Holtmann 
1972a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1973127178d2SJohan Hedberg 
1974127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1975127178d2SJohan Hedberg 
1976127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1977b644ba33SJohan Hedberg 
1978b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1979b644ba33SJohan Hedberg 		goto check_auth;
1980b644ba33SJohan Hedberg 
1981b644ba33SJohan Hedberg 	if (ev->status == 0)
1982b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1983b644ba33SJohan Hedberg 					strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1984b644ba33SJohan Hedberg 	else
1985b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1986b644ba33SJohan Hedberg 
1987b644ba33SJohan Hedberg check_auth:
198879c6c70cSJohan Hedberg 	if (!conn)
198979c6c70cSJohan Hedberg 		goto unlock;
199079c6c70cSJohan Hedberg 
199179c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
199279c6c70cSJohan Hedberg 		goto unlock;
199379c6c70cSJohan Hedberg 
199451a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1995127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1996127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1997127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1998127178d2SJohan Hedberg 	}
1999127178d2SJohan Hedberg 
200079c6c70cSJohan Hedberg unlock:
2001127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2002a9de9248SMarcel Holtmann }
2003a9de9248SMarcel Holtmann 
2004a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2005a9de9248SMarcel Holtmann {
2006a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2007a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2008a9de9248SMarcel Holtmann 
2009a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2010a9de9248SMarcel Holtmann 
2011a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2012a9de9248SMarcel Holtmann 
2013a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2014a9de9248SMarcel Holtmann 	if (conn) {
2015a9de9248SMarcel Holtmann 		if (!ev->status) {
2016ae293196SMarcel Holtmann 			if (ev->encrypt) {
2017ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2018ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2019a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2020da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2021ae293196SMarcel Holtmann 			} else
2022a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2023a9de9248SMarcel Holtmann 		}
2024a9de9248SMarcel Holtmann 
202551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2026a9de9248SMarcel Holtmann 
2027f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2028f8558555SMarcel Holtmann 			if (!ev->status)
2029f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2030f8558555SMarcel Holtmann 
2031f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2032f8558555SMarcel Holtmann 			hci_conn_put(conn);
2033f8558555SMarcel Holtmann 		} else
2034a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2035a9de9248SMarcel Holtmann 	}
2036a9de9248SMarcel Holtmann 
2037a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2038a9de9248SMarcel Holtmann }
2039a9de9248SMarcel Holtmann 
2040a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2041a9de9248SMarcel Holtmann {
2042a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2043a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2044a9de9248SMarcel Holtmann 
2045a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2046a9de9248SMarcel Holtmann 
2047a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2048a9de9248SMarcel Holtmann 
2049a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2050a9de9248SMarcel Holtmann 	if (conn) {
2051a9de9248SMarcel Holtmann 		if (!ev->status)
2052a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2053a9de9248SMarcel Holtmann 
205451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2055a9de9248SMarcel Holtmann 
2056a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2057a9de9248SMarcel Holtmann 	}
2058a9de9248SMarcel Holtmann 
2059a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2060a9de9248SMarcel Holtmann }
2061a9de9248SMarcel Holtmann 
2062a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2063a9de9248SMarcel Holtmann {
2064a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2065a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2066a9de9248SMarcel Holtmann 
2067a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2068a9de9248SMarcel Holtmann 
2069a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2070a9de9248SMarcel Holtmann 
2071a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2072ccd556feSJohan Hedberg 	if (!conn)
2073ccd556feSJohan Hedberg 		goto unlock;
2074ccd556feSJohan Hedberg 
2075769be974SMarcel Holtmann 	if (!ev->status)
2076a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2077a9de9248SMarcel Holtmann 
2078ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2079ccd556feSJohan Hedberg 		goto unlock;
2080ccd556feSJohan Hedberg 
2081ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2082769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2083769be974SMarcel Holtmann 		cp.handle = ev->handle;
2084769be974SMarcel Holtmann 		cp.page = 0x01;
2085ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2086769be974SMarcel Holtmann 							sizeof(cp), &cp);
2087392599b9SJohan Hedberg 		goto unlock;
2088392599b9SJohan Hedberg 	}
2089392599b9SJohan Hedberg 
2090127178d2SJohan Hedberg 	if (!ev->status) {
2091127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2092127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2093127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2094127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2095127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2096b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2097b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2098b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2099b644ba33SJohan Hedberg 						conn->dev_class);
2100392599b9SJohan Hedberg 
2101127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2102769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2103769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2104769be974SMarcel Holtmann 		hci_conn_put(conn);
2105769be974SMarcel Holtmann 	}
2106769be974SMarcel Holtmann 
2107ccd556feSJohan Hedberg unlock:
2108a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2109a9de9248SMarcel Holtmann }
2110a9de9248SMarcel Holtmann 
2111a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2112a9de9248SMarcel Holtmann {
2113a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2114a9de9248SMarcel Holtmann }
2115a9de9248SMarcel Holtmann 
2116a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2117a9de9248SMarcel Holtmann {
2118a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2119a9de9248SMarcel Holtmann }
2120a9de9248SMarcel Holtmann 
2121a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2122a9de9248SMarcel Holtmann {
2123a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2124a9de9248SMarcel Holtmann 	__u16 opcode;
2125a9de9248SMarcel Holtmann 
2126a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2127a9de9248SMarcel Holtmann 
2128a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2129a9de9248SMarcel Holtmann 
2130a9de9248SMarcel Holtmann 	switch (opcode) {
2131a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2132a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2133a9de9248SMarcel Holtmann 		break;
2134a9de9248SMarcel Holtmann 
2135a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2136a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2137a9de9248SMarcel Holtmann 		break;
2138a9de9248SMarcel Holtmann 
2139a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2140a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2141a9de9248SMarcel Holtmann 		break;
2142a9de9248SMarcel Holtmann 
2143a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2144a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2145a9de9248SMarcel Holtmann 		break;
2146a9de9248SMarcel Holtmann 
2147e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2148e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2149e4e8e37cSMarcel Holtmann 		break;
2150e4e8e37cSMarcel Holtmann 
2151a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2152a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2153a9de9248SMarcel Holtmann 		break;
2154a9de9248SMarcel Holtmann 
2155e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2156e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2157e4e8e37cSMarcel Holtmann 		break;
2158e4e8e37cSMarcel Holtmann 
2159e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2160e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2161e4e8e37cSMarcel Holtmann 		break;
2162e4e8e37cSMarcel Holtmann 
2163a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2164a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2165a9de9248SMarcel Holtmann 		break;
2166a9de9248SMarcel Holtmann 
2167a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2168a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2169a9de9248SMarcel Holtmann 		break;
2170a9de9248SMarcel Holtmann 
2171a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2172a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2173a9de9248SMarcel Holtmann 		break;
2174a9de9248SMarcel Holtmann 
2175a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2176a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2177a9de9248SMarcel Holtmann 		break;
2178a9de9248SMarcel Holtmann 
2179a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2180a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2181a9de9248SMarcel Holtmann 		break;
2182a9de9248SMarcel Holtmann 
2183a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2184a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2185a9de9248SMarcel Holtmann 		break;
2186a9de9248SMarcel Holtmann 
2187a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2188a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2189a9de9248SMarcel Holtmann 		break;
2190a9de9248SMarcel Holtmann 
2191a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2192a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2193a9de9248SMarcel Holtmann 		break;
2194a9de9248SMarcel Holtmann 
2195a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2196a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2197a9de9248SMarcel Holtmann 		break;
2198a9de9248SMarcel Holtmann 
2199a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2200a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2201a9de9248SMarcel Holtmann 		break;
2202a9de9248SMarcel Holtmann 
2203a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2204a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2205a9de9248SMarcel Holtmann 		break;
2206a9de9248SMarcel Holtmann 
2207333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2208333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2209333140b5SMarcel Holtmann 		break;
2210333140b5SMarcel Holtmann 
2211a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2212a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2213a9de9248SMarcel Holtmann 		break;
2214a9de9248SMarcel Holtmann 
2215a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2216a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2217a9de9248SMarcel Holtmann 		break;
2218a9de9248SMarcel Holtmann 
2219a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2220a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2221a9de9248SMarcel Holtmann 		break;
2222a9de9248SMarcel Holtmann 
2223971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2224971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2225971e3a4bSAndre Guedes 		break;
2226971e3a4bSAndre Guedes 
2227a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2228a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2229a9de9248SMarcel Holtmann 		break;
2230a9de9248SMarcel Holtmann 
2231a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2232a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2233a9de9248SMarcel Holtmann 		break;
2234a9de9248SMarcel Holtmann 
2235350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2236350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2237350ee4cfSAndrei Emeltchenko 		break;
2238350ee4cfSAndrei Emeltchenko 
223923bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
224023bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
224123bb5763SJohan Hedberg 		break;
224223bb5763SJohan Hedberg 
22431e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22441e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22451e89cffbSAndrei Emeltchenko 		break;
22461e89cffbSAndrei Emeltchenko 
2247928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2248928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2249928abaa7SAndrei Emeltchenko 		break;
2250928abaa7SAndrei Emeltchenko 
2251b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2252b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2253b0916ea0SJohan Hedberg 		break;
2254b0916ea0SJohan Hedberg 
2255d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2256d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2257d5859e22SJohan Hedberg 		break;
2258d5859e22SJohan Hedberg 
2259d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2260d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2261d5859e22SJohan Hedberg 		break;
2262d5859e22SJohan Hedberg 
2263d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2264d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2265d5859e22SJohan Hedberg 		break;
2266d5859e22SJohan Hedberg 
2267d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2268d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2269d5859e22SJohan Hedberg 		break;
2270d5859e22SJohan Hedberg 
2271980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2272980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2273980e1a53SJohan Hedberg 		break;
2274980e1a53SJohan Hedberg 
2275980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2276980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2277980e1a53SJohan Hedberg 		break;
2278980e1a53SJohan Hedberg 
2279c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2280c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2281c35938b2SSzymon Janc 		break;
2282c35938b2SSzymon Janc 
22836ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22846ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22856ed58ec5SVille Tervo 		break;
22866ed58ec5SVille Tervo 
2287a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2288a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2289a5c29683SJohan Hedberg 		break;
2290a5c29683SJohan Hedberg 
2291a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2292a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2293a5c29683SJohan Hedberg 		break;
2294a5c29683SJohan Hedberg 
22951143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
22961143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
22971143d458SBrian Gix 		break;
22981143d458SBrian Gix 
22991143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23001143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
230107f7fa5dSAndre Guedes 
230207f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
230307f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
23041143d458SBrian Gix 		break;
23051143d458SBrian Gix 
2306eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2307eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2308eb9d91f5SAndre Guedes 		break;
2309eb9d91f5SAndre Guedes 
2310a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2311a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2312a7a595f6SVinicius Costa Gomes 		break;
2313a7a595f6SVinicius Costa Gomes 
2314a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2315a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2316a7a595f6SVinicius Costa Gomes 		break;
2317a7a595f6SVinicius Costa Gomes 
2318f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2319f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2320f9b49306SAndre Guedes 		break;
2321f9b49306SAndre Guedes 
2322a9de9248SMarcel Holtmann 	default:
2323a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2324a9de9248SMarcel Holtmann 		break;
2325a9de9248SMarcel Holtmann 	}
2326a9de9248SMarcel Holtmann 
23276bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23286bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23296bd32326SVille Tervo 
2330a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2331a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2332a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2333c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2334a9de9248SMarcel Holtmann 	}
2335a9de9248SMarcel Holtmann }
2336a9de9248SMarcel Holtmann 
2337a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2338a9de9248SMarcel Holtmann {
2339a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2340a9de9248SMarcel Holtmann 	__u16 opcode;
2341a9de9248SMarcel Holtmann 
2342a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2343a9de9248SMarcel Holtmann 
2344a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2345a9de9248SMarcel Holtmann 
2346a9de9248SMarcel Holtmann 	switch (opcode) {
2347a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2348a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2349a9de9248SMarcel Holtmann 		break;
2350a9de9248SMarcel Holtmann 
2351a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2352a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2353a9de9248SMarcel Holtmann 		break;
2354a9de9248SMarcel Holtmann 
2355a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2356a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2357a9de9248SMarcel Holtmann 		break;
2358a9de9248SMarcel Holtmann 
2359f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2360f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2361f8558555SMarcel Holtmann 		break;
2362f8558555SMarcel Holtmann 
2363f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2364f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2365f8558555SMarcel Holtmann 		break;
2366f8558555SMarcel Holtmann 
2367a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2368a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2369a9de9248SMarcel Holtmann 		break;
2370a9de9248SMarcel Holtmann 
2371769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2372769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2373769be974SMarcel Holtmann 		break;
2374769be974SMarcel Holtmann 
2375769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2376769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2377769be974SMarcel Holtmann 		break;
2378769be974SMarcel Holtmann 
2379a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2380a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2381a9de9248SMarcel Holtmann 		break;
2382a9de9248SMarcel Holtmann 
2383a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2384a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2385a9de9248SMarcel Holtmann 		break;
2386a9de9248SMarcel Holtmann 
2387a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2388a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2389a9de9248SMarcel Holtmann 		break;
2390a9de9248SMarcel Holtmann 
23918962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
239288c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
23938962ee74SJohan Hedberg 		break;
23948962ee74SJohan Hedberg 
2395fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2396fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2397fcd89c09SVille Tervo 		break;
2398fcd89c09SVille Tervo 
2399a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2400a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2401a7a595f6SVinicius Costa Gomes 		break;
2402a7a595f6SVinicius Costa Gomes 
2403a9de9248SMarcel Holtmann 	default:
2404a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2405a9de9248SMarcel Holtmann 		break;
2406a9de9248SMarcel Holtmann 	}
2407a9de9248SMarcel Holtmann 
24086bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
24096bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24106bd32326SVille Tervo 
241110572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2412a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2413a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2414c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2415a9de9248SMarcel Holtmann 	}
2416a9de9248SMarcel Holtmann }
2417a9de9248SMarcel Holtmann 
2418a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2419a9de9248SMarcel Holtmann {
2420a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2421a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2422a9de9248SMarcel Holtmann 
2423a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2424a9de9248SMarcel Holtmann 
2425a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2426a9de9248SMarcel Holtmann 
2427a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2428a9de9248SMarcel Holtmann 	if (conn) {
2429a9de9248SMarcel Holtmann 		if (!ev->status) {
2430a9de9248SMarcel Holtmann 			if (ev->role)
2431a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2432a9de9248SMarcel Holtmann 			else
2433a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2434a9de9248SMarcel Holtmann 		}
2435a9de9248SMarcel Holtmann 
243651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2437a9de9248SMarcel Holtmann 
2438a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2439a9de9248SMarcel Holtmann 	}
2440a9de9248SMarcel Holtmann 
2441a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2442a9de9248SMarcel Holtmann }
2443a9de9248SMarcel Holtmann 
24441da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24451da177e4SLinus Torvalds {
2446a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24471da177e4SLinus Torvalds 	int i;
24481da177e4SLinus Torvalds 
244932ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
245032ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
245132ac5b9bSAndrei Emeltchenko 		return;
245232ac5b9bSAndrei Emeltchenko 	}
245332ac5b9bSAndrei Emeltchenko 
2454c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2455c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24561da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24571da177e4SLinus Torvalds 		return;
24581da177e4SLinus Torvalds 	}
24591da177e4SLinus Torvalds 
2460c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2461c5993de8SAndrei Emeltchenko 
2462613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2463613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24641da177e4SLinus Torvalds 		struct hci_conn *conn;
24651da177e4SLinus Torvalds 		__u16  handle, count;
24661da177e4SLinus Torvalds 
2467613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2468613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24691da177e4SLinus Torvalds 
24701da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2471f4280918SAndrei Emeltchenko 		if (!conn)
2472f4280918SAndrei Emeltchenko 			continue;
2473f4280918SAndrei Emeltchenko 
24741da177e4SLinus Torvalds 		conn->sent -= count;
24751da177e4SLinus Torvalds 
2476f4280918SAndrei Emeltchenko 		switch (conn->type) {
2477f4280918SAndrei Emeltchenko 		case ACL_LINK:
247870f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
247970f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24801da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2481f4280918SAndrei Emeltchenko 			break;
2482f4280918SAndrei Emeltchenko 
2483f4280918SAndrei Emeltchenko 		case LE_LINK:
24846ed58ec5SVille Tervo 			if (hdev->le_pkts) {
24856ed58ec5SVille Tervo 				hdev->le_cnt += count;
24866ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
24876ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
24886ed58ec5SVille Tervo 			} else {
24896ed58ec5SVille Tervo 				hdev->acl_cnt += count;
24906ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
24916ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
24926ed58ec5SVille Tervo 			}
2493f4280918SAndrei Emeltchenko 			break;
2494f4280918SAndrei Emeltchenko 
2495f4280918SAndrei Emeltchenko 		case SCO_LINK:
249670f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
249770f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
24985b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2499f4280918SAndrei Emeltchenko 			break;
2500f4280918SAndrei Emeltchenko 
2501f4280918SAndrei Emeltchenko 		default:
2502f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2503f4280918SAndrei Emeltchenko 			break;
25041da177e4SLinus Torvalds 		}
25051da177e4SLinus Torvalds 	}
2506a9de9248SMarcel Holtmann 
25073eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25081da177e4SLinus Torvalds }
25091da177e4SLinus Torvalds 
251025e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
251125e89e99SAndrei Emeltchenko 							struct sk_buff *skb)
251225e89e99SAndrei Emeltchenko {
251325e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
251425e89e99SAndrei Emeltchenko 	int i;
251525e89e99SAndrei Emeltchenko 
251625e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
251725e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
251825e89e99SAndrei Emeltchenko 		return;
251925e89e99SAndrei Emeltchenko 	}
252025e89e99SAndrei Emeltchenko 
252125e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
252225e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
252325e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
252425e89e99SAndrei Emeltchenko 		return;
252525e89e99SAndrei Emeltchenko 	}
252625e89e99SAndrei Emeltchenko 
252725e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
252825e89e99SAndrei Emeltchenko 								ev->num_hndl);
252925e89e99SAndrei Emeltchenko 
253025e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
253125e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
253225e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
253325e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
253425e89e99SAndrei Emeltchenko 
253525e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
253625e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
253725e89e99SAndrei Emeltchenko 
253825e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
253925e89e99SAndrei Emeltchenko 		if (!conn)
254025e89e99SAndrei Emeltchenko 			continue;
254125e89e99SAndrei Emeltchenko 
254225e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
254325e89e99SAndrei Emeltchenko 
254425e89e99SAndrei Emeltchenko 		switch (conn->type) {
254525e89e99SAndrei Emeltchenko 		case ACL_LINK:
254625e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
254725e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
254825e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
254925e89e99SAndrei Emeltchenko 			break;
255025e89e99SAndrei Emeltchenko 
255125e89e99SAndrei Emeltchenko 		default:
255225e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
255325e89e99SAndrei Emeltchenko 			break;
255425e89e99SAndrei Emeltchenko 		}
255525e89e99SAndrei Emeltchenko 	}
255625e89e99SAndrei Emeltchenko 
255725e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
255825e89e99SAndrei Emeltchenko }
255925e89e99SAndrei Emeltchenko 
256004837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25611da177e4SLinus Torvalds {
2562a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
256304837f64SMarcel Holtmann 	struct hci_conn *conn;
25641da177e4SLinus Torvalds 
25651da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
25661da177e4SLinus Torvalds 
25671da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25681da177e4SLinus Torvalds 
256904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
257004837f64SMarcel Holtmann 	if (conn) {
257104837f64SMarcel Holtmann 		conn->mode = ev->mode;
257204837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
257304837f64SMarcel Holtmann 
257451a8efd7SJohan Hedberg 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
257504837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
257658a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
257704837f64SMarcel Holtmann 			else
257858a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
257904837f64SMarcel Holtmann 		}
2580e73439d8SMarcel Holtmann 
258151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2582e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
258304837f64SMarcel Holtmann 	}
258404837f64SMarcel Holtmann 
258504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
258604837f64SMarcel Holtmann }
258704837f64SMarcel Holtmann 
25881da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25891da177e4SLinus Torvalds {
2590052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2591052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2592052b30b0SMarcel Holtmann 
2593a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2594052b30b0SMarcel Holtmann 
2595052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2596052b30b0SMarcel Holtmann 
2597052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2598b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2599b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2600b6f98044SWaldemar Rymarkiewicz 
2601b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2602052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2603052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2604052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2605052b30b0SMarcel Holtmann 	}
2606052b30b0SMarcel Holtmann 
2607a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
260803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
260903b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2610a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2611a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2612a770bb5aSWaldemar Rymarkiewicz 
2613a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2614a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2615a770bb5aSWaldemar Rymarkiewicz 		else
2616a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2617a770bb5aSWaldemar Rymarkiewicz 
2618744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2619a770bb5aSWaldemar Rymarkiewicz 	}
2620980e1a53SJohan Hedberg 
2621b6f98044SWaldemar Rymarkiewicz unlock:
2622052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26231da177e4SLinus Torvalds }
26241da177e4SLinus Torvalds 
26251da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26261da177e4SLinus Torvalds {
262755ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
262855ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
262955ed8ca1SJohan Hedberg 	struct hci_conn *conn;
263055ed8ca1SJohan Hedberg 	struct link_key *key;
263155ed8ca1SJohan Hedberg 
2632a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
263355ed8ca1SJohan Hedberg 
2634a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
263555ed8ca1SJohan Hedberg 		return;
263655ed8ca1SJohan Hedberg 
263755ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
263855ed8ca1SJohan Hedberg 
263955ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
264055ed8ca1SJohan Hedberg 	if (!key) {
264155ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
264255ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
264355ed8ca1SJohan Hedberg 		goto not_found;
264455ed8ca1SJohan Hedberg 	}
264555ed8ca1SJohan Hedberg 
264655ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
264755ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
264855ed8ca1SJohan Hedberg 
2649a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2650b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
265155ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
265255ed8ca1SJohan Hedberg 		goto not_found;
265355ed8ca1SJohan Hedberg 	}
265455ed8ca1SJohan Hedberg 
265555ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
265660b83f57SWaldemar Rymarkiewicz 	if (conn) {
265760b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
265860b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
265960b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
266055ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
266155ed8ca1SJohan Hedberg 			goto not_found;
266255ed8ca1SJohan Hedberg 		}
266355ed8ca1SJohan Hedberg 
266460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
266560b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
266660b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
266760b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
266860b83f57SWaldemar Rymarkiewicz 			goto not_found;
266960b83f57SWaldemar Rymarkiewicz 		}
267060b83f57SWaldemar Rymarkiewicz 
267160b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
267260b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
267360b83f57SWaldemar Rymarkiewicz 	}
267460b83f57SWaldemar Rymarkiewicz 
267555ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
267655ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
267755ed8ca1SJohan Hedberg 
267855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
267955ed8ca1SJohan Hedberg 
268055ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
268155ed8ca1SJohan Hedberg 
268255ed8ca1SJohan Hedberg 	return;
268355ed8ca1SJohan Hedberg 
268455ed8ca1SJohan Hedberg not_found:
268555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
268655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
26871da177e4SLinus Torvalds }
26881da177e4SLinus Torvalds 
26891da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
26901da177e4SLinus Torvalds {
2691052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2692052b30b0SMarcel Holtmann 	struct hci_conn *conn;
269355ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2694052b30b0SMarcel Holtmann 
2695a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2696052b30b0SMarcel Holtmann 
2697052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2698052b30b0SMarcel Holtmann 
2699052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2700052b30b0SMarcel Holtmann 	if (conn) {
2701052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2702052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2703980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
270413d39315SWaldemar Rymarkiewicz 
270513d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
270613d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
270713d39315SWaldemar Rymarkiewicz 
2708052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2709052b30b0SMarcel Holtmann 	}
2710052b30b0SMarcel Holtmann 
2711a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2712d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
271355ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
271455ed8ca1SJohan Hedberg 
2715052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27161da177e4SLinus Torvalds }
27171da177e4SLinus Torvalds 
271804837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
271904837f64SMarcel Holtmann {
2720a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
272104837f64SMarcel Holtmann 	struct hci_conn *conn;
272204837f64SMarcel Holtmann 
272304837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
272404837f64SMarcel Holtmann 
272504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
272604837f64SMarcel Holtmann 
272704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27281da177e4SLinus Torvalds 	if (conn && !ev->status) {
27291da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27301da177e4SLinus Torvalds 
2731cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2732cc11b9c1SAndrei Emeltchenko 		if (ie) {
27331da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27341da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27351da177e4SLinus Torvalds 		}
27361da177e4SLinus Torvalds 	}
27371da177e4SLinus Torvalds 
27381da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27391da177e4SLinus Torvalds }
27401da177e4SLinus Torvalds 
2741a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2742a8746417SMarcel Holtmann {
2743a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2744a8746417SMarcel Holtmann 	struct hci_conn *conn;
2745a8746417SMarcel Holtmann 
2746a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2747a8746417SMarcel Holtmann 
2748a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2749a8746417SMarcel Holtmann 
2750a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2751a8746417SMarcel Holtmann 	if (conn && !ev->status)
2752a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2753a8746417SMarcel Holtmann 
2754a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2755a8746417SMarcel Holtmann }
2756a8746417SMarcel Holtmann 
275785a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
275885a1e930SMarcel Holtmann {
2759a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
276085a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
276185a1e930SMarcel Holtmann 
276285a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
276385a1e930SMarcel Holtmann 
276485a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
276585a1e930SMarcel Holtmann 
2766cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2767cc11b9c1SAndrei Emeltchenko 	if (ie) {
276885a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
276985a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
277085a1e930SMarcel Holtmann 	}
277185a1e930SMarcel Holtmann 
277285a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
277385a1e930SMarcel Holtmann }
277485a1e930SMarcel Holtmann 
2775a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2776a9de9248SMarcel Holtmann {
2777a9de9248SMarcel Holtmann 	struct inquiry_data data;
2778a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
27793175405bSJohan Hedberg 	bool name_known;
2780a9de9248SMarcel Holtmann 
2781a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2782a9de9248SMarcel Holtmann 
2783a9de9248SMarcel Holtmann 	if (!num_rsp)
2784a9de9248SMarcel Holtmann 		return;
2785a9de9248SMarcel Holtmann 
2786a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2787a9de9248SMarcel Holtmann 
2788a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2789138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2790138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2791a9de9248SMarcel Holtmann 
2792e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2793a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2794a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2795a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2796a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2797a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2798a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2799a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
280041a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28013175405bSJohan Hedberg 
28023175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
28033175405bSJohan Hedberg 								false);
280448264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2805e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
28067d262f86SAndre Guedes 						!name_known, NULL, 0);
2807a9de9248SMarcel Holtmann 		}
2808a9de9248SMarcel Holtmann 	} else {
2809a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2810a9de9248SMarcel Holtmann 
2811e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2812a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2813a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2814a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2815a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2816a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2817a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2818a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
281941a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28203175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
28213175405bSJohan Hedberg 								false);
282248264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2823e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
28247d262f86SAndre Guedes 						!name_known, NULL, 0);
2825a9de9248SMarcel Holtmann 		}
2826a9de9248SMarcel Holtmann 	}
2827a9de9248SMarcel Holtmann 
2828a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2829a9de9248SMarcel Holtmann }
2830a9de9248SMarcel Holtmann 
2831a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2832a9de9248SMarcel Holtmann {
283341a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
283441a96212SMarcel Holtmann 	struct hci_conn *conn;
283541a96212SMarcel Holtmann 
2836a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
283741a96212SMarcel Holtmann 
283841a96212SMarcel Holtmann 	hci_dev_lock(hdev);
283941a96212SMarcel Holtmann 
284041a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2841ccd556feSJohan Hedberg 	if (!conn)
2842ccd556feSJohan Hedberg 		goto unlock;
2843ccd556feSJohan Hedberg 
2844769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
284541a96212SMarcel Holtmann 		struct inquiry_entry *ie;
284641a96212SMarcel Holtmann 
2847cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2848cc11b9c1SAndrei Emeltchenko 		if (ie)
284941a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
285041a96212SMarcel Holtmann 
285158a681efSJohan Hedberg 		if (ev->features[0] & 0x01)
285258a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
285341a96212SMarcel Holtmann 	}
285441a96212SMarcel Holtmann 
2855ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2856ccd556feSJohan Hedberg 		goto unlock;
2857ccd556feSJohan Hedberg 
2858127178d2SJohan Hedberg 	if (!ev->status) {
2859127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2860127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2861127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2862127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2863127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2864b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2865b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2866b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2867b644ba33SJohan Hedberg 						conn->dev_class);
2868392599b9SJohan Hedberg 
2869127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2870769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2871769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2872769be974SMarcel Holtmann 		hci_conn_put(conn);
2873769be974SMarcel Holtmann 	}
2874769be974SMarcel Holtmann 
2875ccd556feSJohan Hedberg unlock:
287641a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2877a9de9248SMarcel Holtmann }
2878a9de9248SMarcel Holtmann 
2879a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2880a9de9248SMarcel Holtmann {
2881b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2882b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2883b6a0dc82SMarcel Holtmann 
2884b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2885b6a0dc82SMarcel Holtmann 
2886b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2887b6a0dc82SMarcel Holtmann 
2888b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
28899dc0a3afSMarcel Holtmann 	if (!conn) {
28909dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
28919dc0a3afSMarcel Holtmann 			goto unlock;
28929dc0a3afSMarcel Holtmann 
28939dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2894b6a0dc82SMarcel Holtmann 		if (!conn)
2895b6a0dc82SMarcel Holtmann 			goto unlock;
2896b6a0dc82SMarcel Holtmann 
28979dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
28989dc0a3afSMarcel Holtmann 	}
28999dc0a3afSMarcel Holtmann 
2900732547f9SMarcel Holtmann 	switch (ev->status) {
2901732547f9SMarcel Holtmann 	case 0x00:
2902732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2903732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2904732547f9SMarcel Holtmann 
29059eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2906732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2907732547f9SMarcel Holtmann 		break;
2908732547f9SMarcel Holtmann 
2909705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2910732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29111038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2912732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2913732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2914efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2915efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2916efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2917efc7688bSMarcel Holtmann 			goto unlock;
2918efc7688bSMarcel Holtmann 		}
2919732547f9SMarcel Holtmann 		/* fall through */
2920efc7688bSMarcel Holtmann 
2921732547f9SMarcel Holtmann 	default:
2922b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2923732547f9SMarcel Holtmann 		break;
2924732547f9SMarcel Holtmann 	}
2925b6a0dc82SMarcel Holtmann 
2926b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2927b6a0dc82SMarcel Holtmann 	if (ev->status)
2928b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2929b6a0dc82SMarcel Holtmann 
2930b6a0dc82SMarcel Holtmann unlock:
2931b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2932a9de9248SMarcel Holtmann }
2933a9de9248SMarcel Holtmann 
2934a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2935a9de9248SMarcel Holtmann {
2936a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2937a9de9248SMarcel Holtmann }
2938a9de9248SMarcel Holtmann 
293904837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
294004837f64SMarcel Holtmann {
2941a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
294204837f64SMarcel Holtmann 
294304837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
294404837f64SMarcel Holtmann }
294504837f64SMarcel Holtmann 
2946a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2947a9de9248SMarcel Holtmann {
2948a9de9248SMarcel Holtmann 	struct inquiry_data data;
2949a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2950a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2951a9de9248SMarcel Holtmann 
2952a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2953a9de9248SMarcel Holtmann 
2954a9de9248SMarcel Holtmann 	if (!num_rsp)
2955a9de9248SMarcel Holtmann 		return;
2956a9de9248SMarcel Holtmann 
2957a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2958a9de9248SMarcel Holtmann 
2959e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2960561aafbcSJohan Hedberg 		bool name_known;
2961561aafbcSJohan Hedberg 
2962a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2963a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2964a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2965a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2966a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2967a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2968a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
296941a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2970561aafbcSJohan Hedberg 
2971a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29724ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29734ddb1930SJohan Hedberg 							sizeof(info->data),
29744ddb1930SJohan Hedberg 							EIR_NAME_COMPLETE);
2975561aafbcSJohan Hedberg 		else
2976561aafbcSJohan Hedberg 			name_known = true;
2977561aafbcSJohan Hedberg 
29783175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known);
297948264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2980561aafbcSJohan Hedberg 						info->dev_class, info->rssi,
29817d262f86SAndre Guedes 						!name_known, info->data,
29827d262f86SAndre Guedes 						sizeof(info->data));
2983a9de9248SMarcel Holtmann 	}
2984a9de9248SMarcel Holtmann 
2985a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2986a9de9248SMarcel Holtmann }
2987a9de9248SMarcel Holtmann 
298817fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
298917fa4b9dSJohan Hedberg {
299017fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
299117fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
299217fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
299317fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
299417fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
299517fa4b9dSJohan Hedberg 			return 0x02;
299617fa4b9dSJohan Hedberg 		else
299717fa4b9dSJohan Hedberg 			return 0x03;
299817fa4b9dSJohan Hedberg 	}
299917fa4b9dSJohan Hedberg 
300017fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
300117fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
300258797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
300317fa4b9dSJohan Hedberg 
300417fa4b9dSJohan Hedberg 	return conn->auth_type;
300517fa4b9dSJohan Hedberg }
300617fa4b9dSJohan Hedberg 
30070493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
30080493684eSMarcel Holtmann {
30090493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
30100493684eSMarcel Holtmann 	struct hci_conn *conn;
30110493684eSMarcel Holtmann 
30120493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30130493684eSMarcel Holtmann 
30140493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30150493684eSMarcel Holtmann 
30160493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
301703b555e1SJohan Hedberg 	if (!conn)
301803b555e1SJohan Hedberg 		goto unlock;
301903b555e1SJohan Hedberg 
30200493684eSMarcel Holtmann 	hci_conn_hold(conn);
30210493684eSMarcel Holtmann 
3022a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
302303b555e1SJohan Hedberg 		goto unlock;
302403b555e1SJohan Hedberg 
3025a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
302603b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
302717fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
302817fa4b9dSJohan Hedberg 
302917fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30307a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
30317a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
30327a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
30337a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
30347cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
30357cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
303617fa4b9dSJohan Hedberg 
303758a681efSJohan Hedberg 		if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
3038ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
3039ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3040ce85ee13SSzymon Janc 		else
3041ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3042ce85ee13SSzymon Janc 
304317fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
304417fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
304503b555e1SJohan Hedberg 	} else {
304603b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
304703b555e1SJohan Hedberg 
304803b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30499f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
305003b555e1SJohan Hedberg 
305103b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
305203b555e1SJohan Hedberg 							sizeof(cp), &cp);
305303b555e1SJohan Hedberg 	}
305403b555e1SJohan Hedberg 
305503b555e1SJohan Hedberg unlock:
305603b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
305703b555e1SJohan Hedberg }
305803b555e1SJohan Hedberg 
305903b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
306003b555e1SJohan Hedberg {
306103b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
306203b555e1SJohan Hedberg 	struct hci_conn *conn;
306303b555e1SJohan Hedberg 
306403b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
306503b555e1SJohan Hedberg 
306603b555e1SJohan Hedberg 	hci_dev_lock(hdev);
306703b555e1SJohan Hedberg 
306803b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
306903b555e1SJohan Hedberg 	if (!conn)
307003b555e1SJohan Hedberg 		goto unlock;
307103b555e1SJohan Hedberg 
307203b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
307303b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
307458a681efSJohan Hedberg 	if (ev->oob_data)
307558a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
307603b555e1SJohan Hedberg 
307703b555e1SJohan Hedberg unlock:
30780493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
30790493684eSMarcel Holtmann }
30800493684eSMarcel Holtmann 
3081a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3082a5c29683SJohan Hedberg 							struct sk_buff *skb)
3083a5c29683SJohan Hedberg {
3084a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
308555bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
30867a828908SJohan Hedberg 	struct hci_conn *conn;
3087a5c29683SJohan Hedberg 
3088a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3089a5c29683SJohan Hedberg 
3090a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3091a5c29683SJohan Hedberg 
3092a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
30937a828908SJohan Hedberg 		goto unlock;
30947a828908SJohan Hedberg 
30957a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
30967a828908SJohan Hedberg 	if (!conn)
30977a828908SJohan Hedberg 		goto unlock;
30987a828908SJohan Hedberg 
30997a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
31007a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
31017a828908SJohan Hedberg 
31027a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
31037a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
31047a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
31057a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
31067a828908SJohan Hedberg 	 * bit set. */
31077a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
31087a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
31097a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
31107a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
31117a828908SJohan Hedberg 		goto unlock;
31127a828908SJohan Hedberg 	}
31137a828908SJohan Hedberg 
31147a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
31157a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
31167a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
311755bc1a37SJohan Hedberg 
311855bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
311955bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
312055bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
312151a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
312255bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
312355bc1a37SJohan Hedberg 			confirm_hint = 1;
312455bc1a37SJohan Hedberg 			goto confirm;
312555bc1a37SJohan Hedberg 		}
312655bc1a37SJohan Hedberg 
31279f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
31289f61656aSJohan Hedberg 						hdev->auto_accept_delay);
31299f61656aSJohan Hedberg 
31309f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
31319f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
31329f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
31339f61656aSJohan Hedberg 			goto unlock;
31349f61656aSJohan Hedberg 		}
31359f61656aSJohan Hedberg 
31367a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
31377a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
31387a828908SJohan Hedberg 		goto unlock;
31397a828908SJohan Hedberg 	}
31407a828908SJohan Hedberg 
314155bc1a37SJohan Hedberg confirm:
3142272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
314355bc1a37SJohan Hedberg 								confirm_hint);
3144a5c29683SJohan Hedberg 
31457a828908SJohan Hedberg unlock:
3146a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3147a5c29683SJohan Hedberg }
3148a5c29683SJohan Hedberg 
31491143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
31501143d458SBrian Gix 							struct sk_buff *skb)
31511143d458SBrian Gix {
31521143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
31531143d458SBrian Gix 
31541143d458SBrian Gix 	BT_DBG("%s", hdev->name);
31551143d458SBrian Gix 
31561143d458SBrian Gix 	hci_dev_lock(hdev);
31571143d458SBrian Gix 
3158a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3159272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
31601143d458SBrian Gix 
31611143d458SBrian Gix 	hci_dev_unlock(hdev);
31621143d458SBrian Gix }
31631143d458SBrian Gix 
31640493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
31650493684eSMarcel Holtmann {
31660493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
31670493684eSMarcel Holtmann 	struct hci_conn *conn;
31680493684eSMarcel Holtmann 
31690493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31700493684eSMarcel Holtmann 
31710493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31720493684eSMarcel Holtmann 
31730493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31742a611692SJohan Hedberg 	if (!conn)
31752a611692SJohan Hedberg 		goto unlock;
31762a611692SJohan Hedberg 
31772a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
31782a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
31792a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
31802a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
31812a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
318251a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3183bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3184bab73cb6SJohan Hedberg 								ev->status);
31852a611692SJohan Hedberg 
31860493684eSMarcel Holtmann 	hci_conn_put(conn);
31870493684eSMarcel Holtmann 
31882a611692SJohan Hedberg unlock:
31890493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31900493684eSMarcel Holtmann }
31910493684eSMarcel Holtmann 
319241a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
319341a96212SMarcel Holtmann {
319441a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
319541a96212SMarcel Holtmann 	struct inquiry_entry *ie;
319641a96212SMarcel Holtmann 
319741a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
319841a96212SMarcel Holtmann 
319941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
320041a96212SMarcel Holtmann 
3201cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3202cc11b9c1SAndrei Emeltchenko 	if (ie)
320341a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
320441a96212SMarcel Holtmann 
320541a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
320641a96212SMarcel Holtmann }
320741a96212SMarcel Holtmann 
32082763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
32092763eda6SSzymon Janc 							struct sk_buff *skb)
32102763eda6SSzymon Janc {
32112763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
32122763eda6SSzymon Janc 	struct oob_data *data;
32132763eda6SSzymon Janc 
32142763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
32152763eda6SSzymon Janc 
32162763eda6SSzymon Janc 	hci_dev_lock(hdev);
32172763eda6SSzymon Janc 
3218a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3219e1ba1f15SSzymon Janc 		goto unlock;
3220e1ba1f15SSzymon Janc 
32212763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
32222763eda6SSzymon Janc 	if (data) {
32232763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
32242763eda6SSzymon Janc 
32252763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32262763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
32272763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
32282763eda6SSzymon Janc 
32292763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
32302763eda6SSzymon Janc 									&cp);
32312763eda6SSzymon Janc 	} else {
32322763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
32332763eda6SSzymon Janc 
32342763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32352763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
32362763eda6SSzymon Janc 									&cp);
32372763eda6SSzymon Janc 	}
32382763eda6SSzymon Janc 
3239e1ba1f15SSzymon Janc unlock:
32402763eda6SSzymon Janc 	hci_dev_unlock(hdev);
32412763eda6SSzymon Janc }
32422763eda6SSzymon Janc 
3243fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3244fcd89c09SVille Tervo {
3245fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3246fcd89c09SVille Tervo 	struct hci_conn *conn;
3247fcd89c09SVille Tervo 
3248fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3249fcd89c09SVille Tervo 
3250fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3251fcd89c09SVille Tervo 
3252fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3253b62f328bSVille Tervo 	if (!conn) {
3254b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3255b62f328bSVille Tervo 		if (!conn) {
3256b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3257b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3258b62f328bSVille Tervo 			return;
3259b62f328bSVille Tervo 		}
326029b7988aSAndre Guedes 
326129b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3262b62f328bSVille Tervo 	}
3263fcd89c09SVille Tervo 
3264fcd89c09SVille Tervo 	if (ev->status) {
326548264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
326648264f06SJohan Hedberg 						conn->dst_type, ev->status);
3267fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3268fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3269fcd89c09SVille Tervo 		hci_conn_del(conn);
3270fcd89c09SVille Tervo 		goto unlock;
3271fcd89c09SVille Tervo 	}
3272fcd89c09SVille Tervo 
3273b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3274b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
3275b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0, 0);
327683bc71b4SVinicius Costa Gomes 
32777b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3278fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3279fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3280fcd89c09SVille Tervo 
3281fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3282fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3283fcd89c09SVille Tervo 
3284fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3285fcd89c09SVille Tervo 
3286fcd89c09SVille Tervo unlock:
3287fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3288fcd89c09SVille Tervo }
3289fcd89c09SVille Tervo 
32909aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
32919aa04c91SAndre Guedes 						struct sk_buff *skb)
32929aa04c91SAndre Guedes {
3293e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3294e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
32953c9e9195SAndre Guedes 	s8 rssi;
32969aa04c91SAndre Guedes 
32979aa04c91SAndre Guedes 	hci_dev_lock(hdev);
32989aa04c91SAndre Guedes 
3299e95beb41SAndre Guedes 	while (num_reports--) {
3300e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3301e95beb41SAndre Guedes 
33029aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
33039aa04c91SAndre Guedes 
33043c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
33053c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
33063c9e9195SAndre Guedes 					NULL, rssi, 0, ev->data, ev->length);
33073c9e9195SAndre Guedes 
3308e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
33099aa04c91SAndre Guedes 	}
33109aa04c91SAndre Guedes 
33119aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
33129aa04c91SAndre Guedes }
33139aa04c91SAndre Guedes 
3314a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3315a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3316a7a595f6SVinicius Costa Gomes {
3317a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3318a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3319bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3320a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3321c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3322a7a595f6SVinicius Costa Gomes 
3323a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3324a7a595f6SVinicius Costa Gomes 
3325a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3326a7a595f6SVinicius Costa Gomes 
3327a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3328bea710feSVinicius Costa Gomes 	if (conn == NULL)
3329bea710feSVinicius Costa Gomes 		goto not_found;
3330a7a595f6SVinicius Costa Gomes 
3331bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3332bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3333bea710feSVinicius Costa Gomes 		goto not_found;
3334bea710feSVinicius Costa Gomes 
3335bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3336a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3337c9839a11SVinicius Costa Gomes 
3338c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3339c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3340a7a595f6SVinicius Costa Gomes 
3341a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3342a7a595f6SVinicius Costa Gomes 
3343c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3344c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3345c9839a11SVinicius Costa Gomes 		kfree(ltk);
3346c9839a11SVinicius Costa Gomes 	}
3347c9839a11SVinicius Costa Gomes 
3348a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3349bea710feSVinicius Costa Gomes 
3350bea710feSVinicius Costa Gomes 	return;
3351bea710feSVinicius Costa Gomes 
3352bea710feSVinicius Costa Gomes not_found:
3353bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3354bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3355bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3356a7a595f6SVinicius Costa Gomes }
3357a7a595f6SVinicius Costa Gomes 
3358fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3359fcd89c09SVille Tervo {
3360fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3361fcd89c09SVille Tervo 
3362fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3363fcd89c09SVille Tervo 
3364fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3365fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3366fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3367fcd89c09SVille Tervo 		break;
3368fcd89c09SVille Tervo 
33699aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
33709aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
33719aa04c91SAndre Guedes 		break;
33729aa04c91SAndre Guedes 
3373a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3374a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3375a7a595f6SVinicius Costa Gomes 		break;
3376a7a595f6SVinicius Costa Gomes 
3377fcd89c09SVille Tervo 	default:
3378fcd89c09SVille Tervo 		break;
3379fcd89c09SVille Tervo 	}
3380fcd89c09SVille Tervo }
3381fcd89c09SVille Tervo 
33821da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
33831da177e4SLinus Torvalds {
3384a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3385a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
33861da177e4SLinus Torvalds 
33871da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
33881da177e4SLinus Torvalds 
3389a9de9248SMarcel Holtmann 	switch (event) {
33901da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
33911da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
33921da177e4SLinus Torvalds 		break;
33931da177e4SLinus Torvalds 
33941da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
33951da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
33961da177e4SLinus Torvalds 		break;
33971da177e4SLinus Torvalds 
3398a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3399a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
340021d9e30eSMarcel Holtmann 		break;
340121d9e30eSMarcel Holtmann 
34021da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
34031da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
34041da177e4SLinus Torvalds 		break;
34051da177e4SLinus Torvalds 
34061da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
34071da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
34081da177e4SLinus Torvalds 		break;
34091da177e4SLinus Torvalds 
34101da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
34111da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
34121da177e4SLinus Torvalds 		break;
34131da177e4SLinus Torvalds 
3414a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3415a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3416a9de9248SMarcel Holtmann 		break;
3417a9de9248SMarcel Holtmann 
34181da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
34191da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
34201da177e4SLinus Torvalds 		break;
34211da177e4SLinus Torvalds 
3422a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3423a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3424a9de9248SMarcel Holtmann 		break;
3425a9de9248SMarcel Holtmann 
3426a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3427a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3428a9de9248SMarcel Holtmann 		break;
3429a9de9248SMarcel Holtmann 
3430a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3431a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3432a9de9248SMarcel Holtmann 		break;
3433a9de9248SMarcel Holtmann 
3434a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3435a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3436a9de9248SMarcel Holtmann 		break;
3437a9de9248SMarcel Holtmann 
3438a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3439a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3440a9de9248SMarcel Holtmann 		break;
3441a9de9248SMarcel Holtmann 
3442a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3443a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3444a9de9248SMarcel Holtmann 		break;
3445a9de9248SMarcel Holtmann 
3446a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3447a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3448a9de9248SMarcel Holtmann 		break;
3449a9de9248SMarcel Holtmann 
3450a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3451a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3452a9de9248SMarcel Holtmann 		break;
3453a9de9248SMarcel Holtmann 
3454a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3455a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
34561da177e4SLinus Torvalds 		break;
34571da177e4SLinus Torvalds 
34581da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
34591da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
34601da177e4SLinus Torvalds 		break;
34611da177e4SLinus Torvalds 
34621da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
34631da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
34641da177e4SLinus Torvalds 		break;
34651da177e4SLinus Torvalds 
34661da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
34671da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
34681da177e4SLinus Torvalds 		break;
34691da177e4SLinus Torvalds 
34701da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
34711da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
34721da177e4SLinus Torvalds 		break;
34731da177e4SLinus Torvalds 
3474a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3475a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3476a8746417SMarcel Holtmann 		break;
3477a8746417SMarcel Holtmann 
347885a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
347985a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
348085a1e930SMarcel Holtmann 		break;
348185a1e930SMarcel Holtmann 
3482a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3483a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3484a9de9248SMarcel Holtmann 		break;
3485a9de9248SMarcel Holtmann 
3486a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3487a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3488a9de9248SMarcel Holtmann 		break;
3489a9de9248SMarcel Holtmann 
3490a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3491a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3492a9de9248SMarcel Holtmann 		break;
3493a9de9248SMarcel Holtmann 
3494a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3495a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3496a9de9248SMarcel Holtmann 		break;
3497a9de9248SMarcel Holtmann 
349804837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
349904837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
350004837f64SMarcel Holtmann 		break;
350104837f64SMarcel Holtmann 
3502a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3503a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
35041da177e4SLinus Torvalds 		break;
35051da177e4SLinus Torvalds 
35060493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
35070493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
35080493684eSMarcel Holtmann 		break;
35090493684eSMarcel Holtmann 
351003b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
351103b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
351203b555e1SJohan Hedberg 		break;
351303b555e1SJohan Hedberg 
3514a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3515a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3516a5c29683SJohan Hedberg 		break;
3517a5c29683SJohan Hedberg 
35181143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
35191143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
35201143d458SBrian Gix 		break;
35211143d458SBrian Gix 
35220493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
35230493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
35240493684eSMarcel Holtmann 		break;
35250493684eSMarcel Holtmann 
352641a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
352741a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
352841a96212SMarcel Holtmann 		break;
352941a96212SMarcel Holtmann 
3530fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3531fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3532fcd89c09SVille Tervo 		break;
3533fcd89c09SVille Tervo 
35342763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
35352763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
35362763eda6SSzymon Janc 		break;
35372763eda6SSzymon Janc 
353825e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
353925e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
354025e89e99SAndrei Emeltchenko 		break;
354125e89e99SAndrei Emeltchenko 
35421da177e4SLinus Torvalds 	default:
3543a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
35441da177e4SLinus Torvalds 		break;
35451da177e4SLinus Torvalds 	}
35461da177e4SLinus Torvalds 
35471da177e4SLinus Torvalds 	kfree_skb(skb);
35481da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
35491da177e4SLinus Torvalds }
3550