xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 388fc8fa)
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 
212f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
213f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
21428cc7bdeSJohan Hedberg 	else if (!status)
21528cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
216f51d5b24SJohan Hedberg 
21756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
218a9de9248SMarcel Holtmann }
219a9de9248SMarcel Holtmann 
220a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
221a9de9248SMarcel Holtmann {
222a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
223a9de9248SMarcel Holtmann 
224a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
225a9de9248SMarcel Holtmann 
226a9de9248SMarcel Holtmann 	if (rp->status)
227a9de9248SMarcel Holtmann 		return;
228a9de9248SMarcel Holtmann 
229db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2301f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
231a9de9248SMarcel Holtmann }
232a9de9248SMarcel Holtmann 
233a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
234a9de9248SMarcel Holtmann {
235a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
236a9de9248SMarcel Holtmann 	void *sent;
237a9de9248SMarcel Holtmann 
238a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
239a9de9248SMarcel Holtmann 
240a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
241a9de9248SMarcel Holtmann 	if (!sent)
242a9de9248SMarcel Holtmann 		return;
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds 	if (!status) {
245a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
246a9de9248SMarcel Holtmann 
2471da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2481da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2491da177e4SLinus Torvalds 		else
2501da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2511da177e4SLinus Torvalds 	}
252a9de9248SMarcel Holtmann 
25333ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
25433ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
25533ef95edSJohan Hedberg 
25623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
257a9de9248SMarcel Holtmann }
2581da177e4SLinus Torvalds 
259a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
260a9de9248SMarcel Holtmann {
261a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
262a9de9248SMarcel Holtmann 	void *sent;
263a9de9248SMarcel Holtmann 
264a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
265a9de9248SMarcel Holtmann 
266a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2671da177e4SLinus Torvalds 	if (!sent)
268a9de9248SMarcel Holtmann 		return;
2691da177e4SLinus Torvalds 
2701da177e4SLinus Torvalds 	if (!status) {
271a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
272a9de9248SMarcel Holtmann 
2731da177e4SLinus Torvalds 		if (param)
2741da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2751da177e4SLinus Torvalds 		else
2761da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2771da177e4SLinus Torvalds 	}
278a9de9248SMarcel Holtmann 
27923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2801da177e4SLinus Torvalds }
2811da177e4SLinus Torvalds 
282a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
283a9de9248SMarcel Holtmann {
28436f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28536f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
286a9de9248SMarcel Holtmann 	void *sent;
2871da177e4SLinus Torvalds 
288a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
289a9de9248SMarcel Holtmann 
290a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2911da177e4SLinus Torvalds 	if (!sent)
292a9de9248SMarcel Holtmann 		return;
2931da177e4SLinus Torvalds 
29436f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
295a9de9248SMarcel Holtmann 
29656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29756e5cb86SJohan Hedberg 
2982d7cee58SJohan Hedberg 	if (status != 0) {
299744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3002d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3012d7cee58SJohan Hedberg 		goto done;
3022d7cee58SJohan Hedberg 	}
3032d7cee58SJohan Hedberg 
3049fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3059fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
306a9de9248SMarcel Holtmann 
30773f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3081da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3099fbcbb45SJohan Hedberg 		if (!old_iscan)
310744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31116ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
31216ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31316ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31416ab91abSJohan Hedberg 									to);
31516ab91abSJohan Hedberg 		}
3169fbcbb45SJohan Hedberg 	} else if (old_iscan)
317744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3181da177e4SLinus Torvalds 
3199fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3201da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3219fbcbb45SJohan Hedberg 		if (!old_pscan)
322744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3239fbcbb45SJohan Hedberg 	} else if (old_pscan)
324744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
325a9de9248SMarcel Holtmann 
32636f7fc7eSJohan Hedberg done:
32756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
32823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3291da177e4SLinus Torvalds }
3301da177e4SLinus Torvalds 
331a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
332a9de9248SMarcel Holtmann {
333a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
334a9de9248SMarcel Holtmann 
335a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
336a9de9248SMarcel Holtmann 
337a9de9248SMarcel Holtmann 	if (rp->status)
338a9de9248SMarcel Holtmann 		return;
339a9de9248SMarcel Holtmann 
340a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
341a9de9248SMarcel Holtmann 
342a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
343a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
344a9de9248SMarcel Holtmann }
345a9de9248SMarcel Holtmann 
346a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
347a9de9248SMarcel Holtmann {
348a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
349a9de9248SMarcel Holtmann 	void *sent;
350a9de9248SMarcel Holtmann 
351a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
352a9de9248SMarcel Holtmann 
353a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
354a9de9248SMarcel Holtmann 	if (!sent)
355a9de9248SMarcel Holtmann 		return;
356a9de9248SMarcel Holtmann 
3577f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3587f9a903cSMarcel Holtmann 
3597f9a903cSMarcel Holtmann 	if (status == 0)
360a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3617f9a903cSMarcel Holtmann 
3627f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3637f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3647f9a903cSMarcel Holtmann 
3657f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
366a9de9248SMarcel Holtmann }
367a9de9248SMarcel Holtmann 
368a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
369a9de9248SMarcel Holtmann {
370a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
371a9de9248SMarcel Holtmann 	__u16 setting;
372a9de9248SMarcel Holtmann 
373a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
374a9de9248SMarcel Holtmann 
375a9de9248SMarcel Holtmann 	if (rp->status)
376a9de9248SMarcel Holtmann 		return;
377a9de9248SMarcel Holtmann 
378a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
379a9de9248SMarcel Holtmann 
380a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
381a9de9248SMarcel Holtmann 		return;
382a9de9248SMarcel Holtmann 
383a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
384a9de9248SMarcel Holtmann 
385a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
386a9de9248SMarcel Holtmann 
3873c54711cSGustavo F. Padovan 	if (hdev->notify)
388a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
389a9de9248SMarcel Holtmann }
390a9de9248SMarcel Holtmann 
391a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
392a9de9248SMarcel Holtmann {
393a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
394f383f275SMarcel Holtmann 	__u16 setting;
395a9de9248SMarcel Holtmann 	void *sent;
396a9de9248SMarcel Holtmann 
397a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
398a9de9248SMarcel Holtmann 
399f383f275SMarcel Holtmann 	if (status)
400f383f275SMarcel Holtmann 		return;
401f383f275SMarcel Holtmann 
402a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
403a9de9248SMarcel Holtmann 	if (!sent)
404a9de9248SMarcel Holtmann 		return;
405a9de9248SMarcel Holtmann 
406f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4071da177e4SLinus Torvalds 
408f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
409f383f275SMarcel Holtmann 		return;
410f383f275SMarcel Holtmann 
4111da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4121da177e4SLinus Torvalds 
413a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4141da177e4SLinus Torvalds 
4153c54711cSGustavo F. Padovan 	if (hdev->notify)
4161da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4171da177e4SLinus Torvalds }
4181da177e4SLinus Torvalds 
419a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4201da177e4SLinus Torvalds {
421a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4221da177e4SLinus Torvalds 
423a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4241da177e4SLinus Torvalds 
42523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4261143e5a6SMarcel Holtmann }
4271143e5a6SMarcel Holtmann 
428333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
429333140b5SMarcel Holtmann {
430333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
431333140b5SMarcel Holtmann 	void *sent;
432333140b5SMarcel Holtmann 
433333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
434333140b5SMarcel Holtmann 
435333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
436333140b5SMarcel Holtmann 	if (!sent)
437333140b5SMarcel Holtmann 		return;
438333140b5SMarcel Holtmann 
439c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
440c0ecddc2SJohan Hedberg 		mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
441c0ecddc2SJohan Hedberg 	else if (!status) {
44284bde9d6SJohan Hedberg 		if (*((u8 *) sent))
44384bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
44484bde9d6SJohan Hedberg 		else
44584bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
446c0ecddc2SJohan Hedberg 	}
447333140b5SMarcel Holtmann }
448333140b5SMarcel Holtmann 
449d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
450d5859e22SJohan Hedberg {
451d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
452d5859e22SJohan Hedberg 		return 2;
453d5859e22SJohan Hedberg 
454d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
455d5859e22SJohan Hedberg 		return 1;
456d5859e22SJohan Hedberg 
457d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
458d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
459d5859e22SJohan Hedberg 		return 1;
460d5859e22SJohan Hedberg 
461d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
462d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
463d5859e22SJohan Hedberg 			return 1;
464d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
465d5859e22SJohan Hedberg 			return 1;
466d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
467d5859e22SJohan Hedberg 			return 1;
468d5859e22SJohan Hedberg 	}
469d5859e22SJohan Hedberg 
470d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
471d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
472d5859e22SJohan Hedberg 		return 1;
473d5859e22SJohan Hedberg 
474d5859e22SJohan Hedberg 	return 0;
475d5859e22SJohan Hedberg }
476d5859e22SJohan Hedberg 
477d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
478d5859e22SJohan Hedberg {
479d5859e22SJohan Hedberg 	u8 mode;
480d5859e22SJohan Hedberg 
481d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
482d5859e22SJohan Hedberg 
483d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
484d5859e22SJohan Hedberg }
485d5859e22SJohan Hedberg 
486d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
487d5859e22SJohan Hedberg {
488d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
489d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
490d5859e22SJohan Hedberg 	 * command otherwise */
491d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
492d5859e22SJohan Hedberg 
4936de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
4946de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
4955a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
4966de6c18dSVille Tervo 		return;
4976de6c18dSVille Tervo 
498d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
499d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
500d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
501d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
502d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
503d5859e22SJohan Hedberg 
504d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
505d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
506d5859e22SJohan Hedberg 
507d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
508d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
509d5859e22SJohan Hedberg 
510d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
511d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
512d5859e22SJohan Hedberg 
513d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
514d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
515d5859e22SJohan Hedberg 
516d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
517d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
518d5859e22SJohan Hedberg 
519d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
520d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
521d5859e22SJohan Hedberg 
522d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
523d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
524d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
525d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
526d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
527d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
528d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
529d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
530d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
531d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
532d5859e22SJohan Hedberg 					 * Features Notification */
533d5859e22SJohan Hedberg 	}
534d5859e22SJohan Hedberg 
535d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
536d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
537d5859e22SJohan Hedberg 
538d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
539d5859e22SJohan Hedberg }
540d5859e22SJohan Hedberg 
541e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
542e6100a25SAndre Guedes {
543e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
544e6100a25SAndre Guedes 
545e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
546e6100a25SAndre Guedes 
54706199cf8SJohan Hedberg 	if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
548e6100a25SAndre Guedes 		cp.le = 1;
549e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
550e6100a25SAndre Guedes 	}
551e6100a25SAndre Guedes 
552e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
553e6100a25SAndre Guedes }
554e6100a25SAndre Guedes 
555d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
556d5859e22SJohan Hedberg {
557e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
558e61ef499SAndrei Emeltchenko 		return;
559e61ef499SAndrei Emeltchenko 
560d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
561d5859e22SJohan Hedberg 
562d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
563d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
564d5859e22SJohan Hedberg 
56528cc7bdeSJohan Hedberg 	if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
56628cc7bdeSJohan Hedberg 					test_bit(HCI_MGMT, &hdev->dev_flags)) {
56728cc7bdeSJohan Hedberg 		struct hci_cp_write_local_name cp;
56828cc7bdeSJohan Hedberg 
56928cc7bdeSJohan Hedberg 		memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
57028cc7bdeSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
57128cc7bdeSJohan Hedberg 	}
57228cc7bdeSJohan Hedberg 
57354d04dbbSJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
57454d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
575d5859e22SJohan Hedberg 			u8 mode = 0x01;
57654d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
57754d04dbbSJohan Hedberg 							sizeof(mode), &mode);
57854d04dbbSJohan Hedberg 		} else {
57954d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
58054d04dbbSJohan Hedberg 
58154d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
58254d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
58354d04dbbSJohan Hedberg 
58454d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
58554d04dbbSJohan Hedberg 		}
586d5859e22SJohan Hedberg 	}
587d5859e22SJohan Hedberg 
588d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
589d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
590d5859e22SJohan Hedberg 
591d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
592d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
593971e3a4bSAndre Guedes 
594971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
595971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
596971e3a4bSAndre Guedes 
597971e3a4bSAndre Guedes 		cp.page = 0x01;
598971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
599971e3a4bSAndre Guedes 							sizeof(cp), &cp);
600971e3a4bSAndre Guedes 	}
601e6100a25SAndre Guedes 
60247990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
60347990ea0SJohan Hedberg 		u8 enable = 1;
60447990ea0SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
60547990ea0SJohan Hedberg 						sizeof(enable), &enable);
60647990ea0SJohan Hedberg 	}
60747990ea0SJohan Hedberg 
608e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
609e6100a25SAndre Guedes 		hci_set_le_support(hdev);
610d5859e22SJohan Hedberg }
611d5859e22SJohan Hedberg 
612a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
613a9de9248SMarcel Holtmann {
614a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6151143e5a6SMarcel Holtmann 
616a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
6171143e5a6SMarcel Holtmann 
618a9de9248SMarcel Holtmann 	if (rp->status)
619a9de9248SMarcel Holtmann 		return;
6201143e5a6SMarcel Holtmann 
621a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
622e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
623d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
624e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
625d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6261da177e4SLinus Torvalds 
627a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
628a9de9248SMarcel Holtmann 					hdev->manufacturer,
629a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
630d5859e22SJohan Hedberg 
631d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
632d5859e22SJohan Hedberg 		hci_setup(hdev);
633d5859e22SJohan Hedberg }
634d5859e22SJohan Hedberg 
635d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
636d5859e22SJohan Hedberg {
637d5859e22SJohan Hedberg 	u16 link_policy = 0;
638d5859e22SJohan Hedberg 
639d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
640d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
641d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
642d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
643d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
644d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
645d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
646d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
647d5859e22SJohan Hedberg 
648d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
649d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
650d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6511da177e4SLinus Torvalds }
6521da177e4SLinus Torvalds 
653a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
654a9de9248SMarcel Holtmann {
655a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
656a9de9248SMarcel Holtmann 
657a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
658a9de9248SMarcel Holtmann 
659a9de9248SMarcel Holtmann 	if (rp->status)
660d5859e22SJohan Hedberg 		goto done;
661a9de9248SMarcel Holtmann 
662a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
663d5859e22SJohan Hedberg 
664d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
665d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
666d5859e22SJohan Hedberg 
667d5859e22SJohan Hedberg done:
668d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
669a9de9248SMarcel Holtmann }
670a9de9248SMarcel Holtmann 
671a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
672a9de9248SMarcel Holtmann {
673a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
674a9de9248SMarcel Holtmann 
675a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
676a9de9248SMarcel Holtmann 
677a9de9248SMarcel Holtmann 	if (rp->status)
678a9de9248SMarcel Holtmann 		return;
679a9de9248SMarcel Holtmann 
680a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6811da177e4SLinus Torvalds 
6821da177e4SLinus Torvalds 	/* Adjust default settings according to features
6831da177e4SLinus Torvalds 	 * supported by device. */
684a9de9248SMarcel Holtmann 
6851da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6861da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6871da177e4SLinus Torvalds 
6881da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6891da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6901da177e4SLinus Torvalds 
6915b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6921da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6935b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6945b7f9909SMarcel Holtmann 	}
6951da177e4SLinus Torvalds 
6965b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6971da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6985b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6995b7f9909SMarcel Holtmann 	}
7005b7f9909SMarcel Holtmann 
7015b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
7025b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
7035b7f9909SMarcel Holtmann 
7045b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
7055b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
7065b7f9909SMarcel Holtmann 
7075b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
7085b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
7091da177e4SLinus Torvalds 
710efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
711efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
712efc7688bSMarcel Holtmann 
713efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
714efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
715efc7688bSMarcel Holtmann 
716efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
717efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
718efc7688bSMarcel Holtmann 
719a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
720a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
721a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
722a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
723a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7241da177e4SLinus Torvalds }
7251da177e4SLinus Torvalds 
726971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
727971e3a4bSAndre Guedes 							struct sk_buff *skb)
728971e3a4bSAndre Guedes {
729971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
730971e3a4bSAndre Guedes 
731971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
732971e3a4bSAndre Guedes 
733971e3a4bSAndre Guedes 	if (rp->status)
734971e3a4bSAndre Guedes 		return;
735971e3a4bSAndre Guedes 
736b5b32b65SAndre Guedes 	switch (rp->page) {
737b5b32b65SAndre Guedes 	case 0:
738b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
739b5b32b65SAndre Guedes 		break;
740b5b32b65SAndre Guedes 	case 1:
74159e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
742b5b32b65SAndre Guedes 		break;
743b5b32b65SAndre Guedes 	}
744971e3a4bSAndre Guedes 
745971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
746971e3a4bSAndre Guedes }
747971e3a4bSAndre Guedes 
7481e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7491e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7501e89cffbSAndrei Emeltchenko {
7511e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7521e89cffbSAndrei Emeltchenko 
7531e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7541e89cffbSAndrei Emeltchenko 
7551e89cffbSAndrei Emeltchenko 	if (rp->status)
7561e89cffbSAndrei Emeltchenko 		return;
7571e89cffbSAndrei Emeltchenko 
7581e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7591e89cffbSAndrei Emeltchenko 
7601e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7611e89cffbSAndrei Emeltchenko }
7621e89cffbSAndrei Emeltchenko 
763a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
764a9de9248SMarcel Holtmann {
765a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
766a9de9248SMarcel Holtmann 
767a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
768a9de9248SMarcel Holtmann 
769a9de9248SMarcel Holtmann 	if (rp->status)
770a9de9248SMarcel Holtmann 		return;
771a9de9248SMarcel Holtmann 
772a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
773a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
774a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
775a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
776da1f5198SMarcel Holtmann 
777da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
778da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
779da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
780da1f5198SMarcel Holtmann 	}
781da1f5198SMarcel Holtmann 
782da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
783da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7841da177e4SLinus Torvalds 
785a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
786a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
787a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7881da177e4SLinus Torvalds }
7891da177e4SLinus Torvalds 
790a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
791a9de9248SMarcel Holtmann {
792a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7931da177e4SLinus Torvalds 
794a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
795a9de9248SMarcel Holtmann 
796a9de9248SMarcel Holtmann 	if (!rp->status)
797a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
798a9de9248SMarcel Holtmann 
79923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
80023bb5763SJohan Hedberg }
80123bb5763SJohan Hedberg 
802350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
803350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
804350ee4cfSAndrei Emeltchenko {
805350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
806350ee4cfSAndrei Emeltchenko 
807350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
808350ee4cfSAndrei Emeltchenko 
809350ee4cfSAndrei Emeltchenko 	if (rp->status)
810350ee4cfSAndrei Emeltchenko 		return;
811350ee4cfSAndrei Emeltchenko 
812350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
813350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
814350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
815350ee4cfSAndrei Emeltchenko 
816350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
817350ee4cfSAndrei Emeltchenko 
818350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
819350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
820350ee4cfSAndrei Emeltchenko 
821350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
822350ee4cfSAndrei Emeltchenko }
823350ee4cfSAndrei Emeltchenko 
82423bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
82523bb5763SJohan Hedberg {
82623bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
82723bb5763SJohan Hedberg 
82823bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
82923bb5763SJohan Hedberg 
83023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8311da177e4SLinus Torvalds }
8321da177e4SLinus Torvalds 
833928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
834928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
835928abaa7SAndrei Emeltchenko {
836928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
837928abaa7SAndrei Emeltchenko 
838928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
839928abaa7SAndrei Emeltchenko 
840928abaa7SAndrei Emeltchenko 	if (rp->status)
841928abaa7SAndrei Emeltchenko 		return;
842928abaa7SAndrei Emeltchenko 
843928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
844928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
845928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
846928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
847928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
848928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
849928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
850928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
851928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
852928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
853928abaa7SAndrei Emeltchenko 
854928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
855928abaa7SAndrei Emeltchenko }
856928abaa7SAndrei Emeltchenko 
857b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
858b0916ea0SJohan Hedberg 							struct sk_buff *skb)
859b0916ea0SJohan Hedberg {
860b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
861b0916ea0SJohan Hedberg 
862b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
863b0916ea0SJohan Hedberg 
864b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
865b0916ea0SJohan Hedberg }
866b0916ea0SJohan Hedberg 
867d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
868d5859e22SJohan Hedberg {
869d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
870d5859e22SJohan Hedberg 
871d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
872d5859e22SJohan Hedberg 
873d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
874d5859e22SJohan Hedberg }
875d5859e22SJohan Hedberg 
876d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
877d5859e22SJohan Hedberg 							struct sk_buff *skb)
878d5859e22SJohan Hedberg {
879d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
880d5859e22SJohan Hedberg 
881d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
882d5859e22SJohan Hedberg 
883d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
884d5859e22SJohan Hedberg }
885d5859e22SJohan Hedberg 
886d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
887d5859e22SJohan Hedberg 							struct sk_buff *skb)
888d5859e22SJohan Hedberg {
889d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
890d5859e22SJohan Hedberg 
891d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
892d5859e22SJohan Hedberg 
893d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
894d5859e22SJohan Hedberg }
895d5859e22SJohan Hedberg 
896d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
897d5859e22SJohan Hedberg {
898d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
899d5859e22SJohan Hedberg 
900d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
901d5859e22SJohan Hedberg 
902d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
903d5859e22SJohan Hedberg }
904d5859e22SJohan Hedberg 
905980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
906980e1a53SJohan Hedberg {
907980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
908980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
909980e1a53SJohan Hedberg 	struct hci_conn *conn;
910980e1a53SJohan Hedberg 
911980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
912980e1a53SJohan Hedberg 
91356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
91456e5cb86SJohan Hedberg 
915a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
916744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
917980e1a53SJohan Hedberg 
918980e1a53SJohan Hedberg 	if (rp->status != 0)
91956e5cb86SJohan Hedberg 		goto unlock;
920980e1a53SJohan Hedberg 
921980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
922980e1a53SJohan Hedberg 	if (!cp)
92356e5cb86SJohan Hedberg 		goto unlock;
924980e1a53SJohan Hedberg 
925980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
926980e1a53SJohan Hedberg 	if (conn)
927980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
92856e5cb86SJohan Hedberg 
92956e5cb86SJohan Hedberg unlock:
93056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
931980e1a53SJohan Hedberg }
932980e1a53SJohan Hedberg 
933980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
934980e1a53SJohan Hedberg {
935980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
936980e1a53SJohan Hedberg 
937980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
938980e1a53SJohan Hedberg 
93956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
94056e5cb86SJohan Hedberg 
941a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
942744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
943980e1a53SJohan Hedberg 								rp->status);
94456e5cb86SJohan Hedberg 
94556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
946980e1a53SJohan Hedberg }
94756e5cb86SJohan Hedberg 
9486ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9496ed58ec5SVille Tervo 				       struct sk_buff *skb)
9506ed58ec5SVille Tervo {
9516ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9526ed58ec5SVille Tervo 
9536ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9546ed58ec5SVille Tervo 
9556ed58ec5SVille Tervo 	if (rp->status)
9566ed58ec5SVille Tervo 		return;
9576ed58ec5SVille Tervo 
9586ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9596ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9606ed58ec5SVille Tervo 
9616ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9626ed58ec5SVille Tervo 
9636ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9646ed58ec5SVille Tervo 
9656ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9666ed58ec5SVille Tervo }
967980e1a53SJohan Hedberg 
968a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
969a5c29683SJohan Hedberg {
970a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
971a5c29683SJohan Hedberg 
972a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
973a5c29683SJohan Hedberg 
97456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
97556e5cb86SJohan Hedberg 
976a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
977272d90dfSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
978272d90dfSJohan Hedberg 								0, rp->status);
97956e5cb86SJohan Hedberg 
98056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
981a5c29683SJohan Hedberg }
982a5c29683SJohan Hedberg 
983a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
984a5c29683SJohan Hedberg 							struct sk_buff *skb)
985a5c29683SJohan Hedberg {
986a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
987a5c29683SJohan Hedberg 
988a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
989a5c29683SJohan Hedberg 
99056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
99156e5cb86SJohan Hedberg 
992a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
993744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
994272d90dfSJohan Hedberg 								ACL_LINK, 0,
995a5c29683SJohan Hedberg 								rp->status);
99656e5cb86SJohan Hedberg 
99756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
998a5c29683SJohan Hedberg }
999a5c29683SJohan Hedberg 
10001143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
10011143d458SBrian Gix {
10021143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10031143d458SBrian Gix 
10041143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10051143d458SBrian Gix 
10061143d458SBrian Gix 	hci_dev_lock(hdev);
10071143d458SBrian Gix 
1008a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1009272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1010272d90dfSJohan Hedberg 								0, rp->status);
10111143d458SBrian Gix 
10121143d458SBrian Gix 	hci_dev_unlock(hdev);
10131143d458SBrian Gix }
10141143d458SBrian Gix 
10151143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10161143d458SBrian Gix 							struct sk_buff *skb)
10171143d458SBrian Gix {
10181143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10191143d458SBrian Gix 
10201143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10211143d458SBrian Gix 
10221143d458SBrian Gix 	hci_dev_lock(hdev);
10231143d458SBrian Gix 
1024a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10251143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
1026272d90dfSJohan Hedberg 								ACL_LINK, 0,
10271143d458SBrian Gix 								rp->status);
10281143d458SBrian Gix 
10291143d458SBrian Gix 	hci_dev_unlock(hdev);
10301143d458SBrian Gix }
10311143d458SBrian Gix 
1032c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1033c35938b2SSzymon Janc 							struct sk_buff *skb)
1034c35938b2SSzymon Janc {
1035c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1036c35938b2SSzymon Janc 
1037c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1038c35938b2SSzymon Janc 
103956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1040744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1041c35938b2SSzymon Janc 						rp->randomizer, rp->status);
104256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1043c35938b2SSzymon Janc }
1044c35938b2SSzymon Janc 
104507f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
104607f7fa5dSAndre Guedes {
104707f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
104807f7fa5dSAndre Guedes 
104907f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
10507ba8b4beSAndre Guedes 
10517ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
10523fd24153SAndre Guedes 
10533fd24153SAndre Guedes 	if (status) {
10543fd24153SAndre Guedes 		hci_dev_lock(hdev);
10553fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
10563fd24153SAndre Guedes 		hci_dev_unlock(hdev);
10573fd24153SAndre Guedes 		return;
10583fd24153SAndre Guedes 	}
105907f7fa5dSAndre Guedes }
106007f7fa5dSAndre Guedes 
1061eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1062eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1063eb9d91f5SAndre Guedes {
1064eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1065eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1066eb9d91f5SAndre Guedes 
1067eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1068eb9d91f5SAndre Guedes 
1069eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1070eb9d91f5SAndre Guedes 	if (!cp)
1071eb9d91f5SAndre Guedes 		return;
1072eb9d91f5SAndre Guedes 
107368a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
107468a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
10757ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
10767ba8b4beSAndre Guedes 
10773fd24153SAndre Guedes 		if (status) {
10783fd24153SAndre Guedes 			hci_dev_lock(hdev);
10793fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
10803fd24153SAndre Guedes 			hci_dev_unlock(hdev);
10817ba8b4beSAndre Guedes 			return;
10823fd24153SAndre Guedes 		}
10837ba8b4beSAndre Guedes 
1084d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1085d23264a8SAndre Guedes 
1086db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1087a8f13c8cSAndre Guedes 
1088a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1089eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1090343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1091a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
109268a8aea4SAndrei Emeltchenko 		break;
109368a8aea4SAndrei Emeltchenko 
109468a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
10957ba8b4beSAndre Guedes 		if (status)
10967ba8b4beSAndre Guedes 			return;
10977ba8b4beSAndre Guedes 
1098d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1099d23264a8SAndre Guedes 
11005e0452c0SAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
11015e0452c0SAndre Guedes 
11025e0452c0SAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
11035e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
11045e0452c0SAndre Guedes 		} else {
1105c599008fSAndre Guedes 			hci_dev_lock(hdev);
1106c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1107c599008fSAndre Guedes 			hci_dev_unlock(hdev);
11085e0452c0SAndre Guedes 		}
1109c599008fSAndre Guedes 
111068a8aea4SAndrei Emeltchenko 		break;
111168a8aea4SAndrei Emeltchenko 
111268a8aea4SAndrei Emeltchenko 	default:
111368a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
111468a8aea4SAndrei Emeltchenko 		break;
111535815085SAndre Guedes 	}
1116eb9d91f5SAndre Guedes }
1117eb9d91f5SAndre Guedes 
1118a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1119a7a595f6SVinicius Costa Gomes {
1120a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1121a7a595f6SVinicius Costa Gomes 
1122a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1123a7a595f6SVinicius Costa Gomes 
1124a7a595f6SVinicius Costa Gomes 	if (rp->status)
1125a7a595f6SVinicius Costa Gomes 		return;
1126a7a595f6SVinicius Costa Gomes 
1127a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1128a7a595f6SVinicius Costa Gomes }
1129a7a595f6SVinicius Costa Gomes 
1130a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1131a7a595f6SVinicius Costa Gomes {
1132a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1133a7a595f6SVinicius Costa Gomes 
1134a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1135a7a595f6SVinicius Costa Gomes 
1136a7a595f6SVinicius Costa Gomes 	if (rp->status)
1137a7a595f6SVinicius Costa Gomes 		return;
1138a7a595f6SVinicius Costa Gomes 
1139a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1140a7a595f6SVinicius Costa Gomes }
1141a7a595f6SVinicius Costa Gomes 
1142f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1143f9b49306SAndre Guedes 							struct sk_buff *skb)
1144f9b49306SAndre Guedes {
1145f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
114606199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1147f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1148f9b49306SAndre Guedes 
1149f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1150f9b49306SAndre Guedes 
115106199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
115206199cf8SJohan Hedberg 	if (sent && test_bit(HCI_MGMT, &hdev->dev_flags))
115306199cf8SJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
115406199cf8SJohan Hedberg 
1155f9b49306SAndre Guedes 	if (status)
1156f9b49306SAndre Guedes 		return;
1157f9b49306SAndre Guedes 
1158f9b49306SAndre Guedes 	cp.page = 0x01;
1159f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1160f9b49306SAndre Guedes }
1161f9b49306SAndre Guedes 
1162a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1163a9de9248SMarcel Holtmann {
1164a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1165a9de9248SMarcel Holtmann 
1166a9de9248SMarcel Holtmann 	if (status) {
116723bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1168a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
116956e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1170a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11717a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
117256e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1173314b2381SJohan Hedberg 		return;
1174314b2381SJohan Hedberg 	}
1175314b2381SJohan Hedberg 
117689352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
117789352e7dSAndre Guedes 
117856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1179343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
118056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1181a9de9248SMarcel Holtmann }
1182a9de9248SMarcel Holtmann 
11831da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11841da177e4SLinus Torvalds {
1185a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11861da177e4SLinus Torvalds 	struct hci_conn *conn;
11871da177e4SLinus Torvalds 
1188a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1189a9de9248SMarcel Holtmann 
1190a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11911da177e4SLinus Torvalds 	if (!cp)
11921da177e4SLinus Torvalds 		return;
11931da177e4SLinus Torvalds 
11941da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11951da177e4SLinus Torvalds 
11961da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11971da177e4SLinus Torvalds 
1198a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11991da177e4SLinus Torvalds 
12001da177e4SLinus Torvalds 	if (status) {
12011da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
12024c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
12031da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
12041da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
12051da177e4SLinus Torvalds 				hci_conn_del(conn);
12064c67bc74SMarcel Holtmann 			} else
12074c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
12081da177e4SLinus Torvalds 		}
12091da177e4SLinus Torvalds 	} else {
12101da177e4SLinus Torvalds 		if (!conn) {
12111da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
12121da177e4SLinus Torvalds 			if (conn) {
1213a0c808b3SJohan Hedberg 				conn->out = true;
12141da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
12151da177e4SLinus Torvalds 			} else
1216893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12171da177e4SLinus Torvalds 		}
12181da177e4SLinus Torvalds 	}
12191da177e4SLinus Torvalds 
12201da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12211da177e4SLinus Torvalds }
12221da177e4SLinus Torvalds 
1223a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12241da177e4SLinus Torvalds {
1225a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12261da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12271da177e4SLinus Torvalds 	__u16 handle;
12281da177e4SLinus Torvalds 
1229b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1230b6a0dc82SMarcel Holtmann 
1231a9de9248SMarcel Holtmann 	if (!status)
1232a9de9248SMarcel Holtmann 		return;
1233a9de9248SMarcel Holtmann 
1234a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12351da177e4SLinus Torvalds 	if (!cp)
1236a9de9248SMarcel Holtmann 		return;
12371da177e4SLinus Torvalds 
12381da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12391da177e4SLinus Torvalds 
1240a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
12411da177e4SLinus Torvalds 
12421da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12431da177e4SLinus Torvalds 
12441da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12455a08ecceSAndrei Emeltchenko 	if (acl) {
12465a08ecceSAndrei Emeltchenko 		sco = acl->link;
12475a08ecceSAndrei Emeltchenko 		if (sco) {
12481da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12491da177e4SLinus Torvalds 
12501da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12511da177e4SLinus Torvalds 			hci_conn_del(sco);
12521da177e4SLinus Torvalds 		}
12535a08ecceSAndrei Emeltchenko 	}
12541da177e4SLinus Torvalds 
12551da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12561da177e4SLinus Torvalds }
12571da177e4SLinus Torvalds 
1258f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1259f8558555SMarcel Holtmann {
1260f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1261f8558555SMarcel Holtmann 	struct hci_conn *conn;
1262f8558555SMarcel Holtmann 
1263f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1264f8558555SMarcel Holtmann 
1265f8558555SMarcel Holtmann 	if (!status)
1266f8558555SMarcel Holtmann 		return;
1267f8558555SMarcel Holtmann 
1268f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1269f8558555SMarcel Holtmann 	if (!cp)
1270f8558555SMarcel Holtmann 		return;
1271f8558555SMarcel Holtmann 
1272f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1273f8558555SMarcel Holtmann 
1274f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1275f8558555SMarcel Holtmann 	if (conn) {
1276f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1277f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1278f8558555SMarcel Holtmann 			hci_conn_put(conn);
1279f8558555SMarcel Holtmann 		}
1280f8558555SMarcel Holtmann 	}
1281f8558555SMarcel Holtmann 
1282f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1283f8558555SMarcel Holtmann }
1284f8558555SMarcel Holtmann 
1285f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1286f8558555SMarcel Holtmann {
1287f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1288f8558555SMarcel Holtmann 	struct hci_conn *conn;
1289f8558555SMarcel Holtmann 
1290f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1291f8558555SMarcel Holtmann 
1292f8558555SMarcel Holtmann 	if (!status)
1293f8558555SMarcel Holtmann 		return;
1294f8558555SMarcel Holtmann 
1295f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1296f8558555SMarcel Holtmann 	if (!cp)
1297f8558555SMarcel Holtmann 		return;
1298f8558555SMarcel Holtmann 
1299f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1300f8558555SMarcel Holtmann 
1301f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1302f8558555SMarcel Holtmann 	if (conn) {
1303f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1304f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1305f8558555SMarcel Holtmann 			hci_conn_put(conn);
1306f8558555SMarcel Holtmann 		}
1307f8558555SMarcel Holtmann 	}
1308f8558555SMarcel Holtmann 
1309f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1310f8558555SMarcel Holtmann }
1311f8558555SMarcel Holtmann 
1312127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1313392599b9SJohan Hedberg 							struct hci_conn *conn)
1314392599b9SJohan Hedberg {
1315392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1316392599b9SJohan Hedberg 		return 0;
1317392599b9SJohan Hedberg 
1318765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1319392599b9SJohan Hedberg 		return 0;
1320392599b9SJohan Hedberg 
1321392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1322e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1323aa64a8b5SJohan Hedberg 	if (!hci_conn_ssp_enabled(conn) &&
1324e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1325e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1326392599b9SJohan Hedberg 		return 0;
1327392599b9SJohan Hedberg 
1328392599b9SJohan Hedberg 	return 1;
1329392599b9SJohan Hedberg }
1330392599b9SJohan Hedberg 
133130dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
133230dc78e1SJohan Hedberg {
133330dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
133430dc78e1SJohan Hedberg 
133530dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
133630dc78e1SJohan Hedberg 
133730dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
133830dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
133930dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
134030dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
134130dc78e1SJohan Hedberg 
134230dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
134330dc78e1SJohan Hedberg }
134430dc78e1SJohan Hedberg 
1345b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
134630dc78e1SJohan Hedberg {
134730dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
134830dc78e1SJohan Hedberg 	struct inquiry_entry *e;
134930dc78e1SJohan Hedberg 
1350b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1351b644ba33SJohan Hedberg 		return false;
1352b644ba33SJohan Hedberg 
1353b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1354b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1355b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1356b644ba33SJohan Hedberg 		return true;
1357b644ba33SJohan Hedberg 	}
1358b644ba33SJohan Hedberg 
1359b644ba33SJohan Hedberg 	return false;
1360b644ba33SJohan Hedberg }
1361b644ba33SJohan Hedberg 
1362b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1363b644ba33SJohan Hedberg 					bdaddr_t *bdaddr, u8 *name, u8 name_len)
1364b644ba33SJohan Hedberg {
1365b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1366b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1367b644ba33SJohan Hedberg 
1368b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
1369b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00,
1370b644ba33SJohan Hedberg 					name, name_len, conn->dev_class);
1371b644ba33SJohan Hedberg 
1372b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1373b644ba33SJohan Hedberg 		return;
1374b644ba33SJohan Hedberg 
137530dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
137630dc78e1SJohan Hedberg 		goto discov_complete;
137730dc78e1SJohan Hedberg 
137830dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
137930dc78e1SJohan Hedberg 		return;
138030dc78e1SJohan Hedberg 
138130dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
138230dc78e1SJohan Hedberg 	if (e) {
138330dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
138430dc78e1SJohan Hedberg 		list_del(&e->list);
1385b644ba33SJohan Hedberg 		if (name)
1386b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1387b644ba33SJohan Hedberg 					e->data.rssi, name, name_len);
138830dc78e1SJohan Hedberg 	}
138930dc78e1SJohan Hedberg 
1390b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
139130dc78e1SJohan Hedberg 		return;
139230dc78e1SJohan Hedberg 
139330dc78e1SJohan Hedberg discov_complete:
139430dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
139530dc78e1SJohan Hedberg }
139630dc78e1SJohan Hedberg 
1397a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13981da177e4SLinus Torvalds {
1399127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1400127178d2SJohan Hedberg 	struct hci_conn *conn;
1401127178d2SJohan Hedberg 
1402a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1403127178d2SJohan Hedberg 
1404127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1405127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1406127178d2SJohan Hedberg 	if (!status)
1407127178d2SJohan Hedberg 		return;
1408127178d2SJohan Hedberg 
1409127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1410127178d2SJohan Hedberg 	if (!cp)
1411127178d2SJohan Hedberg 		return;
1412127178d2SJohan Hedberg 
1413127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1414127178d2SJohan Hedberg 
1415127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1416b644ba33SJohan Hedberg 
1417b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1418b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1419b644ba33SJohan Hedberg 
142079c6c70cSJohan Hedberg 	if (!conn)
142179c6c70cSJohan Hedberg 		goto unlock;
142279c6c70cSJohan Hedberg 
142379c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
142479c6c70cSJohan Hedberg 		goto unlock;
142579c6c70cSJohan Hedberg 
142651a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1427127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1428127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1429127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1430127178d2SJohan Hedberg 	}
1431127178d2SJohan Hedberg 
143279c6c70cSJohan Hedberg unlock:
1433127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1434a9de9248SMarcel Holtmann }
14351da177e4SLinus Torvalds 
1436769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1437769be974SMarcel Holtmann {
1438769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1439769be974SMarcel Holtmann 	struct hci_conn *conn;
1440769be974SMarcel Holtmann 
1441769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1442769be974SMarcel Holtmann 
1443769be974SMarcel Holtmann 	if (!status)
1444769be974SMarcel Holtmann 		return;
1445769be974SMarcel Holtmann 
1446769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1447769be974SMarcel Holtmann 	if (!cp)
1448769be974SMarcel Holtmann 		return;
1449769be974SMarcel Holtmann 
1450769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1451769be974SMarcel Holtmann 
1452769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1453769be974SMarcel Holtmann 	if (conn) {
1454769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1455769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1456769be974SMarcel Holtmann 			hci_conn_put(conn);
1457769be974SMarcel Holtmann 		}
1458769be974SMarcel Holtmann 	}
1459769be974SMarcel Holtmann 
1460769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1461769be974SMarcel Holtmann }
1462769be974SMarcel Holtmann 
1463769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1464769be974SMarcel Holtmann {
1465769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1466769be974SMarcel Holtmann 	struct hci_conn *conn;
1467769be974SMarcel Holtmann 
1468769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1469769be974SMarcel Holtmann 
1470769be974SMarcel Holtmann 	if (!status)
1471769be974SMarcel Holtmann 		return;
1472769be974SMarcel Holtmann 
1473769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1474769be974SMarcel Holtmann 	if (!cp)
1475769be974SMarcel Holtmann 		return;
1476769be974SMarcel Holtmann 
1477769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1478769be974SMarcel Holtmann 
1479769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1480769be974SMarcel Holtmann 	if (conn) {
1481769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1482769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1483769be974SMarcel Holtmann 			hci_conn_put(conn);
1484769be974SMarcel Holtmann 		}
1485769be974SMarcel Holtmann 	}
1486769be974SMarcel Holtmann 
1487769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1488769be974SMarcel Holtmann }
1489769be974SMarcel Holtmann 
1490a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1491a9de9248SMarcel Holtmann {
1492b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1493b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1494b6a0dc82SMarcel Holtmann 	__u16 handle;
1495b6a0dc82SMarcel Holtmann 
1496a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1497b6a0dc82SMarcel Holtmann 
1498b6a0dc82SMarcel Holtmann 	if (!status)
1499b6a0dc82SMarcel Holtmann 		return;
1500b6a0dc82SMarcel Holtmann 
1501b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1502b6a0dc82SMarcel Holtmann 	if (!cp)
1503b6a0dc82SMarcel Holtmann 		return;
1504b6a0dc82SMarcel Holtmann 
1505b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1506b6a0dc82SMarcel Holtmann 
1507b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1508b6a0dc82SMarcel Holtmann 
1509b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1510b6a0dc82SMarcel Holtmann 
1511b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15125a08ecceSAndrei Emeltchenko 	if (acl) {
15135a08ecceSAndrei Emeltchenko 		sco = acl->link;
15145a08ecceSAndrei Emeltchenko 		if (sco) {
1515b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1516b6a0dc82SMarcel Holtmann 
1517b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1518b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1519b6a0dc82SMarcel Holtmann 		}
15205a08ecceSAndrei Emeltchenko 	}
1521b6a0dc82SMarcel Holtmann 
1522b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1523a9de9248SMarcel Holtmann }
1524a9de9248SMarcel Holtmann 
1525a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1526a9de9248SMarcel Holtmann {
1527a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
152804837f64SMarcel Holtmann 	struct hci_conn *conn;
152904837f64SMarcel Holtmann 
1530a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1531a9de9248SMarcel Holtmann 
1532a9de9248SMarcel Holtmann 	if (!status)
1533a9de9248SMarcel Holtmann 		return;
1534a9de9248SMarcel Holtmann 
1535a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
153604837f64SMarcel Holtmann 	if (!cp)
1537a9de9248SMarcel Holtmann 		return;
153804837f64SMarcel Holtmann 
153904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
154004837f64SMarcel Holtmann 
154104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1542e73439d8SMarcel Holtmann 	if (conn) {
154351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
154404837f64SMarcel Holtmann 
154551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1546e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1547e73439d8SMarcel Holtmann 	}
1548e73439d8SMarcel Holtmann 
154904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
155004837f64SMarcel Holtmann }
155104837f64SMarcel Holtmann 
1552a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1553a9de9248SMarcel Holtmann {
1554a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
155504837f64SMarcel Holtmann 	struct hci_conn *conn;
155604837f64SMarcel Holtmann 
1557a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1558a9de9248SMarcel Holtmann 
1559a9de9248SMarcel Holtmann 	if (!status)
1560a9de9248SMarcel Holtmann 		return;
1561a9de9248SMarcel Holtmann 
1562a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
156304837f64SMarcel Holtmann 	if (!cp)
1564a9de9248SMarcel Holtmann 		return;
156504837f64SMarcel Holtmann 
156604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
156704837f64SMarcel Holtmann 
156804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1569e73439d8SMarcel Holtmann 	if (conn) {
157051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
157104837f64SMarcel Holtmann 
157251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1573e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1574e73439d8SMarcel Holtmann 	}
1575e73439d8SMarcel Holtmann 
157604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
157704837f64SMarcel Holtmann }
157804837f64SMarcel Holtmann 
157988c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
158088c3df13SJohan Hedberg {
158188c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
158288c3df13SJohan Hedberg 	struct hci_conn *conn;
158388c3df13SJohan Hedberg 
158488c3df13SJohan Hedberg 	if (!status)
158588c3df13SJohan Hedberg 		return;
158688c3df13SJohan Hedberg 
158788c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
158888c3df13SJohan Hedberg 	if (!cp)
158988c3df13SJohan Hedberg 		return;
159088c3df13SJohan Hedberg 
159188c3df13SJohan Hedberg 	hci_dev_lock(hdev);
159288c3df13SJohan Hedberg 
159388c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
159488c3df13SJohan Hedberg 	if (conn)
159588c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
159688c3df13SJohan Hedberg 						conn->dst_type, status);
159788c3df13SJohan Hedberg 
159888c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
159988c3df13SJohan Hedberg }
160088c3df13SJohan Hedberg 
1601fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1602fcd89c09SVille Tervo {
1603fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1604fcd89c09SVille Tervo 	struct hci_conn *conn;
1605fcd89c09SVille Tervo 
1606fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1607fcd89c09SVille Tervo 
1608fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1609fcd89c09SVille Tervo 	if (!cp)
1610fcd89c09SVille Tervo 		return;
1611fcd89c09SVille Tervo 
1612fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1613fcd89c09SVille Tervo 
1614fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1615fcd89c09SVille Tervo 
1616fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1617fcd89c09SVille Tervo 		conn);
1618fcd89c09SVille Tervo 
1619fcd89c09SVille Tervo 	if (status) {
1620fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1621fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1622fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1623fcd89c09SVille Tervo 			hci_conn_del(conn);
1624fcd89c09SVille Tervo 		}
1625fcd89c09SVille Tervo 	} else {
1626fcd89c09SVille Tervo 		if (!conn) {
1627fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
162829b7988aSAndre Guedes 			if (conn) {
162929b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1630a0c808b3SJohan Hedberg 				conn->out = true;
163129b7988aSAndre Guedes 			} else {
1632fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1633fcd89c09SVille Tervo 			}
1634fcd89c09SVille Tervo 		}
163529b7988aSAndre Guedes 	}
1636fcd89c09SVille Tervo 
1637fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1638fcd89c09SVille Tervo }
1639fcd89c09SVille Tervo 
1640a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1641a7a595f6SVinicius Costa Gomes {
1642a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1643a7a595f6SVinicius Costa Gomes }
1644a7a595f6SVinicius Costa Gomes 
16451da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16461da177e4SLinus Torvalds {
16471da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
164830dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
164930dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16501da177e4SLinus Torvalds 
16511da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
16521da177e4SLinus Torvalds 
165323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16546bd57416SMarcel Holtmann 
1655a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
165689352e7dSAndre Guedes 
165789352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
165889352e7dSAndre Guedes 		return;
165989352e7dSAndre Guedes 
1660a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
166130dc78e1SJohan Hedberg 		return;
166230dc78e1SJohan Hedberg 
166356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
166430dc78e1SJohan Hedberg 
1665343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
166630dc78e1SJohan Hedberg 		goto unlock;
166730dc78e1SJohan Hedberg 
166830dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1669ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
167030dc78e1SJohan Hedberg 		goto unlock;
167130dc78e1SJohan Hedberg 	}
167230dc78e1SJohan Hedberg 
167330dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
167430dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
167530dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
167630dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
167730dc78e1SJohan Hedberg 	} else {
167830dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
167930dc78e1SJohan Hedberg 	}
168030dc78e1SJohan Hedberg 
168130dc78e1SJohan Hedberg unlock:
168256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16831da177e4SLinus Torvalds }
16841da177e4SLinus Torvalds 
16851da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16861da177e4SLinus Torvalds {
168745bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1688a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16891da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16901da177e4SLinus Torvalds 
16911da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16921da177e4SLinus Torvalds 
169345bb4bf0SMarcel Holtmann 	if (!num_rsp)
169445bb4bf0SMarcel Holtmann 		return;
169545bb4bf0SMarcel Holtmann 
16961da177e4SLinus Torvalds 	hci_dev_lock(hdev);
169745bb4bf0SMarcel Holtmann 
1698e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1699388fc8faSJohan Hedberg 		bool name_known, ssp;
17003175405bSJohan Hedberg 
17011da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
17021da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
17031da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
17041da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
17051da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
17061da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17071da177e4SLinus Torvalds 		data.rssi		= 0x00;
170841a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17093175405bSJohan Hedberg 
1710388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
171148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
1712388fc8faSJohan Hedberg 					info->dev_class, 0, !name_known, ssp,
17137d262f86SAndre Guedes 					NULL, 0);
17141da177e4SLinus Torvalds 	}
171545bb4bf0SMarcel Holtmann 
17161da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17171da177e4SLinus Torvalds }
17181da177e4SLinus Torvalds 
1719a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17201da177e4SLinus Torvalds {
1721a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1722a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17231da177e4SLinus Torvalds 
1724a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
172545bb4bf0SMarcel Holtmann 
17261da177e4SLinus Torvalds 	hci_dev_lock(hdev);
172745bb4bf0SMarcel Holtmann 
1728a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17299499237aSMarcel Holtmann 	if (!conn) {
17309499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17319499237aSMarcel Holtmann 			goto unlock;
17329499237aSMarcel Holtmann 
17339499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1734a9de9248SMarcel Holtmann 		if (!conn)
1735a9de9248SMarcel Holtmann 			goto unlock;
173645bb4bf0SMarcel Holtmann 
17379499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17389499237aSMarcel Holtmann 	}
17399499237aSMarcel Holtmann 
1740a9de9248SMarcel Holtmann 	if (!ev->status) {
1741a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1742769be974SMarcel Holtmann 
1743769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1744769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1745769be974SMarcel Holtmann 			hci_conn_hold(conn);
1746052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1747769be974SMarcel Holtmann 		} else
1748a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1749a9de9248SMarcel Holtmann 
17509eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
17517d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17527d0db0a3SMarcel Holtmann 
1753a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1754a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1755a9de9248SMarcel Holtmann 
1756a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1757a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1758a9de9248SMarcel Holtmann 
1759a9de9248SMarcel Holtmann 		/* Get remote features */
1760a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1761a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1762a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1763769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1764769be974SMarcel Holtmann 							sizeof(cp), &cp);
176545bb4bf0SMarcel Holtmann 		}
1766a9de9248SMarcel Holtmann 
1767a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1768d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1769a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1770a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1771a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1772a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1773a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1774a9de9248SMarcel Holtmann 		}
177517d5c04cSJohan Hedberg 	} else {
1776a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
177717d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1778744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
177948264f06SJohan Hedberg 						conn->dst_type, ev->status);
178017d5c04cSJohan Hedberg 	}
178145bb4bf0SMarcel Holtmann 
1782e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1783e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
178445bb4bf0SMarcel Holtmann 
1785769be974SMarcel Holtmann 	if (ev->status) {
1786a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1787a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1788c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1789c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1790a9de9248SMarcel Holtmann 
1791a9de9248SMarcel Holtmann unlock:
17921da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1793a9de9248SMarcel Holtmann 
1794a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
17951da177e4SLinus Torvalds }
17961da177e4SLinus Torvalds 
17971da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17981da177e4SLinus Torvalds {
1799a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
18001da177e4SLinus Torvalds 	int mask = hdev->link_mode;
18011da177e4SLinus Torvalds 
1802a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
18031da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
18041da177e4SLinus Torvalds 
18051da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
18061da177e4SLinus Torvalds 
1807138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1808138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
18091da177e4SLinus Torvalds 		/* Connection accepted */
1810c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
18111da177e4SLinus Torvalds 		struct hci_conn *conn;
18121da177e4SLinus Torvalds 
18131da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1814b6a0dc82SMarcel Holtmann 
1815cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1816cc11b9c1SAndrei Emeltchenko 		if (ie)
1817c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1818c7bdd502SMarcel Holtmann 
18191da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
18201da177e4SLinus Torvalds 		if (!conn) {
1821cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1822cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1823893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
18241da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
18251da177e4SLinus Torvalds 				return;
18261da177e4SLinus Torvalds 			}
18271da177e4SLinus Torvalds 		}
1828b6a0dc82SMarcel Holtmann 
18291da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
18301da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1831b6a0dc82SMarcel Holtmann 
18321da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
18331da177e4SLinus Torvalds 
1834b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1835b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1836b6a0dc82SMarcel Holtmann 
18371da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
18381da177e4SLinus Torvalds 
18391da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
18401da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
18411da177e4SLinus Torvalds 			else
18421da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
18431da177e4SLinus Torvalds 
1844b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1845b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1846b6a0dc82SMarcel Holtmann 		} else {
1847b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1848b6a0dc82SMarcel Holtmann 
1849b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1850a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1851b6a0dc82SMarcel Holtmann 
1852b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1853b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1854b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1855b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1856b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1857b6a0dc82SMarcel Holtmann 
1858b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1859b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1860b6a0dc82SMarcel Holtmann 		}
18611da177e4SLinus Torvalds 	} else {
18621da177e4SLinus Torvalds 		/* Connection rejected */
18631da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18641da177e4SLinus Torvalds 
18651da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18669f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1867a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18681da177e4SLinus Torvalds 	}
18691da177e4SLinus Torvalds }
18701da177e4SLinus Torvalds 
18711da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18721da177e4SLinus Torvalds {
1873a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
187404837f64SMarcel Holtmann 	struct hci_conn *conn;
18751da177e4SLinus Torvalds 
18761da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
18771da177e4SLinus Torvalds 
18781da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18791da177e4SLinus Torvalds 
188004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1881f7520543SJohan Hedberg 	if (!conn)
1882f7520543SJohan Hedberg 		goto unlock;
1883f7520543SJohan Hedberg 
188437d9ef76SJohan Hedberg 	if (ev->status == 0)
18851da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18867d0db0a3SMarcel Holtmann 
1887b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1888b644ba33SJohan Hedberg 			(conn->type == ACL_LINK || conn->type == LE_LINK)) {
188937d9ef76SJohan Hedberg 		if (ev->status != 0)
189088c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
189188c3df13SJohan Hedberg 						conn->dst_type, ev->status);
189237d9ef76SJohan Hedberg 		else
1893afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
189448264f06SJohan Hedberg 							conn->dst_type);
189537d9ef76SJohan Hedberg 	}
1896f7520543SJohan Hedberg 
189737d9ef76SJohan Hedberg 	if (ev->status == 0) {
18982950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
18991da177e4SLinus Torvalds 		hci_conn_del(conn);
190037d9ef76SJohan Hedberg 	}
19011da177e4SLinus Torvalds 
1902f7520543SJohan Hedberg unlock:
19031da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19041da177e4SLinus Torvalds }
19051da177e4SLinus Torvalds 
1906a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1907a9de9248SMarcel Holtmann {
1908a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1909a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1910a9de9248SMarcel Holtmann 
1911a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1912a9de9248SMarcel Holtmann 
1913a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1914a9de9248SMarcel Holtmann 
1915a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1916d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1917d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1918d7556e20SWaldemar Rymarkiewicz 
1919765c2a96SJohan Hedberg 	if (!ev->status) {
1920aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
192151a8efd7SJohan Hedberg 				test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1922d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
192319f8def0SWaldemar Rymarkiewicz 		} else {
1924a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1925765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
192619f8def0SWaldemar Rymarkiewicz 		}
19272a611692SJohan Hedberg 	} else {
1928bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1929bab73cb6SJohan Hedberg 								ev->status);
19302a611692SJohan Hedberg 	}
1931a9de9248SMarcel Holtmann 
193251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
193351a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1934a9de9248SMarcel Holtmann 
1935f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1936aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1937f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1938f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1939f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1940d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1941d7556e20SWaldemar Rymarkiewicz 									&cp);
1942f8558555SMarcel Holtmann 		} else {
1943f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1944f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1945f8558555SMarcel Holtmann 			hci_conn_put(conn);
1946f8558555SMarcel Holtmann 		}
1947052b30b0SMarcel Holtmann 	} else {
1948a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1949a9de9248SMarcel Holtmann 
1950052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1951052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1952052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1953052b30b0SMarcel Holtmann 	}
1954052b30b0SMarcel Holtmann 
195551a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1956a9de9248SMarcel Holtmann 		if (!ev->status) {
1957a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1958f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1959f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1960d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1961d7556e20SWaldemar Rymarkiewicz 									&cp);
1962a9de9248SMarcel Holtmann 		} else {
196351a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1964a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1965a9de9248SMarcel Holtmann 		}
1966a9de9248SMarcel Holtmann 	}
1967a9de9248SMarcel Holtmann 
1968d7556e20SWaldemar Rymarkiewicz unlock:
1969a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1970a9de9248SMarcel Holtmann }
1971a9de9248SMarcel Holtmann 
1972a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1973a9de9248SMarcel Holtmann {
1974127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1975127178d2SJohan Hedberg 	struct hci_conn *conn;
1976127178d2SJohan Hedberg 
1977a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1978a9de9248SMarcel Holtmann 
1979a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1980127178d2SJohan Hedberg 
1981127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1982127178d2SJohan Hedberg 
1983127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1984b644ba33SJohan Hedberg 
1985b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1986b644ba33SJohan Hedberg 		goto check_auth;
1987b644ba33SJohan Hedberg 
1988b644ba33SJohan Hedberg 	if (ev->status == 0)
1989b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1990b644ba33SJohan Hedberg 					strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1991b644ba33SJohan Hedberg 	else
1992b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1993b644ba33SJohan Hedberg 
1994b644ba33SJohan Hedberg check_auth:
199579c6c70cSJohan Hedberg 	if (!conn)
199679c6c70cSJohan Hedberg 		goto unlock;
199779c6c70cSJohan Hedberg 
199879c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
199979c6c70cSJohan Hedberg 		goto unlock;
200079c6c70cSJohan Hedberg 
200151a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2002127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2003127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2004127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2005127178d2SJohan Hedberg 	}
2006127178d2SJohan Hedberg 
200779c6c70cSJohan Hedberg unlock:
2008127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2009a9de9248SMarcel Holtmann }
2010a9de9248SMarcel Holtmann 
2011a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2012a9de9248SMarcel Holtmann {
2013a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2014a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2015a9de9248SMarcel Holtmann 
2016a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2017a9de9248SMarcel Holtmann 
2018a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2019a9de9248SMarcel Holtmann 
2020a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2021a9de9248SMarcel Holtmann 	if (conn) {
2022a9de9248SMarcel Holtmann 		if (!ev->status) {
2023ae293196SMarcel Holtmann 			if (ev->encrypt) {
2024ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2025ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2026a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2027da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2028ae293196SMarcel Holtmann 			} else
2029a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2030a9de9248SMarcel Holtmann 		}
2031a9de9248SMarcel Holtmann 
203251a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2033a9de9248SMarcel Holtmann 
2034f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2035f8558555SMarcel Holtmann 			if (!ev->status)
2036f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2037f8558555SMarcel Holtmann 
2038f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2039f8558555SMarcel Holtmann 			hci_conn_put(conn);
2040f8558555SMarcel Holtmann 		} else
2041a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2042a9de9248SMarcel Holtmann 	}
2043a9de9248SMarcel Holtmann 
2044a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2045a9de9248SMarcel Holtmann }
2046a9de9248SMarcel Holtmann 
2047a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2048a9de9248SMarcel Holtmann {
2049a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2050a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2051a9de9248SMarcel Holtmann 
2052a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2053a9de9248SMarcel Holtmann 
2054a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2055a9de9248SMarcel Holtmann 
2056a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2057a9de9248SMarcel Holtmann 	if (conn) {
2058a9de9248SMarcel Holtmann 		if (!ev->status)
2059a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2060a9de9248SMarcel Holtmann 
206151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2062a9de9248SMarcel Holtmann 
2063a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2064a9de9248SMarcel Holtmann 	}
2065a9de9248SMarcel Holtmann 
2066a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2067a9de9248SMarcel Holtmann }
2068a9de9248SMarcel Holtmann 
2069a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2070a9de9248SMarcel Holtmann {
2071a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2072a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2073a9de9248SMarcel Holtmann 
2074a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2075a9de9248SMarcel Holtmann 
2076a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2077a9de9248SMarcel Holtmann 
2078a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2079ccd556feSJohan Hedberg 	if (!conn)
2080ccd556feSJohan Hedberg 		goto unlock;
2081ccd556feSJohan Hedberg 
2082769be974SMarcel Holtmann 	if (!ev->status)
2083a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2084a9de9248SMarcel Holtmann 
2085ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2086ccd556feSJohan Hedberg 		goto unlock;
2087ccd556feSJohan Hedberg 
2088ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2089769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2090769be974SMarcel Holtmann 		cp.handle = ev->handle;
2091769be974SMarcel Holtmann 		cp.page = 0x01;
2092ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2093769be974SMarcel Holtmann 							sizeof(cp), &cp);
2094392599b9SJohan Hedberg 		goto unlock;
2095392599b9SJohan Hedberg 	}
2096392599b9SJohan Hedberg 
2097127178d2SJohan Hedberg 	if (!ev->status) {
2098127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2099127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2100127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2101127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2102127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2103b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2104b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2105b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2106b644ba33SJohan Hedberg 						conn->dev_class);
2107392599b9SJohan Hedberg 
2108127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2109769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2110769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2111769be974SMarcel Holtmann 		hci_conn_put(conn);
2112769be974SMarcel Holtmann 	}
2113769be974SMarcel Holtmann 
2114ccd556feSJohan Hedberg unlock:
2115a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2116a9de9248SMarcel Holtmann }
2117a9de9248SMarcel Holtmann 
2118a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2119a9de9248SMarcel Holtmann {
2120a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2121a9de9248SMarcel Holtmann }
2122a9de9248SMarcel Holtmann 
2123a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2124a9de9248SMarcel Holtmann {
2125a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2126a9de9248SMarcel Holtmann }
2127a9de9248SMarcel Holtmann 
2128a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2129a9de9248SMarcel Holtmann {
2130a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2131a9de9248SMarcel Holtmann 	__u16 opcode;
2132a9de9248SMarcel Holtmann 
2133a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2134a9de9248SMarcel Holtmann 
2135a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2136a9de9248SMarcel Holtmann 
2137a9de9248SMarcel Holtmann 	switch (opcode) {
2138a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2139a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2140a9de9248SMarcel Holtmann 		break;
2141a9de9248SMarcel Holtmann 
2142a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2143a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2144a9de9248SMarcel Holtmann 		break;
2145a9de9248SMarcel Holtmann 
2146a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2147a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2148a9de9248SMarcel Holtmann 		break;
2149a9de9248SMarcel Holtmann 
2150a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2151a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2152a9de9248SMarcel Holtmann 		break;
2153a9de9248SMarcel Holtmann 
2154e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2155e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2156e4e8e37cSMarcel Holtmann 		break;
2157e4e8e37cSMarcel Holtmann 
2158a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2159a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2160a9de9248SMarcel Holtmann 		break;
2161a9de9248SMarcel Holtmann 
2162e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2163e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2164e4e8e37cSMarcel Holtmann 		break;
2165e4e8e37cSMarcel Holtmann 
2166e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2167e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2168e4e8e37cSMarcel Holtmann 		break;
2169e4e8e37cSMarcel Holtmann 
2170a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2171a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2172a9de9248SMarcel Holtmann 		break;
2173a9de9248SMarcel Holtmann 
2174a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2175a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2176a9de9248SMarcel Holtmann 		break;
2177a9de9248SMarcel Holtmann 
2178a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2179a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2180a9de9248SMarcel Holtmann 		break;
2181a9de9248SMarcel Holtmann 
2182a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2183a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2184a9de9248SMarcel Holtmann 		break;
2185a9de9248SMarcel Holtmann 
2186a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2187a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2188a9de9248SMarcel Holtmann 		break;
2189a9de9248SMarcel Holtmann 
2190a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2191a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2192a9de9248SMarcel Holtmann 		break;
2193a9de9248SMarcel Holtmann 
2194a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2195a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2196a9de9248SMarcel Holtmann 		break;
2197a9de9248SMarcel Holtmann 
2198a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2199a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2200a9de9248SMarcel Holtmann 		break;
2201a9de9248SMarcel Holtmann 
2202a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2203a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2204a9de9248SMarcel Holtmann 		break;
2205a9de9248SMarcel Holtmann 
2206a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2207a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2208a9de9248SMarcel Holtmann 		break;
2209a9de9248SMarcel Holtmann 
2210a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2211a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2212a9de9248SMarcel Holtmann 		break;
2213a9de9248SMarcel Holtmann 
2214333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2215333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2216333140b5SMarcel Holtmann 		break;
2217333140b5SMarcel Holtmann 
2218a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2219a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2220a9de9248SMarcel Holtmann 		break;
2221a9de9248SMarcel Holtmann 
2222a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2223a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2224a9de9248SMarcel Holtmann 		break;
2225a9de9248SMarcel Holtmann 
2226a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2227a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2228a9de9248SMarcel Holtmann 		break;
2229a9de9248SMarcel Holtmann 
2230971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2231971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2232971e3a4bSAndre Guedes 		break;
2233971e3a4bSAndre Guedes 
2234a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2235a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2236a9de9248SMarcel Holtmann 		break;
2237a9de9248SMarcel Holtmann 
2238a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2239a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2240a9de9248SMarcel Holtmann 		break;
2241a9de9248SMarcel Holtmann 
2242350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2243350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2244350ee4cfSAndrei Emeltchenko 		break;
2245350ee4cfSAndrei Emeltchenko 
224623bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
224723bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
224823bb5763SJohan Hedberg 		break;
224923bb5763SJohan Hedberg 
22501e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22511e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22521e89cffbSAndrei Emeltchenko 		break;
22531e89cffbSAndrei Emeltchenko 
2254928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2255928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2256928abaa7SAndrei Emeltchenko 		break;
2257928abaa7SAndrei Emeltchenko 
2258b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2259b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2260b0916ea0SJohan Hedberg 		break;
2261b0916ea0SJohan Hedberg 
2262d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2263d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2264d5859e22SJohan Hedberg 		break;
2265d5859e22SJohan Hedberg 
2266d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2267d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2268d5859e22SJohan Hedberg 		break;
2269d5859e22SJohan Hedberg 
2270d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2271d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2272d5859e22SJohan Hedberg 		break;
2273d5859e22SJohan Hedberg 
2274d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2275d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2276d5859e22SJohan Hedberg 		break;
2277d5859e22SJohan Hedberg 
2278980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2279980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2280980e1a53SJohan Hedberg 		break;
2281980e1a53SJohan Hedberg 
2282980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2283980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2284980e1a53SJohan Hedberg 		break;
2285980e1a53SJohan Hedberg 
2286c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2287c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2288c35938b2SSzymon Janc 		break;
2289c35938b2SSzymon Janc 
22906ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22916ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22926ed58ec5SVille Tervo 		break;
22936ed58ec5SVille Tervo 
2294a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2295a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2296a5c29683SJohan Hedberg 		break;
2297a5c29683SJohan Hedberg 
2298a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2299a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2300a5c29683SJohan Hedberg 		break;
2301a5c29683SJohan Hedberg 
23021143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
23031143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
23041143d458SBrian Gix 		break;
23051143d458SBrian Gix 
23061143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23071143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
230807f7fa5dSAndre Guedes 
230907f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
231007f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
23111143d458SBrian Gix 		break;
23121143d458SBrian Gix 
2313eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2314eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2315eb9d91f5SAndre Guedes 		break;
2316eb9d91f5SAndre Guedes 
2317a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2318a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2319a7a595f6SVinicius Costa Gomes 		break;
2320a7a595f6SVinicius Costa Gomes 
2321a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2322a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2323a7a595f6SVinicius Costa Gomes 		break;
2324a7a595f6SVinicius Costa Gomes 
2325f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2326f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2327f9b49306SAndre Guedes 		break;
2328f9b49306SAndre Guedes 
2329a9de9248SMarcel Holtmann 	default:
2330a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2331a9de9248SMarcel Holtmann 		break;
2332a9de9248SMarcel Holtmann 	}
2333a9de9248SMarcel Holtmann 
23346bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23356bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23366bd32326SVille Tervo 
2337a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2338a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2339a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2340c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2341a9de9248SMarcel Holtmann 	}
2342a9de9248SMarcel Holtmann }
2343a9de9248SMarcel Holtmann 
2344a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2345a9de9248SMarcel Holtmann {
2346a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2347a9de9248SMarcel Holtmann 	__u16 opcode;
2348a9de9248SMarcel Holtmann 
2349a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2350a9de9248SMarcel Holtmann 
2351a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2352a9de9248SMarcel Holtmann 
2353a9de9248SMarcel Holtmann 	switch (opcode) {
2354a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2355a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2356a9de9248SMarcel Holtmann 		break;
2357a9de9248SMarcel Holtmann 
2358a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2359a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2360a9de9248SMarcel Holtmann 		break;
2361a9de9248SMarcel Holtmann 
2362a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2363a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2364a9de9248SMarcel Holtmann 		break;
2365a9de9248SMarcel Holtmann 
2366f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2367f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2368f8558555SMarcel Holtmann 		break;
2369f8558555SMarcel Holtmann 
2370f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2371f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2372f8558555SMarcel Holtmann 		break;
2373f8558555SMarcel Holtmann 
2374a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2375a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2376a9de9248SMarcel Holtmann 		break;
2377a9de9248SMarcel Holtmann 
2378769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2379769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2380769be974SMarcel Holtmann 		break;
2381769be974SMarcel Holtmann 
2382769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2383769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2384769be974SMarcel Holtmann 		break;
2385769be974SMarcel Holtmann 
2386a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2387a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2388a9de9248SMarcel Holtmann 		break;
2389a9de9248SMarcel Holtmann 
2390a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2391a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2392a9de9248SMarcel Holtmann 		break;
2393a9de9248SMarcel Holtmann 
2394a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2395a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2396a9de9248SMarcel Holtmann 		break;
2397a9de9248SMarcel Holtmann 
23988962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
239988c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
24008962ee74SJohan Hedberg 		break;
24018962ee74SJohan Hedberg 
2402fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2403fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2404fcd89c09SVille Tervo 		break;
2405fcd89c09SVille Tervo 
2406a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2407a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2408a7a595f6SVinicius Costa Gomes 		break;
2409a7a595f6SVinicius Costa Gomes 
2410a9de9248SMarcel Holtmann 	default:
2411a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2412a9de9248SMarcel Holtmann 		break;
2413a9de9248SMarcel Holtmann 	}
2414a9de9248SMarcel Holtmann 
24156bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
24166bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24176bd32326SVille Tervo 
241810572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2419a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2420a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2421c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2422a9de9248SMarcel Holtmann 	}
2423a9de9248SMarcel Holtmann }
2424a9de9248SMarcel Holtmann 
2425a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2426a9de9248SMarcel Holtmann {
2427a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2428a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2429a9de9248SMarcel Holtmann 
2430a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2431a9de9248SMarcel Holtmann 
2432a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2433a9de9248SMarcel Holtmann 
2434a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2435a9de9248SMarcel Holtmann 	if (conn) {
2436a9de9248SMarcel Holtmann 		if (!ev->status) {
2437a9de9248SMarcel Holtmann 			if (ev->role)
2438a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2439a9de9248SMarcel Holtmann 			else
2440a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2441a9de9248SMarcel Holtmann 		}
2442a9de9248SMarcel Holtmann 
244351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2444a9de9248SMarcel Holtmann 
2445a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2446a9de9248SMarcel Holtmann 	}
2447a9de9248SMarcel Holtmann 
2448a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2449a9de9248SMarcel Holtmann }
2450a9de9248SMarcel Holtmann 
24511da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24521da177e4SLinus Torvalds {
2453a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24541da177e4SLinus Torvalds 	int i;
24551da177e4SLinus Torvalds 
245632ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
245732ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
245832ac5b9bSAndrei Emeltchenko 		return;
245932ac5b9bSAndrei Emeltchenko 	}
246032ac5b9bSAndrei Emeltchenko 
2461c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2462c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24631da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24641da177e4SLinus Torvalds 		return;
24651da177e4SLinus Torvalds 	}
24661da177e4SLinus Torvalds 
2467c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2468c5993de8SAndrei Emeltchenko 
2469613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2470613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24711da177e4SLinus Torvalds 		struct hci_conn *conn;
24721da177e4SLinus Torvalds 		__u16  handle, count;
24731da177e4SLinus Torvalds 
2474613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2475613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24761da177e4SLinus Torvalds 
24771da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2478f4280918SAndrei Emeltchenko 		if (!conn)
2479f4280918SAndrei Emeltchenko 			continue;
2480f4280918SAndrei Emeltchenko 
24811da177e4SLinus Torvalds 		conn->sent -= count;
24821da177e4SLinus Torvalds 
2483f4280918SAndrei Emeltchenko 		switch (conn->type) {
2484f4280918SAndrei Emeltchenko 		case ACL_LINK:
248570f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
248670f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24871da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2488f4280918SAndrei Emeltchenko 			break;
2489f4280918SAndrei Emeltchenko 
2490f4280918SAndrei Emeltchenko 		case LE_LINK:
24916ed58ec5SVille Tervo 			if (hdev->le_pkts) {
24926ed58ec5SVille Tervo 				hdev->le_cnt += count;
24936ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
24946ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
24956ed58ec5SVille Tervo 			} else {
24966ed58ec5SVille Tervo 				hdev->acl_cnt += count;
24976ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
24986ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
24996ed58ec5SVille Tervo 			}
2500f4280918SAndrei Emeltchenko 			break;
2501f4280918SAndrei Emeltchenko 
2502f4280918SAndrei Emeltchenko 		case SCO_LINK:
250370f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
250470f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
25055b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2506f4280918SAndrei Emeltchenko 			break;
2507f4280918SAndrei Emeltchenko 
2508f4280918SAndrei Emeltchenko 		default:
2509f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2510f4280918SAndrei Emeltchenko 			break;
25111da177e4SLinus Torvalds 		}
25121da177e4SLinus Torvalds 	}
2513a9de9248SMarcel Holtmann 
25143eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25151da177e4SLinus Torvalds }
25161da177e4SLinus Torvalds 
251725e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
251825e89e99SAndrei Emeltchenko 							struct sk_buff *skb)
251925e89e99SAndrei Emeltchenko {
252025e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
252125e89e99SAndrei Emeltchenko 	int i;
252225e89e99SAndrei Emeltchenko 
252325e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
252425e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
252525e89e99SAndrei Emeltchenko 		return;
252625e89e99SAndrei Emeltchenko 	}
252725e89e99SAndrei Emeltchenko 
252825e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
252925e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
253025e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
253125e89e99SAndrei Emeltchenko 		return;
253225e89e99SAndrei Emeltchenko 	}
253325e89e99SAndrei Emeltchenko 
253425e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
253525e89e99SAndrei Emeltchenko 								ev->num_hndl);
253625e89e99SAndrei Emeltchenko 
253725e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
253825e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
253925e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
254025e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
254125e89e99SAndrei Emeltchenko 
254225e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
254325e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
254425e89e99SAndrei Emeltchenko 
254525e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
254625e89e99SAndrei Emeltchenko 		if (!conn)
254725e89e99SAndrei Emeltchenko 			continue;
254825e89e99SAndrei Emeltchenko 
254925e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
255025e89e99SAndrei Emeltchenko 
255125e89e99SAndrei Emeltchenko 		switch (conn->type) {
255225e89e99SAndrei Emeltchenko 		case ACL_LINK:
255325e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
255425e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
255525e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
255625e89e99SAndrei Emeltchenko 			break;
255725e89e99SAndrei Emeltchenko 
255825e89e99SAndrei Emeltchenko 		default:
255925e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
256025e89e99SAndrei Emeltchenko 			break;
256125e89e99SAndrei Emeltchenko 		}
256225e89e99SAndrei Emeltchenko 	}
256325e89e99SAndrei Emeltchenko 
256425e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
256525e89e99SAndrei Emeltchenko }
256625e89e99SAndrei Emeltchenko 
256704837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25681da177e4SLinus Torvalds {
2569a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
257004837f64SMarcel Holtmann 	struct hci_conn *conn;
25711da177e4SLinus Torvalds 
25721da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
25731da177e4SLinus Torvalds 
25741da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25751da177e4SLinus Torvalds 
257604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
257704837f64SMarcel Holtmann 	if (conn) {
257804837f64SMarcel Holtmann 		conn->mode = ev->mode;
257904837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
258004837f64SMarcel Holtmann 
258151a8efd7SJohan Hedberg 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
258204837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
258358a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
258404837f64SMarcel Holtmann 			else
258558a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
258604837f64SMarcel Holtmann 		}
2587e73439d8SMarcel Holtmann 
258851a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2589e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
259004837f64SMarcel Holtmann 	}
259104837f64SMarcel Holtmann 
259204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
259304837f64SMarcel Holtmann }
259404837f64SMarcel Holtmann 
25951da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25961da177e4SLinus Torvalds {
2597052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2598052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2599052b30b0SMarcel Holtmann 
2600a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2601052b30b0SMarcel Holtmann 
2602052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2603052b30b0SMarcel Holtmann 
2604052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2605b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2606b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2607b6f98044SWaldemar Rymarkiewicz 
2608b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2609052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2610052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2611052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2612052b30b0SMarcel Holtmann 	}
2613052b30b0SMarcel Holtmann 
2614a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
261503b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
261603b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2617a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2618a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2619a770bb5aSWaldemar Rymarkiewicz 
2620a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2621a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2622a770bb5aSWaldemar Rymarkiewicz 		else
2623a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2624a770bb5aSWaldemar Rymarkiewicz 
2625744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2626a770bb5aSWaldemar Rymarkiewicz 	}
2627980e1a53SJohan Hedberg 
2628b6f98044SWaldemar Rymarkiewicz unlock:
2629052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26301da177e4SLinus Torvalds }
26311da177e4SLinus Torvalds 
26321da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26331da177e4SLinus Torvalds {
263455ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
263555ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
263655ed8ca1SJohan Hedberg 	struct hci_conn *conn;
263755ed8ca1SJohan Hedberg 	struct link_key *key;
263855ed8ca1SJohan Hedberg 
2639a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
264055ed8ca1SJohan Hedberg 
2641a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
264255ed8ca1SJohan Hedberg 		return;
264355ed8ca1SJohan Hedberg 
264455ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
264555ed8ca1SJohan Hedberg 
264655ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
264755ed8ca1SJohan Hedberg 	if (!key) {
264855ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
264955ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
265055ed8ca1SJohan Hedberg 		goto not_found;
265155ed8ca1SJohan Hedberg 	}
265255ed8ca1SJohan Hedberg 
265355ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
265455ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
265555ed8ca1SJohan Hedberg 
2656a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2657b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
265855ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
265955ed8ca1SJohan Hedberg 		goto not_found;
266055ed8ca1SJohan Hedberg 	}
266155ed8ca1SJohan Hedberg 
266255ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
266360b83f57SWaldemar Rymarkiewicz 	if (conn) {
266460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
266560b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
266660b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
266755ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
266855ed8ca1SJohan Hedberg 			goto not_found;
266955ed8ca1SJohan Hedberg 		}
267055ed8ca1SJohan Hedberg 
267160b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
267260b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
267360b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
267460b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
267560b83f57SWaldemar Rymarkiewicz 			goto not_found;
267660b83f57SWaldemar Rymarkiewicz 		}
267760b83f57SWaldemar Rymarkiewicz 
267860b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
267960b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
268060b83f57SWaldemar Rymarkiewicz 	}
268160b83f57SWaldemar Rymarkiewicz 
268255ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
268355ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
268455ed8ca1SJohan Hedberg 
268555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
268655ed8ca1SJohan Hedberg 
268755ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
268855ed8ca1SJohan Hedberg 
268955ed8ca1SJohan Hedberg 	return;
269055ed8ca1SJohan Hedberg 
269155ed8ca1SJohan Hedberg not_found:
269255ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
269355ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
26941da177e4SLinus Torvalds }
26951da177e4SLinus Torvalds 
26961da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
26971da177e4SLinus Torvalds {
2698052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2699052b30b0SMarcel Holtmann 	struct hci_conn *conn;
270055ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2701052b30b0SMarcel Holtmann 
2702a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2703052b30b0SMarcel Holtmann 
2704052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2705052b30b0SMarcel Holtmann 
2706052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2707052b30b0SMarcel Holtmann 	if (conn) {
2708052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2709052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2710980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
271113d39315SWaldemar Rymarkiewicz 
271213d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
271313d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
271413d39315SWaldemar Rymarkiewicz 
2715052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2716052b30b0SMarcel Holtmann 	}
2717052b30b0SMarcel Holtmann 
2718a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2719d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
272055ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
272155ed8ca1SJohan Hedberg 
2722052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27231da177e4SLinus Torvalds }
27241da177e4SLinus Torvalds 
272504837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
272604837f64SMarcel Holtmann {
2727a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
272804837f64SMarcel Holtmann 	struct hci_conn *conn;
272904837f64SMarcel Holtmann 
273004837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
273104837f64SMarcel Holtmann 
273204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
273304837f64SMarcel Holtmann 
273404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27351da177e4SLinus Torvalds 	if (conn && !ev->status) {
27361da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27371da177e4SLinus Torvalds 
2738cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2739cc11b9c1SAndrei Emeltchenko 		if (ie) {
27401da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27411da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27421da177e4SLinus Torvalds 		}
27431da177e4SLinus Torvalds 	}
27441da177e4SLinus Torvalds 
27451da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27461da177e4SLinus Torvalds }
27471da177e4SLinus Torvalds 
2748a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2749a8746417SMarcel Holtmann {
2750a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2751a8746417SMarcel Holtmann 	struct hci_conn *conn;
2752a8746417SMarcel Holtmann 
2753a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2754a8746417SMarcel Holtmann 
2755a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2756a8746417SMarcel Holtmann 
2757a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2758a8746417SMarcel Holtmann 	if (conn && !ev->status)
2759a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2760a8746417SMarcel Holtmann 
2761a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2762a8746417SMarcel Holtmann }
2763a8746417SMarcel Holtmann 
276485a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
276585a1e930SMarcel Holtmann {
2766a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
276785a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
276885a1e930SMarcel Holtmann 
276985a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
277085a1e930SMarcel Holtmann 
277185a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
277285a1e930SMarcel Holtmann 
2773cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2774cc11b9c1SAndrei Emeltchenko 	if (ie) {
277585a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
277685a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
277785a1e930SMarcel Holtmann 	}
277885a1e930SMarcel Holtmann 
277985a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
278085a1e930SMarcel Holtmann }
278185a1e930SMarcel Holtmann 
2782a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2783a9de9248SMarcel Holtmann {
2784a9de9248SMarcel Holtmann 	struct inquiry_data data;
2785a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2786388fc8faSJohan Hedberg 	bool name_known, ssp;
2787a9de9248SMarcel Holtmann 
2788a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2789a9de9248SMarcel Holtmann 
2790a9de9248SMarcel Holtmann 	if (!num_rsp)
2791a9de9248SMarcel Holtmann 		return;
2792a9de9248SMarcel Holtmann 
2793a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2794a9de9248SMarcel Holtmann 
2795a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2796138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2797138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2798a9de9248SMarcel Holtmann 
2799e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2800a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2801a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2802a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2803a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2804a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2805a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2806a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
280741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28083175405bSJohan Hedberg 
28093175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2810388fc8faSJohan Hedberg 								false, &ssp);
281148264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2812e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2813388fc8faSJohan Hedberg 						!name_known, ssp, NULL, 0);
2814a9de9248SMarcel Holtmann 		}
2815a9de9248SMarcel Holtmann 	} else {
2816a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2817a9de9248SMarcel Holtmann 
2818e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2819a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2820a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2821a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2822a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2823a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2824a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2825a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
282641a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28273175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2828388fc8faSJohan Hedberg 								false, &ssp);
282948264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2830e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
2831388fc8faSJohan Hedberg 						!name_known, ssp, NULL, 0);
2832a9de9248SMarcel Holtmann 		}
2833a9de9248SMarcel Holtmann 	}
2834a9de9248SMarcel Holtmann 
2835a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2836a9de9248SMarcel Holtmann }
2837a9de9248SMarcel Holtmann 
2838a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2839a9de9248SMarcel Holtmann {
284041a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
284141a96212SMarcel Holtmann 	struct hci_conn *conn;
284241a96212SMarcel Holtmann 
2843a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
284441a96212SMarcel Holtmann 
284541a96212SMarcel Holtmann 	hci_dev_lock(hdev);
284641a96212SMarcel Holtmann 
284741a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2848ccd556feSJohan Hedberg 	if (!conn)
2849ccd556feSJohan Hedberg 		goto unlock;
2850ccd556feSJohan Hedberg 
2851769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
285241a96212SMarcel Holtmann 		struct inquiry_entry *ie;
285341a96212SMarcel Holtmann 
2854cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2855cc11b9c1SAndrei Emeltchenko 		if (ie)
285641a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
285741a96212SMarcel Holtmann 
285858a681efSJohan Hedberg 		if (ev->features[0] & 0x01)
285958a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
286041a96212SMarcel Holtmann 	}
286141a96212SMarcel Holtmann 
2862ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2863ccd556feSJohan Hedberg 		goto unlock;
2864ccd556feSJohan Hedberg 
2865127178d2SJohan Hedberg 	if (!ev->status) {
2866127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2867127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2868127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2869127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2870127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2871b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2872b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2873b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2874b644ba33SJohan Hedberg 						conn->dev_class);
2875392599b9SJohan Hedberg 
2876127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2877769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2878769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2879769be974SMarcel Holtmann 		hci_conn_put(conn);
2880769be974SMarcel Holtmann 	}
2881769be974SMarcel Holtmann 
2882ccd556feSJohan Hedberg unlock:
288341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2884a9de9248SMarcel Holtmann }
2885a9de9248SMarcel Holtmann 
2886a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2887a9de9248SMarcel Holtmann {
2888b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2889b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2890b6a0dc82SMarcel Holtmann 
2891b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2892b6a0dc82SMarcel Holtmann 
2893b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2894b6a0dc82SMarcel Holtmann 
2895b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
28969dc0a3afSMarcel Holtmann 	if (!conn) {
28979dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
28989dc0a3afSMarcel Holtmann 			goto unlock;
28999dc0a3afSMarcel Holtmann 
29009dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2901b6a0dc82SMarcel Holtmann 		if (!conn)
2902b6a0dc82SMarcel Holtmann 			goto unlock;
2903b6a0dc82SMarcel Holtmann 
29049dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
29059dc0a3afSMarcel Holtmann 	}
29069dc0a3afSMarcel Holtmann 
2907732547f9SMarcel Holtmann 	switch (ev->status) {
2908732547f9SMarcel Holtmann 	case 0x00:
2909732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2910732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2911732547f9SMarcel Holtmann 
29129eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2913732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2914732547f9SMarcel Holtmann 		break;
2915732547f9SMarcel Holtmann 
2916705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2917732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29181038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2919732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2920732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2921efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2922efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2923efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2924efc7688bSMarcel Holtmann 			goto unlock;
2925efc7688bSMarcel Holtmann 		}
2926732547f9SMarcel Holtmann 		/* fall through */
2927efc7688bSMarcel Holtmann 
2928732547f9SMarcel Holtmann 	default:
2929b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2930732547f9SMarcel Holtmann 		break;
2931732547f9SMarcel Holtmann 	}
2932b6a0dc82SMarcel Holtmann 
2933b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2934b6a0dc82SMarcel Holtmann 	if (ev->status)
2935b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2936b6a0dc82SMarcel Holtmann 
2937b6a0dc82SMarcel Holtmann unlock:
2938b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2939a9de9248SMarcel Holtmann }
2940a9de9248SMarcel Holtmann 
2941a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2942a9de9248SMarcel Holtmann {
2943a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2944a9de9248SMarcel Holtmann }
2945a9de9248SMarcel Holtmann 
294604837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
294704837f64SMarcel Holtmann {
2948a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
294904837f64SMarcel Holtmann 
295004837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
295104837f64SMarcel Holtmann }
295204837f64SMarcel Holtmann 
2953a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2954a9de9248SMarcel Holtmann {
2955a9de9248SMarcel Holtmann 	struct inquiry_data data;
2956a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2957a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2958a9de9248SMarcel Holtmann 
2959a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2960a9de9248SMarcel Holtmann 
2961a9de9248SMarcel Holtmann 	if (!num_rsp)
2962a9de9248SMarcel Holtmann 		return;
2963a9de9248SMarcel Holtmann 
2964a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2965a9de9248SMarcel Holtmann 
2966e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2967388fc8faSJohan Hedberg 		bool name_known, ssp;
2968561aafbcSJohan Hedberg 
2969a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2970a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2971a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2972a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2973a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2974a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2975a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
297641a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2977561aafbcSJohan Hedberg 
2978a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29794ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29804ddb1930SJohan Hedberg 							sizeof(info->data),
29814ddb1930SJohan Hedberg 							EIR_NAME_COMPLETE);
2982561aafbcSJohan Hedberg 		else
2983561aafbcSJohan Hedberg 			name_known = true;
2984561aafbcSJohan Hedberg 
2985388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
2986388fc8faSJohan Hedberg 									&ssp);
298748264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2988561aafbcSJohan Hedberg 						info->dev_class, info->rssi,
2989388fc8faSJohan Hedberg 						!name_known, ssp, info->data,
29907d262f86SAndre Guedes 						sizeof(info->data));
2991a9de9248SMarcel Holtmann 	}
2992a9de9248SMarcel Holtmann 
2993a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2994a9de9248SMarcel Holtmann }
2995a9de9248SMarcel Holtmann 
299617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
299717fa4b9dSJohan Hedberg {
299817fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
299917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
300017fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
300117fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
300217fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
300317fa4b9dSJohan Hedberg 			return 0x02;
300417fa4b9dSJohan Hedberg 		else
300517fa4b9dSJohan Hedberg 			return 0x03;
300617fa4b9dSJohan Hedberg 	}
300717fa4b9dSJohan Hedberg 
300817fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
300917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
301058797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
301117fa4b9dSJohan Hedberg 
301217fa4b9dSJohan Hedberg 	return conn->auth_type;
301317fa4b9dSJohan Hedberg }
301417fa4b9dSJohan Hedberg 
30150493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
30160493684eSMarcel Holtmann {
30170493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
30180493684eSMarcel Holtmann 	struct hci_conn *conn;
30190493684eSMarcel Holtmann 
30200493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30210493684eSMarcel Holtmann 
30220493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30230493684eSMarcel Holtmann 
30240493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
302503b555e1SJohan Hedberg 	if (!conn)
302603b555e1SJohan Hedberg 		goto unlock;
302703b555e1SJohan Hedberg 
30280493684eSMarcel Holtmann 	hci_conn_hold(conn);
30290493684eSMarcel Holtmann 
3030a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
303103b555e1SJohan Hedberg 		goto unlock;
303203b555e1SJohan Hedberg 
3033a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
303403b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
303517fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
303617fa4b9dSJohan Hedberg 
303717fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30387a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
30397a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
30407a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
30417a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
30427cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
30437cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
304417fa4b9dSJohan Hedberg 
304558a681efSJohan Hedberg 		if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
3046ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
3047ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3048ce85ee13SSzymon Janc 		else
3049ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3050ce85ee13SSzymon Janc 
305117fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
305217fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
305303b555e1SJohan Hedberg 	} else {
305403b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
305503b555e1SJohan Hedberg 
305603b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30579f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
305803b555e1SJohan Hedberg 
305903b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
306003b555e1SJohan Hedberg 							sizeof(cp), &cp);
306103b555e1SJohan Hedberg 	}
306203b555e1SJohan Hedberg 
306303b555e1SJohan Hedberg unlock:
306403b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
306503b555e1SJohan Hedberg }
306603b555e1SJohan Hedberg 
306703b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
306803b555e1SJohan Hedberg {
306903b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
307003b555e1SJohan Hedberg 	struct hci_conn *conn;
307103b555e1SJohan Hedberg 
307203b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
307303b555e1SJohan Hedberg 
307403b555e1SJohan Hedberg 	hci_dev_lock(hdev);
307503b555e1SJohan Hedberg 
307603b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
307703b555e1SJohan Hedberg 	if (!conn)
307803b555e1SJohan Hedberg 		goto unlock;
307903b555e1SJohan Hedberg 
308003b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
308103b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
308258a681efSJohan Hedberg 	if (ev->oob_data)
308358a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
308403b555e1SJohan Hedberg 
308503b555e1SJohan Hedberg unlock:
30860493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
30870493684eSMarcel Holtmann }
30880493684eSMarcel Holtmann 
3089a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3090a5c29683SJohan Hedberg 							struct sk_buff *skb)
3091a5c29683SJohan Hedberg {
3092a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
309355bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
30947a828908SJohan Hedberg 	struct hci_conn *conn;
3095a5c29683SJohan Hedberg 
3096a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3097a5c29683SJohan Hedberg 
3098a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3099a5c29683SJohan Hedberg 
3100a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
31017a828908SJohan Hedberg 		goto unlock;
31027a828908SJohan Hedberg 
31037a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31047a828908SJohan Hedberg 	if (!conn)
31057a828908SJohan Hedberg 		goto unlock;
31067a828908SJohan Hedberg 
31077a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
31087a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
31097a828908SJohan Hedberg 
31107a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
31117a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
31127a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
31137a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
31147a828908SJohan Hedberg 	 * bit set. */
31157a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
31167a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
31177a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
31187a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
31197a828908SJohan Hedberg 		goto unlock;
31207a828908SJohan Hedberg 	}
31217a828908SJohan Hedberg 
31227a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
31237a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
31247a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
312555bc1a37SJohan Hedberg 
312655bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
312755bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
312855bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
312951a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
313055bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
313155bc1a37SJohan Hedberg 			confirm_hint = 1;
313255bc1a37SJohan Hedberg 			goto confirm;
313355bc1a37SJohan Hedberg 		}
313455bc1a37SJohan Hedberg 
31359f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
31369f61656aSJohan Hedberg 						hdev->auto_accept_delay);
31379f61656aSJohan Hedberg 
31389f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
31399f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
31409f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
31419f61656aSJohan Hedberg 			goto unlock;
31429f61656aSJohan Hedberg 		}
31439f61656aSJohan Hedberg 
31447a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
31457a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
31467a828908SJohan Hedberg 		goto unlock;
31477a828908SJohan Hedberg 	}
31487a828908SJohan Hedberg 
314955bc1a37SJohan Hedberg confirm:
3150272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
315155bc1a37SJohan Hedberg 								confirm_hint);
3152a5c29683SJohan Hedberg 
31537a828908SJohan Hedberg unlock:
3154a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3155a5c29683SJohan Hedberg }
3156a5c29683SJohan Hedberg 
31571143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
31581143d458SBrian Gix 							struct sk_buff *skb)
31591143d458SBrian Gix {
31601143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
31611143d458SBrian Gix 
31621143d458SBrian Gix 	BT_DBG("%s", hdev->name);
31631143d458SBrian Gix 
31641143d458SBrian Gix 	hci_dev_lock(hdev);
31651143d458SBrian Gix 
3166a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3167272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
31681143d458SBrian Gix 
31691143d458SBrian Gix 	hci_dev_unlock(hdev);
31701143d458SBrian Gix }
31711143d458SBrian Gix 
31720493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
31730493684eSMarcel Holtmann {
31740493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
31750493684eSMarcel Holtmann 	struct hci_conn *conn;
31760493684eSMarcel Holtmann 
31770493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31780493684eSMarcel Holtmann 
31790493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31800493684eSMarcel Holtmann 
31810493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31822a611692SJohan Hedberg 	if (!conn)
31832a611692SJohan Hedberg 		goto unlock;
31842a611692SJohan Hedberg 
31852a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
31862a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
31872a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
31882a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
31892a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
319051a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3191bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3192bab73cb6SJohan Hedberg 								ev->status);
31932a611692SJohan Hedberg 
31940493684eSMarcel Holtmann 	hci_conn_put(conn);
31950493684eSMarcel Holtmann 
31962a611692SJohan Hedberg unlock:
31970493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31980493684eSMarcel Holtmann }
31990493684eSMarcel Holtmann 
320041a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
320141a96212SMarcel Holtmann {
320241a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
320341a96212SMarcel Holtmann 	struct inquiry_entry *ie;
320441a96212SMarcel Holtmann 
320541a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
320641a96212SMarcel Holtmann 
320741a96212SMarcel Holtmann 	hci_dev_lock(hdev);
320841a96212SMarcel Holtmann 
3209cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3210cc11b9c1SAndrei Emeltchenko 	if (ie)
321141a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
321241a96212SMarcel Holtmann 
321341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
321441a96212SMarcel Holtmann }
321541a96212SMarcel Holtmann 
32162763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
32172763eda6SSzymon Janc 							struct sk_buff *skb)
32182763eda6SSzymon Janc {
32192763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
32202763eda6SSzymon Janc 	struct oob_data *data;
32212763eda6SSzymon Janc 
32222763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
32232763eda6SSzymon Janc 
32242763eda6SSzymon Janc 	hci_dev_lock(hdev);
32252763eda6SSzymon Janc 
3226a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3227e1ba1f15SSzymon Janc 		goto unlock;
3228e1ba1f15SSzymon Janc 
32292763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
32302763eda6SSzymon Janc 	if (data) {
32312763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
32322763eda6SSzymon Janc 
32332763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32342763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
32352763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
32362763eda6SSzymon Janc 
32372763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
32382763eda6SSzymon Janc 									&cp);
32392763eda6SSzymon Janc 	} else {
32402763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
32412763eda6SSzymon Janc 
32422763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32432763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
32442763eda6SSzymon Janc 									&cp);
32452763eda6SSzymon Janc 	}
32462763eda6SSzymon Janc 
3247e1ba1f15SSzymon Janc unlock:
32482763eda6SSzymon Janc 	hci_dev_unlock(hdev);
32492763eda6SSzymon Janc }
32502763eda6SSzymon Janc 
3251fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3252fcd89c09SVille Tervo {
3253fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3254fcd89c09SVille Tervo 	struct hci_conn *conn;
3255fcd89c09SVille Tervo 
3256fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3257fcd89c09SVille Tervo 
3258fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3259fcd89c09SVille Tervo 
3260fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3261b62f328bSVille Tervo 	if (!conn) {
3262b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3263b62f328bSVille Tervo 		if (!conn) {
3264b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3265b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3266b62f328bSVille Tervo 			return;
3267b62f328bSVille Tervo 		}
326829b7988aSAndre Guedes 
326929b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3270b62f328bSVille Tervo 	}
3271fcd89c09SVille Tervo 
3272fcd89c09SVille Tervo 	if (ev->status) {
327348264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
327448264f06SJohan Hedberg 						conn->dst_type, ev->status);
3275fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3276fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3277fcd89c09SVille Tervo 		hci_conn_del(conn);
3278fcd89c09SVille Tervo 		goto unlock;
3279fcd89c09SVille Tervo 	}
3280fcd89c09SVille Tervo 
3281b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3282b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
3283b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0, 0);
328483bc71b4SVinicius Costa Gomes 
32857b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3286fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3287fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3288fcd89c09SVille Tervo 
3289fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3290fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3291fcd89c09SVille Tervo 
3292fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3293fcd89c09SVille Tervo 
3294fcd89c09SVille Tervo unlock:
3295fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3296fcd89c09SVille Tervo }
3297fcd89c09SVille Tervo 
32989aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
32999aa04c91SAndre Guedes 						struct sk_buff *skb)
33009aa04c91SAndre Guedes {
3301e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3302e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
33033c9e9195SAndre Guedes 	s8 rssi;
33049aa04c91SAndre Guedes 
33059aa04c91SAndre Guedes 	hci_dev_lock(hdev);
33069aa04c91SAndre Guedes 
3307e95beb41SAndre Guedes 	while (num_reports--) {
3308e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3309e95beb41SAndre Guedes 
33109aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
33119aa04c91SAndre Guedes 
33123c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
33133c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
3314388fc8faSJohan Hedberg 					NULL, rssi, 0, 1, ev->data,
3315388fc8faSJohan Hedberg 					ev->length);
33163c9e9195SAndre Guedes 
3317e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
33189aa04c91SAndre Guedes 	}
33199aa04c91SAndre Guedes 
33209aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
33219aa04c91SAndre Guedes }
33229aa04c91SAndre Guedes 
3323a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3324a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3325a7a595f6SVinicius Costa Gomes {
3326a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3327a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3328bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3329a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3330c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3331a7a595f6SVinicius Costa Gomes 
3332a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3333a7a595f6SVinicius Costa Gomes 
3334a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3335a7a595f6SVinicius Costa Gomes 
3336a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3337bea710feSVinicius Costa Gomes 	if (conn == NULL)
3338bea710feSVinicius Costa Gomes 		goto not_found;
3339a7a595f6SVinicius Costa Gomes 
3340bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3341bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3342bea710feSVinicius Costa Gomes 		goto not_found;
3343bea710feSVinicius Costa Gomes 
3344bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3345a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3346c9839a11SVinicius Costa Gomes 
3347c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3348c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3349a7a595f6SVinicius Costa Gomes 
3350a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3351a7a595f6SVinicius Costa Gomes 
3352c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3353c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3354c9839a11SVinicius Costa Gomes 		kfree(ltk);
3355c9839a11SVinicius Costa Gomes 	}
3356c9839a11SVinicius Costa Gomes 
3357a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3358bea710feSVinicius Costa Gomes 
3359bea710feSVinicius Costa Gomes 	return;
3360bea710feSVinicius Costa Gomes 
3361bea710feSVinicius Costa Gomes not_found:
3362bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3363bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3364bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3365a7a595f6SVinicius Costa Gomes }
3366a7a595f6SVinicius Costa Gomes 
3367fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3368fcd89c09SVille Tervo {
3369fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3370fcd89c09SVille Tervo 
3371fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3372fcd89c09SVille Tervo 
3373fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3374fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3375fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3376fcd89c09SVille Tervo 		break;
3377fcd89c09SVille Tervo 
33789aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
33799aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
33809aa04c91SAndre Guedes 		break;
33819aa04c91SAndre Guedes 
3382a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3383a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3384a7a595f6SVinicius Costa Gomes 		break;
3385a7a595f6SVinicius Costa Gomes 
3386fcd89c09SVille Tervo 	default:
3387fcd89c09SVille Tervo 		break;
3388fcd89c09SVille Tervo 	}
3389fcd89c09SVille Tervo }
3390fcd89c09SVille Tervo 
33911da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
33921da177e4SLinus Torvalds {
3393a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3394a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
33951da177e4SLinus Torvalds 
33961da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
33971da177e4SLinus Torvalds 
3398a9de9248SMarcel Holtmann 	switch (event) {
33991da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
34001da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
34011da177e4SLinus Torvalds 		break;
34021da177e4SLinus Torvalds 
34031da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
34041da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
34051da177e4SLinus Torvalds 		break;
34061da177e4SLinus Torvalds 
3407a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3408a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
340921d9e30eSMarcel Holtmann 		break;
341021d9e30eSMarcel Holtmann 
34111da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
34121da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
34131da177e4SLinus Torvalds 		break;
34141da177e4SLinus Torvalds 
34151da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
34161da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
34171da177e4SLinus Torvalds 		break;
34181da177e4SLinus Torvalds 
34191da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
34201da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
34211da177e4SLinus Torvalds 		break;
34221da177e4SLinus Torvalds 
3423a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3424a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3425a9de9248SMarcel Holtmann 		break;
3426a9de9248SMarcel Holtmann 
34271da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
34281da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
34291da177e4SLinus Torvalds 		break;
34301da177e4SLinus Torvalds 
3431a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3432a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3433a9de9248SMarcel Holtmann 		break;
3434a9de9248SMarcel Holtmann 
3435a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3436a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3437a9de9248SMarcel Holtmann 		break;
3438a9de9248SMarcel Holtmann 
3439a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3440a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3441a9de9248SMarcel Holtmann 		break;
3442a9de9248SMarcel Holtmann 
3443a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3444a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3445a9de9248SMarcel Holtmann 		break;
3446a9de9248SMarcel Holtmann 
3447a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3448a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3449a9de9248SMarcel Holtmann 		break;
3450a9de9248SMarcel Holtmann 
3451a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3452a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3453a9de9248SMarcel Holtmann 		break;
3454a9de9248SMarcel Holtmann 
3455a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3456a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3457a9de9248SMarcel Holtmann 		break;
3458a9de9248SMarcel Holtmann 
3459a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3460a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3461a9de9248SMarcel Holtmann 		break;
3462a9de9248SMarcel Holtmann 
3463a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3464a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
34651da177e4SLinus Torvalds 		break;
34661da177e4SLinus Torvalds 
34671da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
34681da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
34691da177e4SLinus Torvalds 		break;
34701da177e4SLinus Torvalds 
34711da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
34721da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
34731da177e4SLinus Torvalds 		break;
34741da177e4SLinus Torvalds 
34751da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
34761da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
34771da177e4SLinus Torvalds 		break;
34781da177e4SLinus Torvalds 
34791da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
34801da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
34811da177e4SLinus Torvalds 		break;
34821da177e4SLinus Torvalds 
3483a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3484a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3485a8746417SMarcel Holtmann 		break;
3486a8746417SMarcel Holtmann 
348785a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
348885a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
348985a1e930SMarcel Holtmann 		break;
349085a1e930SMarcel Holtmann 
3491a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3492a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3493a9de9248SMarcel Holtmann 		break;
3494a9de9248SMarcel Holtmann 
3495a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3496a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3497a9de9248SMarcel Holtmann 		break;
3498a9de9248SMarcel Holtmann 
3499a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3500a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3501a9de9248SMarcel Holtmann 		break;
3502a9de9248SMarcel Holtmann 
3503a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3504a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3505a9de9248SMarcel Holtmann 		break;
3506a9de9248SMarcel Holtmann 
350704837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
350804837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
350904837f64SMarcel Holtmann 		break;
351004837f64SMarcel Holtmann 
3511a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3512a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
35131da177e4SLinus Torvalds 		break;
35141da177e4SLinus Torvalds 
35150493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
35160493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
35170493684eSMarcel Holtmann 		break;
35180493684eSMarcel Holtmann 
351903b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
352003b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
352103b555e1SJohan Hedberg 		break;
352203b555e1SJohan Hedberg 
3523a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3524a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3525a5c29683SJohan Hedberg 		break;
3526a5c29683SJohan Hedberg 
35271143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
35281143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
35291143d458SBrian Gix 		break;
35301143d458SBrian Gix 
35310493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
35320493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
35330493684eSMarcel Holtmann 		break;
35340493684eSMarcel Holtmann 
353541a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
353641a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
353741a96212SMarcel Holtmann 		break;
353841a96212SMarcel Holtmann 
3539fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3540fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3541fcd89c09SVille Tervo 		break;
3542fcd89c09SVille Tervo 
35432763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
35442763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
35452763eda6SSzymon Janc 		break;
35462763eda6SSzymon Janc 
354725e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
354825e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
354925e89e99SAndrei Emeltchenko 		break;
355025e89e99SAndrei Emeltchenko 
35511da177e4SLinus Torvalds 	default:
3552a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
35531da177e4SLinus Torvalds 		break;
35541da177e4SLinus Torvalds 	}
35551da177e4SLinus Torvalds 
35561da177e4SLinus Torvalds 	kfree_skb(skb);
35571da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
35581da177e4SLinus Torvalds }
3559