xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 54d04dbb)
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 
212a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
213744cf19eSJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
214b312b161SJohan Hedberg 
21556e5cb86SJohan Hedberg 	if (status == 0)
2161f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
21756e5cb86SJohan Hedberg 
21856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
219a9de9248SMarcel Holtmann }
220a9de9248SMarcel Holtmann 
221a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
222a9de9248SMarcel Holtmann {
223a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
224a9de9248SMarcel Holtmann 
225a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
226a9de9248SMarcel Holtmann 
227a9de9248SMarcel Holtmann 	if (rp->status)
228a9de9248SMarcel Holtmann 		return;
229a9de9248SMarcel Holtmann 
2301f6c6378SJohan Hedberg 	memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
231a9de9248SMarcel Holtmann }
232a9de9248SMarcel Holtmann 
233a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
234a9de9248SMarcel Holtmann {
235a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
236a9de9248SMarcel Holtmann 	void *sent;
237a9de9248SMarcel Holtmann 
238a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
239a9de9248SMarcel Holtmann 
240a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
241a9de9248SMarcel Holtmann 	if (!sent)
242a9de9248SMarcel Holtmann 		return;
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds 	if (!status) {
245a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
246a9de9248SMarcel Holtmann 
2471da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2481da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2491da177e4SLinus Torvalds 		else
2501da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2511da177e4SLinus Torvalds 	}
252a9de9248SMarcel Holtmann 
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 
353f383f275SMarcel Holtmann 	if (status)
354f383f275SMarcel Holtmann 		return;
355f383f275SMarcel Holtmann 
356a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
357a9de9248SMarcel Holtmann 	if (!sent)
358a9de9248SMarcel Holtmann 		return;
359a9de9248SMarcel Holtmann 
360a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, sent, 3);
361a9de9248SMarcel Holtmann }
362a9de9248SMarcel Holtmann 
363a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
364a9de9248SMarcel Holtmann {
365a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
366a9de9248SMarcel Holtmann 	__u16 setting;
367a9de9248SMarcel Holtmann 
368a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
369a9de9248SMarcel Holtmann 
370a9de9248SMarcel Holtmann 	if (rp->status)
371a9de9248SMarcel Holtmann 		return;
372a9de9248SMarcel Holtmann 
373a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
374a9de9248SMarcel Holtmann 
375a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
376a9de9248SMarcel Holtmann 		return;
377a9de9248SMarcel Holtmann 
378a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
379a9de9248SMarcel Holtmann 
380a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
381a9de9248SMarcel Holtmann 
3823c54711cSGustavo F. Padovan 	if (hdev->notify)
383a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
384a9de9248SMarcel Holtmann }
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
387a9de9248SMarcel Holtmann {
388a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
389f383f275SMarcel Holtmann 	__u16 setting;
390a9de9248SMarcel Holtmann 	void *sent;
391a9de9248SMarcel Holtmann 
392a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
393a9de9248SMarcel Holtmann 
394f383f275SMarcel Holtmann 	if (status)
395f383f275SMarcel Holtmann 		return;
396f383f275SMarcel Holtmann 
397a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
398a9de9248SMarcel Holtmann 	if (!sent)
399a9de9248SMarcel Holtmann 		return;
400a9de9248SMarcel Holtmann 
401f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4021da177e4SLinus Torvalds 
403f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
404f383f275SMarcel Holtmann 		return;
405f383f275SMarcel Holtmann 
4061da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4071da177e4SLinus Torvalds 
408a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4091da177e4SLinus Torvalds 
4103c54711cSGustavo F. Padovan 	if (hdev->notify)
4111da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4121da177e4SLinus Torvalds }
4131da177e4SLinus Torvalds 
414a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4151da177e4SLinus Torvalds {
416a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4171da177e4SLinus Torvalds 
418a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4191da177e4SLinus Torvalds 
42023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4211143e5a6SMarcel Holtmann }
4221143e5a6SMarcel Holtmann 
423333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
424333140b5SMarcel Holtmann {
425333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
426333140b5SMarcel Holtmann 	void *sent;
427333140b5SMarcel Holtmann 
428333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
429333140b5SMarcel Holtmann 
430333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
431333140b5SMarcel Holtmann 	if (!sent)
432333140b5SMarcel Holtmann 		return;
433333140b5SMarcel Holtmann 
434c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
435c0ecddc2SJohan Hedberg 		mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
436c0ecddc2SJohan Hedberg 	else if (!status) {
43784bde9d6SJohan Hedberg 		if (*((u8 *) sent))
43884bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
43984bde9d6SJohan Hedberg 		else
44084bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
441c0ecddc2SJohan Hedberg 	}
442333140b5SMarcel Holtmann }
443333140b5SMarcel Holtmann 
444d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
445d5859e22SJohan Hedberg {
446d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
447d5859e22SJohan Hedberg 		return 2;
448d5859e22SJohan Hedberg 
449d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
450d5859e22SJohan Hedberg 		return 1;
451d5859e22SJohan Hedberg 
452d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
453d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
454d5859e22SJohan Hedberg 		return 1;
455d5859e22SJohan Hedberg 
456d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
457d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
458d5859e22SJohan Hedberg 			return 1;
459d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
460d5859e22SJohan Hedberg 			return 1;
461d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
462d5859e22SJohan Hedberg 			return 1;
463d5859e22SJohan Hedberg 	}
464d5859e22SJohan Hedberg 
465d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
466d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
467d5859e22SJohan Hedberg 		return 1;
468d5859e22SJohan Hedberg 
469d5859e22SJohan Hedberg 	return 0;
470d5859e22SJohan Hedberg }
471d5859e22SJohan Hedberg 
472d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
473d5859e22SJohan Hedberg {
474d5859e22SJohan Hedberg 	u8 mode;
475d5859e22SJohan Hedberg 
476d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
477d5859e22SJohan Hedberg 
478d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
479d5859e22SJohan Hedberg }
480d5859e22SJohan Hedberg 
481d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
482d5859e22SJohan Hedberg {
483d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
484d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
485d5859e22SJohan Hedberg 	 * command otherwise */
486d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
487d5859e22SJohan Hedberg 
4886de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
4896de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
4905a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
4916de6c18dSVille Tervo 		return;
4926de6c18dSVille Tervo 
493d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
494d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
495d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
496d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
497d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
498d5859e22SJohan Hedberg 
499d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
500d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
501d5859e22SJohan Hedberg 
502d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
503d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
504d5859e22SJohan Hedberg 
505d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
506d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
507d5859e22SJohan Hedberg 
508d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
509d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
510d5859e22SJohan Hedberg 
511d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
512d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
513d5859e22SJohan Hedberg 
514d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
515d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
516d5859e22SJohan Hedberg 
517d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
518d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
519d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
520d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
521d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
522d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
523d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
524d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
525d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
526d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
527d5859e22SJohan Hedberg 					 * Features Notification */
528d5859e22SJohan Hedberg 	}
529d5859e22SJohan Hedberg 
530d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
531d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
532d5859e22SJohan Hedberg 
533d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
534d5859e22SJohan Hedberg }
535d5859e22SJohan Hedberg 
536e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev)
537e6100a25SAndre Guedes {
538e6100a25SAndre Guedes 	struct hci_cp_write_le_host_supported cp;
539e6100a25SAndre Guedes 
540e6100a25SAndre Guedes 	memset(&cp, 0, sizeof(cp));
541e6100a25SAndre Guedes 
542e6100a25SAndre Guedes 	if (enable_le) {
543e6100a25SAndre Guedes 		cp.le = 1;
544e6100a25SAndre Guedes 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
545e6100a25SAndre Guedes 	}
546e6100a25SAndre Guedes 
547e6100a25SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
548e6100a25SAndre Guedes }
549e6100a25SAndre Guedes 
550d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
551d5859e22SJohan Hedberg {
552e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
553e61ef499SAndrei Emeltchenko 		return;
554e61ef499SAndrei Emeltchenko 
555d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
556d5859e22SJohan Hedberg 
557d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
558d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
559d5859e22SJohan Hedberg 
560*54d04dbbSJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
561*54d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
562d5859e22SJohan Hedberg 			u8 mode = 0x01;
563*54d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
564*54d04dbbSJohan Hedberg 							sizeof(mode), &mode);
565*54d04dbbSJohan Hedberg 		} else {
566*54d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
567*54d04dbbSJohan Hedberg 
568*54d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
569*54d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
570*54d04dbbSJohan Hedberg 
571*54d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
572*54d04dbbSJohan Hedberg 		}
573d5859e22SJohan Hedberg 	}
574d5859e22SJohan Hedberg 
575d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
576d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
577d5859e22SJohan Hedberg 
578d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
579d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
580971e3a4bSAndre Guedes 
581971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
582971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
583971e3a4bSAndre Guedes 
584971e3a4bSAndre Guedes 		cp.page = 0x01;
585971e3a4bSAndre Guedes 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
586971e3a4bSAndre Guedes 							sizeof(cp), &cp);
587971e3a4bSAndre Guedes 	}
588e6100a25SAndre Guedes 
58947990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
59047990ea0SJohan Hedberg 		u8 enable = 1;
59147990ea0SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
59247990ea0SJohan Hedberg 						sizeof(enable), &enable);
59347990ea0SJohan Hedberg 	}
59447990ea0SJohan Hedberg 
595e6100a25SAndre Guedes 	if (hdev->features[4] & LMP_LE)
596e6100a25SAndre Guedes 		hci_set_le_support(hdev);
597d5859e22SJohan Hedberg }
598d5859e22SJohan Hedberg 
599a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
600a9de9248SMarcel Holtmann {
601a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6021143e5a6SMarcel Holtmann 
603a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
6041143e5a6SMarcel Holtmann 
605a9de9248SMarcel Holtmann 	if (rp->status)
606a9de9248SMarcel Holtmann 		return;
6071143e5a6SMarcel Holtmann 
608a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
609e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
610d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
611e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
612d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6131da177e4SLinus Torvalds 
614a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
615a9de9248SMarcel Holtmann 					hdev->manufacturer,
616a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
617d5859e22SJohan Hedberg 
618d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
619d5859e22SJohan Hedberg 		hci_setup(hdev);
620d5859e22SJohan Hedberg }
621d5859e22SJohan Hedberg 
622d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
623d5859e22SJohan Hedberg {
624d5859e22SJohan Hedberg 	u16 link_policy = 0;
625d5859e22SJohan Hedberg 
626d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
627d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
628d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
629d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
630d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
631d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
632d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
633d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
634d5859e22SJohan Hedberg 
635d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
636d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
637d5859e22SJohan Hedberg 					sizeof(link_policy), &link_policy);
6381da177e4SLinus Torvalds }
6391da177e4SLinus Torvalds 
640a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
641a9de9248SMarcel Holtmann {
642a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
643a9de9248SMarcel Holtmann 
644a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
645a9de9248SMarcel Holtmann 
646a9de9248SMarcel Holtmann 	if (rp->status)
647d5859e22SJohan Hedberg 		goto done;
648a9de9248SMarcel Holtmann 
649a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
650d5859e22SJohan Hedberg 
651d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
652d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
653d5859e22SJohan Hedberg 
654d5859e22SJohan Hedberg done:
655d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
656a9de9248SMarcel Holtmann }
657a9de9248SMarcel Holtmann 
658a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
659a9de9248SMarcel Holtmann {
660a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
661a9de9248SMarcel Holtmann 
662a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
663a9de9248SMarcel Holtmann 
664a9de9248SMarcel Holtmann 	if (rp->status)
665a9de9248SMarcel Holtmann 		return;
666a9de9248SMarcel Holtmann 
667a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6681da177e4SLinus Torvalds 
6691da177e4SLinus Torvalds 	/* Adjust default settings according to features
6701da177e4SLinus Torvalds 	 * supported by device. */
671a9de9248SMarcel Holtmann 
6721da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6731da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6741da177e4SLinus Torvalds 
6751da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6761da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6771da177e4SLinus Torvalds 
6785b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6791da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6805b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6815b7f9909SMarcel Holtmann 	}
6821da177e4SLinus Torvalds 
6835b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6841da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6855b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6865b7f9909SMarcel Holtmann 	}
6875b7f9909SMarcel Holtmann 
6885b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6895b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6905b7f9909SMarcel Holtmann 
6915b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6925b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6935b7f9909SMarcel Holtmann 
6945b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6955b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6961da177e4SLinus Torvalds 
697efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
698efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
699efc7688bSMarcel Holtmann 
700efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
701efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
702efc7688bSMarcel Holtmann 
703efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
704efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
705efc7688bSMarcel Holtmann 
706a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
707a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
708a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
709a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
710a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7111da177e4SLinus Torvalds }
7121da177e4SLinus Torvalds 
713971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
714971e3a4bSAndre Guedes 							struct sk_buff *skb)
715971e3a4bSAndre Guedes {
716971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
717971e3a4bSAndre Guedes 
718971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
719971e3a4bSAndre Guedes 
720971e3a4bSAndre Guedes 	if (rp->status)
721971e3a4bSAndre Guedes 		return;
722971e3a4bSAndre Guedes 
723b5b32b65SAndre Guedes 	switch (rp->page) {
724b5b32b65SAndre Guedes 	case 0:
725b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
726b5b32b65SAndre Guedes 		break;
727b5b32b65SAndre Guedes 	case 1:
72859e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
729b5b32b65SAndre Guedes 		break;
730b5b32b65SAndre Guedes 	}
731971e3a4bSAndre Guedes 
732971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
733971e3a4bSAndre Guedes }
734971e3a4bSAndre Guedes 
7351e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7361e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7371e89cffbSAndrei Emeltchenko {
7381e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7391e89cffbSAndrei Emeltchenko 
7401e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7411e89cffbSAndrei Emeltchenko 
7421e89cffbSAndrei Emeltchenko 	if (rp->status)
7431e89cffbSAndrei Emeltchenko 		return;
7441e89cffbSAndrei Emeltchenko 
7451e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7461e89cffbSAndrei Emeltchenko 
7471e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7481e89cffbSAndrei Emeltchenko }
7491e89cffbSAndrei Emeltchenko 
750a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
751a9de9248SMarcel Holtmann {
752a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
753a9de9248SMarcel Holtmann 
754a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
755a9de9248SMarcel Holtmann 
756a9de9248SMarcel Holtmann 	if (rp->status)
757a9de9248SMarcel Holtmann 		return;
758a9de9248SMarcel Holtmann 
759a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
760a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
761a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
762a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
763da1f5198SMarcel Holtmann 
764da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
765da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
766da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
767da1f5198SMarcel Holtmann 	}
768da1f5198SMarcel Holtmann 
769da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
770da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7711da177e4SLinus Torvalds 
772a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
773a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
774a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7751da177e4SLinus Torvalds }
7761da177e4SLinus Torvalds 
777a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
778a9de9248SMarcel Holtmann {
779a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7801da177e4SLinus Torvalds 
781a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
782a9de9248SMarcel Holtmann 
783a9de9248SMarcel Holtmann 	if (!rp->status)
784a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
785a9de9248SMarcel Holtmann 
78623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
78723bb5763SJohan Hedberg }
78823bb5763SJohan Hedberg 
789350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
790350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
791350ee4cfSAndrei Emeltchenko {
792350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
793350ee4cfSAndrei Emeltchenko 
794350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
795350ee4cfSAndrei Emeltchenko 
796350ee4cfSAndrei Emeltchenko 	if (rp->status)
797350ee4cfSAndrei Emeltchenko 		return;
798350ee4cfSAndrei Emeltchenko 
799350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
800350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
801350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
802350ee4cfSAndrei Emeltchenko 
803350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
804350ee4cfSAndrei Emeltchenko 
805350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
806350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
807350ee4cfSAndrei Emeltchenko 
808350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
809350ee4cfSAndrei Emeltchenko }
810350ee4cfSAndrei Emeltchenko 
81123bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
81223bb5763SJohan Hedberg {
81323bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
81423bb5763SJohan Hedberg 
81523bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
81623bb5763SJohan Hedberg 
81723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8181da177e4SLinus Torvalds }
8191da177e4SLinus Torvalds 
820928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
821928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
822928abaa7SAndrei Emeltchenko {
823928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
824928abaa7SAndrei Emeltchenko 
825928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
826928abaa7SAndrei Emeltchenko 
827928abaa7SAndrei Emeltchenko 	if (rp->status)
828928abaa7SAndrei Emeltchenko 		return;
829928abaa7SAndrei Emeltchenko 
830928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
831928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
832928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
833928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
834928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
835928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
836928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
837928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
838928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
839928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
840928abaa7SAndrei Emeltchenko 
841928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
842928abaa7SAndrei Emeltchenko }
843928abaa7SAndrei Emeltchenko 
844b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
845b0916ea0SJohan Hedberg 							struct sk_buff *skb)
846b0916ea0SJohan Hedberg {
847b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
848b0916ea0SJohan Hedberg 
849b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
850b0916ea0SJohan Hedberg 
851b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
852b0916ea0SJohan Hedberg }
853b0916ea0SJohan Hedberg 
854d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
855d5859e22SJohan Hedberg {
856d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
857d5859e22SJohan Hedberg 
858d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
859d5859e22SJohan Hedberg 
860d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
861d5859e22SJohan Hedberg }
862d5859e22SJohan Hedberg 
863d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
864d5859e22SJohan Hedberg 							struct sk_buff *skb)
865d5859e22SJohan Hedberg {
866d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
867d5859e22SJohan Hedberg 
868d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
869d5859e22SJohan Hedberg 
870d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
871d5859e22SJohan Hedberg }
872d5859e22SJohan Hedberg 
873d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
874d5859e22SJohan Hedberg 							struct sk_buff *skb)
875d5859e22SJohan Hedberg {
876d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
877d5859e22SJohan Hedberg 
878d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
879d5859e22SJohan Hedberg 
880d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
881d5859e22SJohan Hedberg }
882d5859e22SJohan Hedberg 
883d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
884d5859e22SJohan Hedberg {
885d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
886d5859e22SJohan Hedberg 
887d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
888d5859e22SJohan Hedberg 
889d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
890d5859e22SJohan Hedberg }
891d5859e22SJohan Hedberg 
892980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
893980e1a53SJohan Hedberg {
894980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
895980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
896980e1a53SJohan Hedberg 	struct hci_conn *conn;
897980e1a53SJohan Hedberg 
898980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
899980e1a53SJohan Hedberg 
90056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
90156e5cb86SJohan Hedberg 
902a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
903744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
904980e1a53SJohan Hedberg 
905980e1a53SJohan Hedberg 	if (rp->status != 0)
90656e5cb86SJohan Hedberg 		goto unlock;
907980e1a53SJohan Hedberg 
908980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
909980e1a53SJohan Hedberg 	if (!cp)
91056e5cb86SJohan Hedberg 		goto unlock;
911980e1a53SJohan Hedberg 
912980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
913980e1a53SJohan Hedberg 	if (conn)
914980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
91556e5cb86SJohan Hedberg 
91656e5cb86SJohan Hedberg unlock:
91756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
918980e1a53SJohan Hedberg }
919980e1a53SJohan Hedberg 
920980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
921980e1a53SJohan Hedberg {
922980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
923980e1a53SJohan Hedberg 
924980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
925980e1a53SJohan Hedberg 
92656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92756e5cb86SJohan Hedberg 
928a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
929744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
930980e1a53SJohan Hedberg 								rp->status);
93156e5cb86SJohan Hedberg 
93256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
933980e1a53SJohan Hedberg }
93456e5cb86SJohan Hedberg 
9356ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9366ed58ec5SVille Tervo 				       struct sk_buff *skb)
9376ed58ec5SVille Tervo {
9386ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9396ed58ec5SVille Tervo 
9406ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9416ed58ec5SVille Tervo 
9426ed58ec5SVille Tervo 	if (rp->status)
9436ed58ec5SVille Tervo 		return;
9446ed58ec5SVille Tervo 
9456ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9466ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9476ed58ec5SVille Tervo 
9486ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9496ed58ec5SVille Tervo 
9506ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9516ed58ec5SVille Tervo 
9526ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9536ed58ec5SVille Tervo }
954980e1a53SJohan Hedberg 
955a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
956a5c29683SJohan Hedberg {
957a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
958a5c29683SJohan Hedberg 
959a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
960a5c29683SJohan Hedberg 
96156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96256e5cb86SJohan Hedberg 
963a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
964272d90dfSJohan Hedberg 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
965272d90dfSJohan Hedberg 								0, rp->status);
96656e5cb86SJohan Hedberg 
96756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
968a5c29683SJohan Hedberg }
969a5c29683SJohan Hedberg 
970a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
971a5c29683SJohan Hedberg 							struct sk_buff *skb)
972a5c29683SJohan Hedberg {
973a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
974a5c29683SJohan Hedberg 
975a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
976a5c29683SJohan Hedberg 
97756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
97856e5cb86SJohan Hedberg 
979a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
980744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
981272d90dfSJohan Hedberg 								ACL_LINK, 0,
982a5c29683SJohan Hedberg 								rp->status);
98356e5cb86SJohan Hedberg 
98456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
985a5c29683SJohan Hedberg }
986a5c29683SJohan Hedberg 
9871143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9881143d458SBrian Gix {
9891143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9901143d458SBrian Gix 
9911143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9921143d458SBrian Gix 
9931143d458SBrian Gix 	hci_dev_lock(hdev);
9941143d458SBrian Gix 
995a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
996272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
997272d90dfSJohan Hedberg 								0, rp->status);
9981143d458SBrian Gix 
9991143d458SBrian Gix 	hci_dev_unlock(hdev);
10001143d458SBrian Gix }
10011143d458SBrian Gix 
10021143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10031143d458SBrian Gix 							struct sk_buff *skb)
10041143d458SBrian Gix {
10051143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10061143d458SBrian Gix 
10071143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10081143d458SBrian Gix 
10091143d458SBrian Gix 	hci_dev_lock(hdev);
10101143d458SBrian Gix 
1011a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10121143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
1013272d90dfSJohan Hedberg 								ACL_LINK, 0,
10141143d458SBrian Gix 								rp->status);
10151143d458SBrian Gix 
10161143d458SBrian Gix 	hci_dev_unlock(hdev);
10171143d458SBrian Gix }
10181143d458SBrian Gix 
1019c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1020c35938b2SSzymon Janc 							struct sk_buff *skb)
1021c35938b2SSzymon Janc {
1022c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1023c35938b2SSzymon Janc 
1024c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1025c35938b2SSzymon Janc 
102656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1027744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1028c35938b2SSzymon Janc 						rp->randomizer, rp->status);
102956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1030c35938b2SSzymon Janc }
1031c35938b2SSzymon Janc 
103207f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
103307f7fa5dSAndre Guedes {
103407f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
103507f7fa5dSAndre Guedes 
103607f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
10377ba8b4beSAndre Guedes 
10387ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
10393fd24153SAndre Guedes 
10403fd24153SAndre Guedes 	if (status) {
10413fd24153SAndre Guedes 		hci_dev_lock(hdev);
10423fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
10433fd24153SAndre Guedes 		hci_dev_unlock(hdev);
10443fd24153SAndre Guedes 		return;
10453fd24153SAndre Guedes 	}
104607f7fa5dSAndre Guedes }
104707f7fa5dSAndre Guedes 
1048eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1049eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1050eb9d91f5SAndre Guedes {
1051eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1052eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1053eb9d91f5SAndre Guedes 
1054eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1055eb9d91f5SAndre Guedes 
1056eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1057eb9d91f5SAndre Guedes 	if (!cp)
1058eb9d91f5SAndre Guedes 		return;
1059eb9d91f5SAndre Guedes 
106068a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
106168a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
10627ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
10637ba8b4beSAndre Guedes 
10643fd24153SAndre Guedes 		if (status) {
10653fd24153SAndre Guedes 			hci_dev_lock(hdev);
10663fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
10673fd24153SAndre Guedes 			hci_dev_unlock(hdev);
10687ba8b4beSAndre Guedes 			return;
10693fd24153SAndre Guedes 		}
10707ba8b4beSAndre Guedes 
1071d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1072d23264a8SAndre Guedes 
1073db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1074a8f13c8cSAndre Guedes 
1075a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1076eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1077343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1078a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
107968a8aea4SAndrei Emeltchenko 		break;
108068a8aea4SAndrei Emeltchenko 
108168a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
10827ba8b4beSAndre Guedes 		if (status)
10837ba8b4beSAndre Guedes 			return;
10847ba8b4beSAndre Guedes 
1085d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1086d23264a8SAndre Guedes 
10875e0452c0SAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
10885e0452c0SAndre Guedes 
10895e0452c0SAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
10905e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
10915e0452c0SAndre Guedes 		} else {
1092c599008fSAndre Guedes 			hci_dev_lock(hdev);
1093c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1094c599008fSAndre Guedes 			hci_dev_unlock(hdev);
10955e0452c0SAndre Guedes 		}
1096c599008fSAndre Guedes 
109768a8aea4SAndrei Emeltchenko 		break;
109868a8aea4SAndrei Emeltchenko 
109968a8aea4SAndrei Emeltchenko 	default:
110068a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
110168a8aea4SAndrei Emeltchenko 		break;
110235815085SAndre Guedes 	}
1103eb9d91f5SAndre Guedes }
1104eb9d91f5SAndre Guedes 
1105a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1106a7a595f6SVinicius Costa Gomes {
1107a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1108a7a595f6SVinicius Costa Gomes 
1109a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1110a7a595f6SVinicius Costa Gomes 
1111a7a595f6SVinicius Costa Gomes 	if (rp->status)
1112a7a595f6SVinicius Costa Gomes 		return;
1113a7a595f6SVinicius Costa Gomes 
1114a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1115a7a595f6SVinicius Costa Gomes }
1116a7a595f6SVinicius Costa Gomes 
1117a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1118a7a595f6SVinicius Costa Gomes {
1119a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1120a7a595f6SVinicius Costa Gomes 
1121a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1122a7a595f6SVinicius Costa Gomes 
1123a7a595f6SVinicius Costa Gomes 	if (rp->status)
1124a7a595f6SVinicius Costa Gomes 		return;
1125a7a595f6SVinicius Costa Gomes 
1126a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1127a7a595f6SVinicius Costa Gomes }
1128a7a595f6SVinicius Costa Gomes 
1129f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1130f9b49306SAndre Guedes 							struct sk_buff *skb)
1131f9b49306SAndre Guedes {
1132f9b49306SAndre Guedes 	struct hci_cp_read_local_ext_features cp;
1133f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1134f9b49306SAndre Guedes 
1135f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1136f9b49306SAndre Guedes 
1137f9b49306SAndre Guedes 	if (status)
1138f9b49306SAndre Guedes 		return;
1139f9b49306SAndre Guedes 
1140f9b49306SAndre Guedes 	cp.page = 0x01;
1141f9b49306SAndre Guedes 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
1142f9b49306SAndre Guedes }
1143f9b49306SAndre Guedes 
1144a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1145a9de9248SMarcel Holtmann {
1146a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1147a9de9248SMarcel Holtmann 
1148a9de9248SMarcel Holtmann 	if (status) {
114923bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1150a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
115156e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1152a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11537a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
115456e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1155314b2381SJohan Hedberg 		return;
1156314b2381SJohan Hedberg 	}
1157314b2381SJohan Hedberg 
115889352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
115989352e7dSAndre Guedes 
116056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1161343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
116256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1163a9de9248SMarcel Holtmann }
1164a9de9248SMarcel Holtmann 
11651da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11661da177e4SLinus Torvalds {
1167a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11681da177e4SLinus Torvalds 	struct hci_conn *conn;
11691da177e4SLinus Torvalds 
1170a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1171a9de9248SMarcel Holtmann 
1172a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11731da177e4SLinus Torvalds 	if (!cp)
11741da177e4SLinus Torvalds 		return;
11751da177e4SLinus Torvalds 
11761da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11771da177e4SLinus Torvalds 
11781da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11791da177e4SLinus Torvalds 
1180a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
11811da177e4SLinus Torvalds 
11821da177e4SLinus Torvalds 	if (status) {
11831da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11844c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11851da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11861da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11871da177e4SLinus Torvalds 				hci_conn_del(conn);
11884c67bc74SMarcel Holtmann 			} else
11894c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11901da177e4SLinus Torvalds 		}
11911da177e4SLinus Torvalds 	} else {
11921da177e4SLinus Torvalds 		if (!conn) {
11931da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11941da177e4SLinus Torvalds 			if (conn) {
1195a0c808b3SJohan Hedberg 				conn->out = true;
11961da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11971da177e4SLinus Torvalds 			} else
1198893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11991da177e4SLinus Torvalds 		}
12001da177e4SLinus Torvalds 	}
12011da177e4SLinus Torvalds 
12021da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12031da177e4SLinus Torvalds }
12041da177e4SLinus Torvalds 
1205a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12061da177e4SLinus Torvalds {
1207a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12081da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12091da177e4SLinus Torvalds 	__u16 handle;
12101da177e4SLinus Torvalds 
1211b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1212b6a0dc82SMarcel Holtmann 
1213a9de9248SMarcel Holtmann 	if (!status)
1214a9de9248SMarcel Holtmann 		return;
1215a9de9248SMarcel Holtmann 
1216a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12171da177e4SLinus Torvalds 	if (!cp)
1218a9de9248SMarcel Holtmann 		return;
12191da177e4SLinus Torvalds 
12201da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12211da177e4SLinus Torvalds 
1222a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12251da177e4SLinus Torvalds 
12261da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12275a08ecceSAndrei Emeltchenko 	if (acl) {
12285a08ecceSAndrei Emeltchenko 		sco = acl->link;
12295a08ecceSAndrei Emeltchenko 		if (sco) {
12301da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12311da177e4SLinus Torvalds 
12321da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12331da177e4SLinus Torvalds 			hci_conn_del(sco);
12341da177e4SLinus Torvalds 		}
12355a08ecceSAndrei Emeltchenko 	}
12361da177e4SLinus Torvalds 
12371da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12381da177e4SLinus Torvalds }
12391da177e4SLinus Torvalds 
1240f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1241f8558555SMarcel Holtmann {
1242f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1243f8558555SMarcel Holtmann 	struct hci_conn *conn;
1244f8558555SMarcel Holtmann 
1245f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1246f8558555SMarcel Holtmann 
1247f8558555SMarcel Holtmann 	if (!status)
1248f8558555SMarcel Holtmann 		return;
1249f8558555SMarcel Holtmann 
1250f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1251f8558555SMarcel Holtmann 	if (!cp)
1252f8558555SMarcel Holtmann 		return;
1253f8558555SMarcel Holtmann 
1254f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1255f8558555SMarcel Holtmann 
1256f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1257f8558555SMarcel Holtmann 	if (conn) {
1258f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1259f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1260f8558555SMarcel Holtmann 			hci_conn_put(conn);
1261f8558555SMarcel Holtmann 		}
1262f8558555SMarcel Holtmann 	}
1263f8558555SMarcel Holtmann 
1264f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1265f8558555SMarcel Holtmann }
1266f8558555SMarcel Holtmann 
1267f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1268f8558555SMarcel Holtmann {
1269f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1270f8558555SMarcel Holtmann 	struct hci_conn *conn;
1271f8558555SMarcel Holtmann 
1272f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1273f8558555SMarcel Holtmann 
1274f8558555SMarcel Holtmann 	if (!status)
1275f8558555SMarcel Holtmann 		return;
1276f8558555SMarcel Holtmann 
1277f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1278f8558555SMarcel Holtmann 	if (!cp)
1279f8558555SMarcel Holtmann 		return;
1280f8558555SMarcel Holtmann 
1281f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1282f8558555SMarcel Holtmann 
1283f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1284f8558555SMarcel Holtmann 	if (conn) {
1285f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1286f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1287f8558555SMarcel Holtmann 			hci_conn_put(conn);
1288f8558555SMarcel Holtmann 		}
1289f8558555SMarcel Holtmann 	}
1290f8558555SMarcel Holtmann 
1291f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1292f8558555SMarcel Holtmann }
1293f8558555SMarcel Holtmann 
1294127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1295392599b9SJohan Hedberg 							struct hci_conn *conn)
1296392599b9SJohan Hedberg {
1297392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1298392599b9SJohan Hedberg 		return 0;
1299392599b9SJohan Hedberg 
1300765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1301392599b9SJohan Hedberg 		return 0;
1302392599b9SJohan Hedberg 
1303392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1304e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1305aa64a8b5SJohan Hedberg 	if (!hci_conn_ssp_enabled(conn) &&
1306e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1307e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1308392599b9SJohan Hedberg 		return 0;
1309392599b9SJohan Hedberg 
1310392599b9SJohan Hedberg 	return 1;
1311392599b9SJohan Hedberg }
1312392599b9SJohan Hedberg 
131330dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e)
131430dc78e1SJohan Hedberg {
131530dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
131630dc78e1SJohan Hedberg 
131730dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
131830dc78e1SJohan Hedberg 
131930dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
132030dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
132130dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
132230dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
132330dc78e1SJohan Hedberg 
132430dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
132530dc78e1SJohan Hedberg }
132630dc78e1SJohan Hedberg 
1327b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
132830dc78e1SJohan Hedberg {
132930dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
133030dc78e1SJohan Hedberg 	struct inquiry_entry *e;
133130dc78e1SJohan Hedberg 
1332b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1333b644ba33SJohan Hedberg 		return false;
1334b644ba33SJohan Hedberg 
1335b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1336b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1337b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1338b644ba33SJohan Hedberg 		return true;
1339b644ba33SJohan Hedberg 	}
1340b644ba33SJohan Hedberg 
1341b644ba33SJohan Hedberg 	return false;
1342b644ba33SJohan Hedberg }
1343b644ba33SJohan Hedberg 
1344b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1345b644ba33SJohan Hedberg 					bdaddr_t *bdaddr, u8 *name, u8 name_len)
1346b644ba33SJohan Hedberg {
1347b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1348b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1349b644ba33SJohan Hedberg 
1350b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
1351b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00,
1352b644ba33SJohan Hedberg 					name, name_len, conn->dev_class);
1353b644ba33SJohan Hedberg 
1354b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1355b644ba33SJohan Hedberg 		return;
1356b644ba33SJohan Hedberg 
135730dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
135830dc78e1SJohan Hedberg 		goto discov_complete;
135930dc78e1SJohan Hedberg 
136030dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
136130dc78e1SJohan Hedberg 		return;
136230dc78e1SJohan Hedberg 
136330dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
136430dc78e1SJohan Hedberg 	if (e) {
136530dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
136630dc78e1SJohan Hedberg 		list_del(&e->list);
1367b644ba33SJohan Hedberg 		if (name)
1368b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1369b644ba33SJohan Hedberg 					e->data.rssi, name, name_len);
137030dc78e1SJohan Hedberg 	}
137130dc78e1SJohan Hedberg 
1372b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
137330dc78e1SJohan Hedberg 		return;
137430dc78e1SJohan Hedberg 
137530dc78e1SJohan Hedberg discov_complete:
137630dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
137730dc78e1SJohan Hedberg }
137830dc78e1SJohan Hedberg 
1379a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13801da177e4SLinus Torvalds {
1381127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1382127178d2SJohan Hedberg 	struct hci_conn *conn;
1383127178d2SJohan Hedberg 
1384a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1385127178d2SJohan Hedberg 
1386127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1387127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1388127178d2SJohan Hedberg 	if (!status)
1389127178d2SJohan Hedberg 		return;
1390127178d2SJohan Hedberg 
1391127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1392127178d2SJohan Hedberg 	if (!cp)
1393127178d2SJohan Hedberg 		return;
1394127178d2SJohan Hedberg 
1395127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1396127178d2SJohan Hedberg 
1397127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1398b644ba33SJohan Hedberg 
1399b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1400b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1401b644ba33SJohan Hedberg 
140279c6c70cSJohan Hedberg 	if (!conn)
140379c6c70cSJohan Hedberg 		goto unlock;
140479c6c70cSJohan Hedberg 
140579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
140679c6c70cSJohan Hedberg 		goto unlock;
140779c6c70cSJohan Hedberg 
140851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1409127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1410127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1411127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1412127178d2SJohan Hedberg 	}
1413127178d2SJohan Hedberg 
141479c6c70cSJohan Hedberg unlock:
1415127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1416a9de9248SMarcel Holtmann }
14171da177e4SLinus Torvalds 
1418769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1419769be974SMarcel Holtmann {
1420769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1421769be974SMarcel Holtmann 	struct hci_conn *conn;
1422769be974SMarcel Holtmann 
1423769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1424769be974SMarcel Holtmann 
1425769be974SMarcel Holtmann 	if (!status)
1426769be974SMarcel Holtmann 		return;
1427769be974SMarcel Holtmann 
1428769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1429769be974SMarcel Holtmann 	if (!cp)
1430769be974SMarcel Holtmann 		return;
1431769be974SMarcel Holtmann 
1432769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1433769be974SMarcel Holtmann 
1434769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1435769be974SMarcel Holtmann 	if (conn) {
1436769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1437769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1438769be974SMarcel Holtmann 			hci_conn_put(conn);
1439769be974SMarcel Holtmann 		}
1440769be974SMarcel Holtmann 	}
1441769be974SMarcel Holtmann 
1442769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1443769be974SMarcel Holtmann }
1444769be974SMarcel Holtmann 
1445769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1446769be974SMarcel Holtmann {
1447769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1448769be974SMarcel Holtmann 	struct hci_conn *conn;
1449769be974SMarcel Holtmann 
1450769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1451769be974SMarcel Holtmann 
1452769be974SMarcel Holtmann 	if (!status)
1453769be974SMarcel Holtmann 		return;
1454769be974SMarcel Holtmann 
1455769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1456769be974SMarcel Holtmann 	if (!cp)
1457769be974SMarcel Holtmann 		return;
1458769be974SMarcel Holtmann 
1459769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1460769be974SMarcel Holtmann 
1461769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1462769be974SMarcel Holtmann 	if (conn) {
1463769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1464769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1465769be974SMarcel Holtmann 			hci_conn_put(conn);
1466769be974SMarcel Holtmann 		}
1467769be974SMarcel Holtmann 	}
1468769be974SMarcel Holtmann 
1469769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1470769be974SMarcel Holtmann }
1471769be974SMarcel Holtmann 
1472a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1473a9de9248SMarcel Holtmann {
1474b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1475b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1476b6a0dc82SMarcel Holtmann 	__u16 handle;
1477b6a0dc82SMarcel Holtmann 
1478a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1479b6a0dc82SMarcel Holtmann 
1480b6a0dc82SMarcel Holtmann 	if (!status)
1481b6a0dc82SMarcel Holtmann 		return;
1482b6a0dc82SMarcel Holtmann 
1483b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1484b6a0dc82SMarcel Holtmann 	if (!cp)
1485b6a0dc82SMarcel Holtmann 		return;
1486b6a0dc82SMarcel Holtmann 
1487b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1488b6a0dc82SMarcel Holtmann 
1489b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1490b6a0dc82SMarcel Holtmann 
1491b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1492b6a0dc82SMarcel Holtmann 
1493b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14945a08ecceSAndrei Emeltchenko 	if (acl) {
14955a08ecceSAndrei Emeltchenko 		sco = acl->link;
14965a08ecceSAndrei Emeltchenko 		if (sco) {
1497b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1498b6a0dc82SMarcel Holtmann 
1499b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1500b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1501b6a0dc82SMarcel Holtmann 		}
15025a08ecceSAndrei Emeltchenko 	}
1503b6a0dc82SMarcel Holtmann 
1504b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1505a9de9248SMarcel Holtmann }
1506a9de9248SMarcel Holtmann 
1507a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1508a9de9248SMarcel Holtmann {
1509a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
151004837f64SMarcel Holtmann 	struct hci_conn *conn;
151104837f64SMarcel Holtmann 
1512a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1513a9de9248SMarcel Holtmann 
1514a9de9248SMarcel Holtmann 	if (!status)
1515a9de9248SMarcel Holtmann 		return;
1516a9de9248SMarcel Holtmann 
1517a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
151804837f64SMarcel Holtmann 	if (!cp)
1519a9de9248SMarcel Holtmann 		return;
152004837f64SMarcel Holtmann 
152104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
152204837f64SMarcel Holtmann 
152304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1524e73439d8SMarcel Holtmann 	if (conn) {
152551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
152604837f64SMarcel Holtmann 
152751a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1528e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1529e73439d8SMarcel Holtmann 	}
1530e73439d8SMarcel Holtmann 
153104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
153204837f64SMarcel Holtmann }
153304837f64SMarcel Holtmann 
1534a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1535a9de9248SMarcel Holtmann {
1536a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
153704837f64SMarcel Holtmann 	struct hci_conn *conn;
153804837f64SMarcel Holtmann 
1539a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1540a9de9248SMarcel Holtmann 
1541a9de9248SMarcel Holtmann 	if (!status)
1542a9de9248SMarcel Holtmann 		return;
1543a9de9248SMarcel Holtmann 
1544a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
154504837f64SMarcel Holtmann 	if (!cp)
1546a9de9248SMarcel Holtmann 		return;
154704837f64SMarcel Holtmann 
154804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
154904837f64SMarcel Holtmann 
155004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1551e73439d8SMarcel Holtmann 	if (conn) {
155251a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
155304837f64SMarcel Holtmann 
155451a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1555e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1556e73439d8SMarcel Holtmann 	}
1557e73439d8SMarcel Holtmann 
155804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
155904837f64SMarcel Holtmann }
156004837f64SMarcel Holtmann 
156188c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
156288c3df13SJohan Hedberg {
156388c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
156488c3df13SJohan Hedberg 	struct hci_conn *conn;
156588c3df13SJohan Hedberg 
156688c3df13SJohan Hedberg 	if (!status)
156788c3df13SJohan Hedberg 		return;
156888c3df13SJohan Hedberg 
156988c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
157088c3df13SJohan Hedberg 	if (!cp)
157188c3df13SJohan Hedberg 		return;
157288c3df13SJohan Hedberg 
157388c3df13SJohan Hedberg 	hci_dev_lock(hdev);
157488c3df13SJohan Hedberg 
157588c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
157688c3df13SJohan Hedberg 	if (conn)
157788c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
157888c3df13SJohan Hedberg 						conn->dst_type, status);
157988c3df13SJohan Hedberg 
158088c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
158188c3df13SJohan Hedberg }
158288c3df13SJohan Hedberg 
1583fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1584fcd89c09SVille Tervo {
1585fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1586fcd89c09SVille Tervo 	struct hci_conn *conn;
1587fcd89c09SVille Tervo 
1588fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1589fcd89c09SVille Tervo 
1590fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1591fcd89c09SVille Tervo 	if (!cp)
1592fcd89c09SVille Tervo 		return;
1593fcd89c09SVille Tervo 
1594fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1595fcd89c09SVille Tervo 
1596fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1597fcd89c09SVille Tervo 
1598fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1599fcd89c09SVille Tervo 		conn);
1600fcd89c09SVille Tervo 
1601fcd89c09SVille Tervo 	if (status) {
1602fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1603fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1604fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1605fcd89c09SVille Tervo 			hci_conn_del(conn);
1606fcd89c09SVille Tervo 		}
1607fcd89c09SVille Tervo 	} else {
1608fcd89c09SVille Tervo 		if (!conn) {
1609fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
161029b7988aSAndre Guedes 			if (conn) {
161129b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1612a0c808b3SJohan Hedberg 				conn->out = true;
161329b7988aSAndre Guedes 			} else {
1614fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1615fcd89c09SVille Tervo 			}
1616fcd89c09SVille Tervo 		}
161729b7988aSAndre Guedes 	}
1618fcd89c09SVille Tervo 
1619fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1620fcd89c09SVille Tervo }
1621fcd89c09SVille Tervo 
1622a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1623a7a595f6SVinicius Costa Gomes {
1624a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1625a7a595f6SVinicius Costa Gomes }
1626a7a595f6SVinicius Costa Gomes 
16271da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16281da177e4SLinus Torvalds {
16291da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
163030dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
163130dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16321da177e4SLinus Torvalds 
16331da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
16341da177e4SLinus Torvalds 
163523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16366bd57416SMarcel Holtmann 
1637a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
163889352e7dSAndre Guedes 
163989352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
164089352e7dSAndre Guedes 		return;
164189352e7dSAndre Guedes 
1642a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
164330dc78e1SJohan Hedberg 		return;
164430dc78e1SJohan Hedberg 
164556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
164630dc78e1SJohan Hedberg 
1647343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
164830dc78e1SJohan Hedberg 		goto unlock;
164930dc78e1SJohan Hedberg 
165030dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1651ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
165230dc78e1SJohan Hedberg 		goto unlock;
165330dc78e1SJohan Hedberg 	}
165430dc78e1SJohan Hedberg 
165530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
165630dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
165730dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
165830dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
165930dc78e1SJohan Hedberg 	} else {
166030dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
166130dc78e1SJohan Hedberg 	}
166230dc78e1SJohan Hedberg 
166330dc78e1SJohan Hedberg unlock:
166456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16651da177e4SLinus Torvalds }
16661da177e4SLinus Torvalds 
16671da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16681da177e4SLinus Torvalds {
166945bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1670a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16711da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16721da177e4SLinus Torvalds 
16731da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16741da177e4SLinus Torvalds 
167545bb4bf0SMarcel Holtmann 	if (!num_rsp)
167645bb4bf0SMarcel Holtmann 		return;
167745bb4bf0SMarcel Holtmann 
16781da177e4SLinus Torvalds 	hci_dev_lock(hdev);
167945bb4bf0SMarcel Holtmann 
1680e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
16813175405bSJohan Hedberg 		bool name_known;
16823175405bSJohan Hedberg 
16831da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16841da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16851da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16861da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16871da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16881da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16891da177e4SLinus Torvalds 		data.rssi		= 0x00;
169041a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16913175405bSJohan Hedberg 
16923175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false);
169348264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
16947d262f86SAndre Guedes 					info->dev_class, 0, !name_known,
16957d262f86SAndre Guedes 					NULL, 0);
16961da177e4SLinus Torvalds 	}
169745bb4bf0SMarcel Holtmann 
16981da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16991da177e4SLinus Torvalds }
17001da177e4SLinus Torvalds 
1701a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17021da177e4SLinus Torvalds {
1703a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1704a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17051da177e4SLinus Torvalds 
1706a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
170745bb4bf0SMarcel Holtmann 
17081da177e4SLinus Torvalds 	hci_dev_lock(hdev);
170945bb4bf0SMarcel Holtmann 
1710a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17119499237aSMarcel Holtmann 	if (!conn) {
17129499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17139499237aSMarcel Holtmann 			goto unlock;
17149499237aSMarcel Holtmann 
17159499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1716a9de9248SMarcel Holtmann 		if (!conn)
1717a9de9248SMarcel Holtmann 			goto unlock;
171845bb4bf0SMarcel Holtmann 
17199499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17209499237aSMarcel Holtmann 	}
17219499237aSMarcel Holtmann 
1722a9de9248SMarcel Holtmann 	if (!ev->status) {
1723a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1724769be974SMarcel Holtmann 
1725769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1726769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1727769be974SMarcel Holtmann 			hci_conn_hold(conn);
1728052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1729769be974SMarcel Holtmann 		} else
1730a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1731a9de9248SMarcel Holtmann 
17329eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
17337d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17347d0db0a3SMarcel Holtmann 
1735a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1736a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1737a9de9248SMarcel Holtmann 
1738a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1739a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1740a9de9248SMarcel Holtmann 
1741a9de9248SMarcel Holtmann 		/* Get remote features */
1742a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1743a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1744a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1745769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1746769be974SMarcel Holtmann 							sizeof(cp), &cp);
174745bb4bf0SMarcel Holtmann 		}
1748a9de9248SMarcel Holtmann 
1749a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1750d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1751a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1752a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1753a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1754a8746417SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
1755a8746417SMarcel Holtmann 							sizeof(cp), &cp);
1756a9de9248SMarcel Holtmann 		}
175717d5c04cSJohan Hedberg 	} else {
1758a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
175917d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1760744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
176148264f06SJohan Hedberg 						conn->dst_type, ev->status);
176217d5c04cSJohan Hedberg 	}
176345bb4bf0SMarcel Holtmann 
1764e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1765e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
176645bb4bf0SMarcel Holtmann 
1767769be974SMarcel Holtmann 	if (ev->status) {
1768a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1769a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1770c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1771c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1772a9de9248SMarcel Holtmann 
1773a9de9248SMarcel Holtmann unlock:
17741da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1775a9de9248SMarcel Holtmann 
1776a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
17771da177e4SLinus Torvalds }
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17801da177e4SLinus Torvalds {
1781a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17821da177e4SLinus Torvalds 	int mask = hdev->link_mode;
17831da177e4SLinus Torvalds 
1784a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
17851da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
17861da177e4SLinus Torvalds 
17871da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
17881da177e4SLinus Torvalds 
1789138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1790138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
17911da177e4SLinus Torvalds 		/* Connection accepted */
1792c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17931da177e4SLinus Torvalds 		struct hci_conn *conn;
17941da177e4SLinus Torvalds 
17951da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1796b6a0dc82SMarcel Holtmann 
1797cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1798cc11b9c1SAndrei Emeltchenko 		if (ie)
1799c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1800c7bdd502SMarcel Holtmann 
18011da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
18021da177e4SLinus Torvalds 		if (!conn) {
1803cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1804cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1805893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
18061da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
18071da177e4SLinus Torvalds 				return;
18081da177e4SLinus Torvalds 			}
18091da177e4SLinus Torvalds 		}
1810b6a0dc82SMarcel Holtmann 
18111da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
18121da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1813b6a0dc82SMarcel Holtmann 
18141da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
18151da177e4SLinus Torvalds 
1816b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1817b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1818b6a0dc82SMarcel Holtmann 
18191da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
18201da177e4SLinus Torvalds 
18211da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
18221da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
18231da177e4SLinus Torvalds 			else
18241da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
18251da177e4SLinus Torvalds 
1826b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ,
1827b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1828b6a0dc82SMarcel Holtmann 		} else {
1829b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1830b6a0dc82SMarcel Holtmann 
1831b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1832a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1833b6a0dc82SMarcel Holtmann 
1834b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1835b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1836b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1837b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1838b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1839b6a0dc82SMarcel Holtmann 
1840b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1841b6a0dc82SMarcel Holtmann 							sizeof(cp), &cp);
1842b6a0dc82SMarcel Holtmann 		}
18431da177e4SLinus Torvalds 	} else {
18441da177e4SLinus Torvalds 		/* Connection rejected */
18451da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18461da177e4SLinus Torvalds 
18471da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18489f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1849a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18501da177e4SLinus Torvalds 	}
18511da177e4SLinus Torvalds }
18521da177e4SLinus Torvalds 
18531da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18541da177e4SLinus Torvalds {
1855a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
185604837f64SMarcel Holtmann 	struct hci_conn *conn;
18571da177e4SLinus Torvalds 
18581da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
18591da177e4SLinus Torvalds 
18601da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18611da177e4SLinus Torvalds 
186204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1863f7520543SJohan Hedberg 	if (!conn)
1864f7520543SJohan Hedberg 		goto unlock;
1865f7520543SJohan Hedberg 
186637d9ef76SJohan Hedberg 	if (ev->status == 0)
18671da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18687d0db0a3SMarcel Holtmann 
1869b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1870b644ba33SJohan Hedberg 			(conn->type == ACL_LINK || conn->type == LE_LINK)) {
187137d9ef76SJohan Hedberg 		if (ev->status != 0)
187288c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
187388c3df13SJohan Hedberg 						conn->dst_type, ev->status);
187437d9ef76SJohan Hedberg 		else
1875afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
187648264f06SJohan Hedberg 							conn->dst_type);
187737d9ef76SJohan Hedberg 	}
1878f7520543SJohan Hedberg 
187937d9ef76SJohan Hedberg 	if (ev->status == 0) {
18802950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
18811da177e4SLinus Torvalds 		hci_conn_del(conn);
188237d9ef76SJohan Hedberg 	}
18831da177e4SLinus Torvalds 
1884f7520543SJohan Hedberg unlock:
18851da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18861da177e4SLinus Torvalds }
18871da177e4SLinus Torvalds 
1888a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1889a9de9248SMarcel Holtmann {
1890a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1891a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1892a9de9248SMarcel Holtmann 
1893a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1894a9de9248SMarcel Holtmann 
1895a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1896a9de9248SMarcel Holtmann 
1897a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1898d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1899d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1900d7556e20SWaldemar Rymarkiewicz 
1901765c2a96SJohan Hedberg 	if (!ev->status) {
1902aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
190351a8efd7SJohan Hedberg 				test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1904d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
190519f8def0SWaldemar Rymarkiewicz 		} else {
1906a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1907765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
190819f8def0SWaldemar Rymarkiewicz 		}
19092a611692SJohan Hedberg 	} else {
1910bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1911bab73cb6SJohan Hedberg 								ev->status);
19122a611692SJohan Hedberg 	}
1913a9de9248SMarcel Holtmann 
191451a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
191551a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1916a9de9248SMarcel Holtmann 
1917f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1918aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1919f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1920f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1921f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1922d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1923d7556e20SWaldemar Rymarkiewicz 									&cp);
1924f8558555SMarcel Holtmann 		} else {
1925f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1926f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1927f8558555SMarcel Holtmann 			hci_conn_put(conn);
1928f8558555SMarcel Holtmann 		}
1929052b30b0SMarcel Holtmann 	} else {
1930a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1931a9de9248SMarcel Holtmann 
1932052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1933052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1934052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1935052b30b0SMarcel Holtmann 	}
1936052b30b0SMarcel Holtmann 
193751a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1938a9de9248SMarcel Holtmann 		if (!ev->status) {
1939a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1940f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1941f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1942d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1943d7556e20SWaldemar Rymarkiewicz 									&cp);
1944a9de9248SMarcel Holtmann 		} else {
194551a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1946a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1947a9de9248SMarcel Holtmann 		}
1948a9de9248SMarcel Holtmann 	}
1949a9de9248SMarcel Holtmann 
1950d7556e20SWaldemar Rymarkiewicz unlock:
1951a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1952a9de9248SMarcel Holtmann }
1953a9de9248SMarcel Holtmann 
1954a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1955a9de9248SMarcel Holtmann {
1956127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1957127178d2SJohan Hedberg 	struct hci_conn *conn;
1958127178d2SJohan Hedberg 
1959a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1960a9de9248SMarcel Holtmann 
1961a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1962127178d2SJohan Hedberg 
1963127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1964127178d2SJohan Hedberg 
1965127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1966b644ba33SJohan Hedberg 
1967b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1968b644ba33SJohan Hedberg 		goto check_auth;
1969b644ba33SJohan Hedberg 
1970b644ba33SJohan Hedberg 	if (ev->status == 0)
1971b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1972b644ba33SJohan Hedberg 					strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1973b644ba33SJohan Hedberg 	else
1974b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1975b644ba33SJohan Hedberg 
1976b644ba33SJohan Hedberg check_auth:
197779c6c70cSJohan Hedberg 	if (!conn)
197879c6c70cSJohan Hedberg 		goto unlock;
197979c6c70cSJohan Hedberg 
198079c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
198179c6c70cSJohan Hedberg 		goto unlock;
198279c6c70cSJohan Hedberg 
198351a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1984127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1985127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1986127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1987127178d2SJohan Hedberg 	}
1988127178d2SJohan Hedberg 
198979c6c70cSJohan Hedberg unlock:
1990127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1991a9de9248SMarcel Holtmann }
1992a9de9248SMarcel Holtmann 
1993a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1994a9de9248SMarcel Holtmann {
1995a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1996a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1997a9de9248SMarcel Holtmann 
1998a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1999a9de9248SMarcel Holtmann 
2000a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2001a9de9248SMarcel Holtmann 
2002a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2003a9de9248SMarcel Holtmann 	if (conn) {
2004a9de9248SMarcel Holtmann 		if (!ev->status) {
2005ae293196SMarcel Holtmann 			if (ev->encrypt) {
2006ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2007ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2008a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2009da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2010ae293196SMarcel Holtmann 			} else
2011a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2012a9de9248SMarcel Holtmann 		}
2013a9de9248SMarcel Holtmann 
201451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2015a9de9248SMarcel Holtmann 
2016f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2017f8558555SMarcel Holtmann 			if (!ev->status)
2018f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2019f8558555SMarcel Holtmann 
2020f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2021f8558555SMarcel Holtmann 			hci_conn_put(conn);
2022f8558555SMarcel Holtmann 		} else
2023a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2024a9de9248SMarcel Holtmann 	}
2025a9de9248SMarcel Holtmann 
2026a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2027a9de9248SMarcel Holtmann }
2028a9de9248SMarcel Holtmann 
2029a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2030a9de9248SMarcel Holtmann {
2031a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2032a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2033a9de9248SMarcel Holtmann 
2034a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2035a9de9248SMarcel Holtmann 
2036a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2037a9de9248SMarcel Holtmann 
2038a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2039a9de9248SMarcel Holtmann 	if (conn) {
2040a9de9248SMarcel Holtmann 		if (!ev->status)
2041a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2042a9de9248SMarcel Holtmann 
204351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2044a9de9248SMarcel Holtmann 
2045a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2046a9de9248SMarcel Holtmann 	}
2047a9de9248SMarcel Holtmann 
2048a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2049a9de9248SMarcel Holtmann }
2050a9de9248SMarcel Holtmann 
2051a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2052a9de9248SMarcel Holtmann {
2053a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2054a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2055a9de9248SMarcel Holtmann 
2056a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2057a9de9248SMarcel Holtmann 
2058a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2059a9de9248SMarcel Holtmann 
2060a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2061ccd556feSJohan Hedberg 	if (!conn)
2062ccd556feSJohan Hedberg 		goto unlock;
2063ccd556feSJohan Hedberg 
2064769be974SMarcel Holtmann 	if (!ev->status)
2065a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2066a9de9248SMarcel Holtmann 
2067ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2068ccd556feSJohan Hedberg 		goto unlock;
2069ccd556feSJohan Hedberg 
2070ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2071769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2072769be974SMarcel Holtmann 		cp.handle = ev->handle;
2073769be974SMarcel Holtmann 		cp.page = 0x01;
2074ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2075769be974SMarcel Holtmann 							sizeof(cp), &cp);
2076392599b9SJohan Hedberg 		goto unlock;
2077392599b9SJohan Hedberg 	}
2078392599b9SJohan Hedberg 
2079127178d2SJohan Hedberg 	if (!ev->status) {
2080127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2081127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2082127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2083127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2084127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2085b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2086b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2087b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2088b644ba33SJohan Hedberg 						conn->dev_class);
2089392599b9SJohan Hedberg 
2090127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2091769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2092769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2093769be974SMarcel Holtmann 		hci_conn_put(conn);
2094769be974SMarcel Holtmann 	}
2095769be974SMarcel Holtmann 
2096ccd556feSJohan Hedberg unlock:
2097a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2098a9de9248SMarcel Holtmann }
2099a9de9248SMarcel Holtmann 
2100a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2101a9de9248SMarcel Holtmann {
2102a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2103a9de9248SMarcel Holtmann }
2104a9de9248SMarcel Holtmann 
2105a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2106a9de9248SMarcel Holtmann {
2107a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2108a9de9248SMarcel Holtmann }
2109a9de9248SMarcel Holtmann 
2110a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2111a9de9248SMarcel Holtmann {
2112a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2113a9de9248SMarcel Holtmann 	__u16 opcode;
2114a9de9248SMarcel Holtmann 
2115a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2116a9de9248SMarcel Holtmann 
2117a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2118a9de9248SMarcel Holtmann 
2119a9de9248SMarcel Holtmann 	switch (opcode) {
2120a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2121a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2122a9de9248SMarcel Holtmann 		break;
2123a9de9248SMarcel Holtmann 
2124a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2125a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2126a9de9248SMarcel Holtmann 		break;
2127a9de9248SMarcel Holtmann 
2128a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2129a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2130a9de9248SMarcel Holtmann 		break;
2131a9de9248SMarcel Holtmann 
2132a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2133a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2134a9de9248SMarcel Holtmann 		break;
2135a9de9248SMarcel Holtmann 
2136e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2137e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2138e4e8e37cSMarcel Holtmann 		break;
2139e4e8e37cSMarcel Holtmann 
2140a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2141a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2142a9de9248SMarcel Holtmann 		break;
2143a9de9248SMarcel Holtmann 
2144e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2145e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2146e4e8e37cSMarcel Holtmann 		break;
2147e4e8e37cSMarcel Holtmann 
2148e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2149e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2150e4e8e37cSMarcel Holtmann 		break;
2151e4e8e37cSMarcel Holtmann 
2152a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2153a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2154a9de9248SMarcel Holtmann 		break;
2155a9de9248SMarcel Holtmann 
2156a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2157a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2158a9de9248SMarcel Holtmann 		break;
2159a9de9248SMarcel Holtmann 
2160a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2161a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2162a9de9248SMarcel Holtmann 		break;
2163a9de9248SMarcel Holtmann 
2164a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2165a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2166a9de9248SMarcel Holtmann 		break;
2167a9de9248SMarcel Holtmann 
2168a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2169a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2170a9de9248SMarcel Holtmann 		break;
2171a9de9248SMarcel Holtmann 
2172a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2173a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2174a9de9248SMarcel Holtmann 		break;
2175a9de9248SMarcel Holtmann 
2176a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2177a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2178a9de9248SMarcel Holtmann 		break;
2179a9de9248SMarcel Holtmann 
2180a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2181a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2182a9de9248SMarcel Holtmann 		break;
2183a9de9248SMarcel Holtmann 
2184a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2185a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2186a9de9248SMarcel Holtmann 		break;
2187a9de9248SMarcel Holtmann 
2188a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2189a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2190a9de9248SMarcel Holtmann 		break;
2191a9de9248SMarcel Holtmann 
2192a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2193a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2194a9de9248SMarcel Holtmann 		break;
2195a9de9248SMarcel Holtmann 
2196333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2197333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2198333140b5SMarcel Holtmann 		break;
2199333140b5SMarcel Holtmann 
2200a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2201a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2202a9de9248SMarcel Holtmann 		break;
2203a9de9248SMarcel Holtmann 
2204a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2205a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2206a9de9248SMarcel Holtmann 		break;
2207a9de9248SMarcel Holtmann 
2208a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2209a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2210a9de9248SMarcel Holtmann 		break;
2211a9de9248SMarcel Holtmann 
2212971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2213971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2214971e3a4bSAndre Guedes 		break;
2215971e3a4bSAndre Guedes 
2216a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2217a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2218a9de9248SMarcel Holtmann 		break;
2219a9de9248SMarcel Holtmann 
2220a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2221a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2222a9de9248SMarcel Holtmann 		break;
2223a9de9248SMarcel Holtmann 
2224350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2225350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2226350ee4cfSAndrei Emeltchenko 		break;
2227350ee4cfSAndrei Emeltchenko 
222823bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
222923bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
223023bb5763SJohan Hedberg 		break;
223123bb5763SJohan Hedberg 
22321e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22331e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22341e89cffbSAndrei Emeltchenko 		break;
22351e89cffbSAndrei Emeltchenko 
2236928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2237928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2238928abaa7SAndrei Emeltchenko 		break;
2239928abaa7SAndrei Emeltchenko 
2240b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2241b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2242b0916ea0SJohan Hedberg 		break;
2243b0916ea0SJohan Hedberg 
2244d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2245d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2246d5859e22SJohan Hedberg 		break;
2247d5859e22SJohan Hedberg 
2248d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2249d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2250d5859e22SJohan Hedberg 		break;
2251d5859e22SJohan Hedberg 
2252d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2253d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2254d5859e22SJohan Hedberg 		break;
2255d5859e22SJohan Hedberg 
2256d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2257d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2258d5859e22SJohan Hedberg 		break;
2259d5859e22SJohan Hedberg 
2260980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2261980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2262980e1a53SJohan Hedberg 		break;
2263980e1a53SJohan Hedberg 
2264980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2265980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2266980e1a53SJohan Hedberg 		break;
2267980e1a53SJohan Hedberg 
2268c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2269c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2270c35938b2SSzymon Janc 		break;
2271c35938b2SSzymon Janc 
22726ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22736ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22746ed58ec5SVille Tervo 		break;
22756ed58ec5SVille Tervo 
2276a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2277a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2278a5c29683SJohan Hedberg 		break;
2279a5c29683SJohan Hedberg 
2280a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2281a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2282a5c29683SJohan Hedberg 		break;
2283a5c29683SJohan Hedberg 
22841143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
22851143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
22861143d458SBrian Gix 		break;
22871143d458SBrian Gix 
22881143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
22891143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
229007f7fa5dSAndre Guedes 
229107f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
229207f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
22931143d458SBrian Gix 		break;
22941143d458SBrian Gix 
2295eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2296eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2297eb9d91f5SAndre Guedes 		break;
2298eb9d91f5SAndre Guedes 
2299a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2300a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2301a7a595f6SVinicius Costa Gomes 		break;
2302a7a595f6SVinicius Costa Gomes 
2303a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2304a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2305a7a595f6SVinicius Costa Gomes 		break;
2306a7a595f6SVinicius Costa Gomes 
2307f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2308f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2309f9b49306SAndre Guedes 		break;
2310f9b49306SAndre Guedes 
2311a9de9248SMarcel Holtmann 	default:
2312a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2313a9de9248SMarcel Holtmann 		break;
2314a9de9248SMarcel Holtmann 	}
2315a9de9248SMarcel Holtmann 
23166bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23176bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23186bd32326SVille Tervo 
2319a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2320a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2321a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2322c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2323a9de9248SMarcel Holtmann 	}
2324a9de9248SMarcel Holtmann }
2325a9de9248SMarcel Holtmann 
2326a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2327a9de9248SMarcel Holtmann {
2328a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2329a9de9248SMarcel Holtmann 	__u16 opcode;
2330a9de9248SMarcel Holtmann 
2331a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2332a9de9248SMarcel Holtmann 
2333a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2334a9de9248SMarcel Holtmann 
2335a9de9248SMarcel Holtmann 	switch (opcode) {
2336a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2337a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2338a9de9248SMarcel Holtmann 		break;
2339a9de9248SMarcel Holtmann 
2340a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2341a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2342a9de9248SMarcel Holtmann 		break;
2343a9de9248SMarcel Holtmann 
2344a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2345a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2346a9de9248SMarcel Holtmann 		break;
2347a9de9248SMarcel Holtmann 
2348f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2349f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2350f8558555SMarcel Holtmann 		break;
2351f8558555SMarcel Holtmann 
2352f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2353f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2354f8558555SMarcel Holtmann 		break;
2355f8558555SMarcel Holtmann 
2356a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2357a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2358a9de9248SMarcel Holtmann 		break;
2359a9de9248SMarcel Holtmann 
2360769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2361769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2362769be974SMarcel Holtmann 		break;
2363769be974SMarcel Holtmann 
2364769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2365769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2366769be974SMarcel Holtmann 		break;
2367769be974SMarcel Holtmann 
2368a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2369a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2370a9de9248SMarcel Holtmann 		break;
2371a9de9248SMarcel Holtmann 
2372a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2373a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2374a9de9248SMarcel Holtmann 		break;
2375a9de9248SMarcel Holtmann 
2376a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2377a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2378a9de9248SMarcel Holtmann 		break;
2379a9de9248SMarcel Holtmann 
23808962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
238188c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
23828962ee74SJohan Hedberg 		break;
23838962ee74SJohan Hedberg 
2384fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2385fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2386fcd89c09SVille Tervo 		break;
2387fcd89c09SVille Tervo 
2388a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2389a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2390a7a595f6SVinicius Costa Gomes 		break;
2391a7a595f6SVinicius Costa Gomes 
2392a9de9248SMarcel Holtmann 	default:
2393a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2394a9de9248SMarcel Holtmann 		break;
2395a9de9248SMarcel Holtmann 	}
2396a9de9248SMarcel Holtmann 
23976bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23986bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23996bd32326SVille Tervo 
240010572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2401a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2402a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2403c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2404a9de9248SMarcel Holtmann 	}
2405a9de9248SMarcel Holtmann }
2406a9de9248SMarcel Holtmann 
2407a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2408a9de9248SMarcel Holtmann {
2409a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2410a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2411a9de9248SMarcel Holtmann 
2412a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2413a9de9248SMarcel Holtmann 
2414a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2415a9de9248SMarcel Holtmann 
2416a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2417a9de9248SMarcel Holtmann 	if (conn) {
2418a9de9248SMarcel Holtmann 		if (!ev->status) {
2419a9de9248SMarcel Holtmann 			if (ev->role)
2420a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2421a9de9248SMarcel Holtmann 			else
2422a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2423a9de9248SMarcel Holtmann 		}
2424a9de9248SMarcel Holtmann 
242551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2426a9de9248SMarcel Holtmann 
2427a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2428a9de9248SMarcel Holtmann 	}
2429a9de9248SMarcel Holtmann 
2430a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2431a9de9248SMarcel Holtmann }
2432a9de9248SMarcel Holtmann 
24331da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24341da177e4SLinus Torvalds {
2435a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24361da177e4SLinus Torvalds 	int i;
24371da177e4SLinus Torvalds 
243832ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
243932ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
244032ac5b9bSAndrei Emeltchenko 		return;
244132ac5b9bSAndrei Emeltchenko 	}
244232ac5b9bSAndrei Emeltchenko 
2443c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2444c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24451da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24461da177e4SLinus Torvalds 		return;
24471da177e4SLinus Torvalds 	}
24481da177e4SLinus Torvalds 
2449c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2450c5993de8SAndrei Emeltchenko 
2451613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2452613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24531da177e4SLinus Torvalds 		struct hci_conn *conn;
24541da177e4SLinus Torvalds 		__u16  handle, count;
24551da177e4SLinus Torvalds 
2456613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2457613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24581da177e4SLinus Torvalds 
24591da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2460f4280918SAndrei Emeltchenko 		if (!conn)
2461f4280918SAndrei Emeltchenko 			continue;
2462f4280918SAndrei Emeltchenko 
24631da177e4SLinus Torvalds 		conn->sent -= count;
24641da177e4SLinus Torvalds 
2465f4280918SAndrei Emeltchenko 		switch (conn->type) {
2466f4280918SAndrei Emeltchenko 		case ACL_LINK:
246770f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
246870f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24691da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2470f4280918SAndrei Emeltchenko 			break;
2471f4280918SAndrei Emeltchenko 
2472f4280918SAndrei Emeltchenko 		case LE_LINK:
24736ed58ec5SVille Tervo 			if (hdev->le_pkts) {
24746ed58ec5SVille Tervo 				hdev->le_cnt += count;
24756ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
24766ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
24776ed58ec5SVille Tervo 			} else {
24786ed58ec5SVille Tervo 				hdev->acl_cnt += count;
24796ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
24806ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
24816ed58ec5SVille Tervo 			}
2482f4280918SAndrei Emeltchenko 			break;
2483f4280918SAndrei Emeltchenko 
2484f4280918SAndrei Emeltchenko 		case SCO_LINK:
248570f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
248670f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
24875b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2488f4280918SAndrei Emeltchenko 			break;
2489f4280918SAndrei Emeltchenko 
2490f4280918SAndrei Emeltchenko 		default:
2491f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2492f4280918SAndrei Emeltchenko 			break;
24931da177e4SLinus Torvalds 		}
24941da177e4SLinus Torvalds 	}
2495a9de9248SMarcel Holtmann 
24963eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
24971da177e4SLinus Torvalds }
24981da177e4SLinus Torvalds 
249925e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
250025e89e99SAndrei Emeltchenko 							struct sk_buff *skb)
250125e89e99SAndrei Emeltchenko {
250225e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
250325e89e99SAndrei Emeltchenko 	int i;
250425e89e99SAndrei Emeltchenko 
250525e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
250625e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
250725e89e99SAndrei Emeltchenko 		return;
250825e89e99SAndrei Emeltchenko 	}
250925e89e99SAndrei Emeltchenko 
251025e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
251125e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
251225e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
251325e89e99SAndrei Emeltchenko 		return;
251425e89e99SAndrei Emeltchenko 	}
251525e89e99SAndrei Emeltchenko 
251625e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
251725e89e99SAndrei Emeltchenko 								ev->num_hndl);
251825e89e99SAndrei Emeltchenko 
251925e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
252025e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
252125e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
252225e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
252325e89e99SAndrei Emeltchenko 
252425e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
252525e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
252625e89e99SAndrei Emeltchenko 
252725e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
252825e89e99SAndrei Emeltchenko 		if (!conn)
252925e89e99SAndrei Emeltchenko 			continue;
253025e89e99SAndrei Emeltchenko 
253125e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
253225e89e99SAndrei Emeltchenko 
253325e89e99SAndrei Emeltchenko 		switch (conn->type) {
253425e89e99SAndrei Emeltchenko 		case ACL_LINK:
253525e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
253625e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
253725e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
253825e89e99SAndrei Emeltchenko 			break;
253925e89e99SAndrei Emeltchenko 
254025e89e99SAndrei Emeltchenko 		default:
254125e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
254225e89e99SAndrei Emeltchenko 			break;
254325e89e99SAndrei Emeltchenko 		}
254425e89e99SAndrei Emeltchenko 	}
254525e89e99SAndrei Emeltchenko 
254625e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
254725e89e99SAndrei Emeltchenko }
254825e89e99SAndrei Emeltchenko 
254904837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25501da177e4SLinus Torvalds {
2551a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
255204837f64SMarcel Holtmann 	struct hci_conn *conn;
25531da177e4SLinus Torvalds 
25541da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
25551da177e4SLinus Torvalds 
25561da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25571da177e4SLinus Torvalds 
255804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
255904837f64SMarcel Holtmann 	if (conn) {
256004837f64SMarcel Holtmann 		conn->mode = ev->mode;
256104837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
256204837f64SMarcel Holtmann 
256351a8efd7SJohan Hedberg 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
256404837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
256558a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
256604837f64SMarcel Holtmann 			else
256758a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
256804837f64SMarcel Holtmann 		}
2569e73439d8SMarcel Holtmann 
257051a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2571e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
257204837f64SMarcel Holtmann 	}
257304837f64SMarcel Holtmann 
257404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
257504837f64SMarcel Holtmann }
257604837f64SMarcel Holtmann 
25771da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25781da177e4SLinus Torvalds {
2579052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2580052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2581052b30b0SMarcel Holtmann 
2582a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2583052b30b0SMarcel Holtmann 
2584052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2585052b30b0SMarcel Holtmann 
2586052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2587b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2588b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2589b6f98044SWaldemar Rymarkiewicz 
2590b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2591052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2592052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2593052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2594052b30b0SMarcel Holtmann 	}
2595052b30b0SMarcel Holtmann 
2596a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
259703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
259803b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2599a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2600a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2601a770bb5aSWaldemar Rymarkiewicz 
2602a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2603a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2604a770bb5aSWaldemar Rymarkiewicz 		else
2605a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2606a770bb5aSWaldemar Rymarkiewicz 
2607744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2608a770bb5aSWaldemar Rymarkiewicz 	}
2609980e1a53SJohan Hedberg 
2610b6f98044SWaldemar Rymarkiewicz unlock:
2611052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26121da177e4SLinus Torvalds }
26131da177e4SLinus Torvalds 
26141da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26151da177e4SLinus Torvalds {
261655ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
261755ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
261855ed8ca1SJohan Hedberg 	struct hci_conn *conn;
261955ed8ca1SJohan Hedberg 	struct link_key *key;
262055ed8ca1SJohan Hedberg 
2621a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
262255ed8ca1SJohan Hedberg 
2623a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
262455ed8ca1SJohan Hedberg 		return;
262555ed8ca1SJohan Hedberg 
262655ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
262755ed8ca1SJohan Hedberg 
262855ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
262955ed8ca1SJohan Hedberg 	if (!key) {
263055ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
263155ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
263255ed8ca1SJohan Hedberg 		goto not_found;
263355ed8ca1SJohan Hedberg 	}
263455ed8ca1SJohan Hedberg 
263555ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
263655ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
263755ed8ca1SJohan Hedberg 
2638a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2639b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
264055ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
264155ed8ca1SJohan Hedberg 		goto not_found;
264255ed8ca1SJohan Hedberg 	}
264355ed8ca1SJohan Hedberg 
264455ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
264560b83f57SWaldemar Rymarkiewicz 	if (conn) {
264660b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
264760b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
264860b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
264955ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
265055ed8ca1SJohan Hedberg 			goto not_found;
265155ed8ca1SJohan Hedberg 		}
265255ed8ca1SJohan Hedberg 
265360b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
265460b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
265560b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
265660b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
265760b83f57SWaldemar Rymarkiewicz 			goto not_found;
265860b83f57SWaldemar Rymarkiewicz 		}
265960b83f57SWaldemar Rymarkiewicz 
266060b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
266160b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
266260b83f57SWaldemar Rymarkiewicz 	}
266360b83f57SWaldemar Rymarkiewicz 
266455ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
266555ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
266655ed8ca1SJohan Hedberg 
266755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
266855ed8ca1SJohan Hedberg 
266955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
267055ed8ca1SJohan Hedberg 
267155ed8ca1SJohan Hedberg 	return;
267255ed8ca1SJohan Hedberg 
267355ed8ca1SJohan Hedberg not_found:
267455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
267555ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
26761da177e4SLinus Torvalds }
26771da177e4SLinus Torvalds 
26781da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
26791da177e4SLinus Torvalds {
2680052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2681052b30b0SMarcel Holtmann 	struct hci_conn *conn;
268255ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2683052b30b0SMarcel Holtmann 
2684a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2685052b30b0SMarcel Holtmann 
2686052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2687052b30b0SMarcel Holtmann 
2688052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2689052b30b0SMarcel Holtmann 	if (conn) {
2690052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2691052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2692980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
269313d39315SWaldemar Rymarkiewicz 
269413d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
269513d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
269613d39315SWaldemar Rymarkiewicz 
2697052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2698052b30b0SMarcel Holtmann 	}
2699052b30b0SMarcel Holtmann 
2700a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2701d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
270255ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
270355ed8ca1SJohan Hedberg 
2704052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27051da177e4SLinus Torvalds }
27061da177e4SLinus Torvalds 
270704837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
270804837f64SMarcel Holtmann {
2709a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
271004837f64SMarcel Holtmann 	struct hci_conn *conn;
271104837f64SMarcel Holtmann 
271204837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
271304837f64SMarcel Holtmann 
271404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
271504837f64SMarcel Holtmann 
271604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27171da177e4SLinus Torvalds 	if (conn && !ev->status) {
27181da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27191da177e4SLinus Torvalds 
2720cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2721cc11b9c1SAndrei Emeltchenko 		if (ie) {
27221da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27231da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27241da177e4SLinus Torvalds 		}
27251da177e4SLinus Torvalds 	}
27261da177e4SLinus Torvalds 
27271da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27281da177e4SLinus Torvalds }
27291da177e4SLinus Torvalds 
2730a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2731a8746417SMarcel Holtmann {
2732a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2733a8746417SMarcel Holtmann 	struct hci_conn *conn;
2734a8746417SMarcel Holtmann 
2735a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2736a8746417SMarcel Holtmann 
2737a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2738a8746417SMarcel Holtmann 
2739a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2740a8746417SMarcel Holtmann 	if (conn && !ev->status)
2741a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2742a8746417SMarcel Holtmann 
2743a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2744a8746417SMarcel Holtmann }
2745a8746417SMarcel Holtmann 
274685a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
274785a1e930SMarcel Holtmann {
2748a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
274985a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
275085a1e930SMarcel Holtmann 
275185a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
275285a1e930SMarcel Holtmann 
275385a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
275485a1e930SMarcel Holtmann 
2755cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2756cc11b9c1SAndrei Emeltchenko 	if (ie) {
275785a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
275885a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
275985a1e930SMarcel Holtmann 	}
276085a1e930SMarcel Holtmann 
276185a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
276285a1e930SMarcel Holtmann }
276385a1e930SMarcel Holtmann 
2764a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2765a9de9248SMarcel Holtmann {
2766a9de9248SMarcel Holtmann 	struct inquiry_data data;
2767a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
27683175405bSJohan Hedberg 	bool name_known;
2769a9de9248SMarcel Holtmann 
2770a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2771a9de9248SMarcel Holtmann 
2772a9de9248SMarcel Holtmann 	if (!num_rsp)
2773a9de9248SMarcel Holtmann 		return;
2774a9de9248SMarcel Holtmann 
2775a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2776a9de9248SMarcel Holtmann 
2777a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2778138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2779138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2780a9de9248SMarcel Holtmann 
2781e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2782a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2783a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2784a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2785a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2786a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2787a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2788a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
278941a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27903175405bSJohan Hedberg 
27913175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
27923175405bSJohan Hedberg 								false);
279348264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2794e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
27957d262f86SAndre Guedes 						!name_known, NULL, 0);
2796a9de9248SMarcel Holtmann 		}
2797a9de9248SMarcel Holtmann 	} else {
2798a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2799a9de9248SMarcel Holtmann 
2800e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2801a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2802a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2803a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2804a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2805a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2806a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2807a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
280841a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28093175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
28103175405bSJohan Hedberg 								false);
281148264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2812e17acd40SJohan Hedberg 						info->dev_class, info->rssi,
28137d262f86SAndre Guedes 						!name_known, NULL, 0);
2814a9de9248SMarcel Holtmann 		}
2815a9de9248SMarcel Holtmann 	}
2816a9de9248SMarcel Holtmann 
2817a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2818a9de9248SMarcel Holtmann }
2819a9de9248SMarcel Holtmann 
2820a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2821a9de9248SMarcel Holtmann {
282241a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
282341a96212SMarcel Holtmann 	struct hci_conn *conn;
282441a96212SMarcel Holtmann 
2825a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
282641a96212SMarcel Holtmann 
282741a96212SMarcel Holtmann 	hci_dev_lock(hdev);
282841a96212SMarcel Holtmann 
282941a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2830ccd556feSJohan Hedberg 	if (!conn)
2831ccd556feSJohan Hedberg 		goto unlock;
2832ccd556feSJohan Hedberg 
2833769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
283441a96212SMarcel Holtmann 		struct inquiry_entry *ie;
283541a96212SMarcel Holtmann 
2836cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2837cc11b9c1SAndrei Emeltchenko 		if (ie)
283841a96212SMarcel Holtmann 			ie->data.ssp_mode = (ev->features[0] & 0x01);
283941a96212SMarcel Holtmann 
284058a681efSJohan Hedberg 		if (ev->features[0] & 0x01)
284158a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
284241a96212SMarcel Holtmann 	}
284341a96212SMarcel Holtmann 
2844ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2845ccd556feSJohan Hedberg 		goto unlock;
2846ccd556feSJohan Hedberg 
2847127178d2SJohan Hedberg 	if (!ev->status) {
2848127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2849127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2850127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2851127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2852127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2853b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2854b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
2855b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0,
2856b644ba33SJohan Hedberg 						conn->dev_class);
2857392599b9SJohan Hedberg 
2858127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2859769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2860769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2861769be974SMarcel Holtmann 		hci_conn_put(conn);
2862769be974SMarcel Holtmann 	}
2863769be974SMarcel Holtmann 
2864ccd556feSJohan Hedberg unlock:
286541a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2866a9de9248SMarcel Holtmann }
2867a9de9248SMarcel Holtmann 
2868a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2869a9de9248SMarcel Holtmann {
2870b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2871b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2872b6a0dc82SMarcel Holtmann 
2873b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2874b6a0dc82SMarcel Holtmann 
2875b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2876b6a0dc82SMarcel Holtmann 
2877b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
28789dc0a3afSMarcel Holtmann 	if (!conn) {
28799dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
28809dc0a3afSMarcel Holtmann 			goto unlock;
28819dc0a3afSMarcel Holtmann 
28829dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2883b6a0dc82SMarcel Holtmann 		if (!conn)
2884b6a0dc82SMarcel Holtmann 			goto unlock;
2885b6a0dc82SMarcel Holtmann 
28869dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
28879dc0a3afSMarcel Holtmann 	}
28889dc0a3afSMarcel Holtmann 
2889732547f9SMarcel Holtmann 	switch (ev->status) {
2890732547f9SMarcel Holtmann 	case 0x00:
2891732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2892732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2893732547f9SMarcel Holtmann 
28949eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2895732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2896732547f9SMarcel Holtmann 		break;
2897732547f9SMarcel Holtmann 
2898705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2899732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29001038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2901732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2902732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2903efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2904efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2905efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2906efc7688bSMarcel Holtmann 			goto unlock;
2907efc7688bSMarcel Holtmann 		}
2908732547f9SMarcel Holtmann 		/* fall through */
2909efc7688bSMarcel Holtmann 
2910732547f9SMarcel Holtmann 	default:
2911b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2912732547f9SMarcel Holtmann 		break;
2913732547f9SMarcel Holtmann 	}
2914b6a0dc82SMarcel Holtmann 
2915b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2916b6a0dc82SMarcel Holtmann 	if (ev->status)
2917b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2918b6a0dc82SMarcel Holtmann 
2919b6a0dc82SMarcel Holtmann unlock:
2920b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2921a9de9248SMarcel Holtmann }
2922a9de9248SMarcel Holtmann 
2923a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2924a9de9248SMarcel Holtmann {
2925a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2926a9de9248SMarcel Holtmann }
2927a9de9248SMarcel Holtmann 
292804837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
292904837f64SMarcel Holtmann {
2930a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
293104837f64SMarcel Holtmann 
293204837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
293304837f64SMarcel Holtmann }
293404837f64SMarcel Holtmann 
2935a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2936a9de9248SMarcel Holtmann {
2937a9de9248SMarcel Holtmann 	struct inquiry_data data;
2938a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2939a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2940a9de9248SMarcel Holtmann 
2941a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2942a9de9248SMarcel Holtmann 
2943a9de9248SMarcel Holtmann 	if (!num_rsp)
2944a9de9248SMarcel Holtmann 		return;
2945a9de9248SMarcel Holtmann 
2946a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2947a9de9248SMarcel Holtmann 
2948e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2949561aafbcSJohan Hedberg 		bool name_known;
2950561aafbcSJohan Hedberg 
2951a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2952a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2953a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2954a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2955a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2956a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2957a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
295841a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2959561aafbcSJohan Hedberg 
2960a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29614ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29624ddb1930SJohan Hedberg 							sizeof(info->data),
29634ddb1930SJohan Hedberg 							EIR_NAME_COMPLETE);
2964561aafbcSJohan Hedberg 		else
2965561aafbcSJohan Hedberg 			name_known = true;
2966561aafbcSJohan Hedberg 
29673175405bSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known);
296848264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2969561aafbcSJohan Hedberg 						info->dev_class, info->rssi,
29707d262f86SAndre Guedes 						!name_known, info->data,
29717d262f86SAndre Guedes 						sizeof(info->data));
2972a9de9248SMarcel Holtmann 	}
2973a9de9248SMarcel Holtmann 
2974a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2975a9de9248SMarcel Holtmann }
2976a9de9248SMarcel Holtmann 
297717fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
297817fa4b9dSJohan Hedberg {
297917fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
298017fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
298117fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
298217fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
298317fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
298417fa4b9dSJohan Hedberg 			return 0x02;
298517fa4b9dSJohan Hedberg 		else
298617fa4b9dSJohan Hedberg 			return 0x03;
298717fa4b9dSJohan Hedberg 	}
298817fa4b9dSJohan Hedberg 
298917fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
299017fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
299158797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
299217fa4b9dSJohan Hedberg 
299317fa4b9dSJohan Hedberg 	return conn->auth_type;
299417fa4b9dSJohan Hedberg }
299517fa4b9dSJohan Hedberg 
29960493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29970493684eSMarcel Holtmann {
29980493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
29990493684eSMarcel Holtmann 	struct hci_conn *conn;
30000493684eSMarcel Holtmann 
30010493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30020493684eSMarcel Holtmann 
30030493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30040493684eSMarcel Holtmann 
30050493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
300603b555e1SJohan Hedberg 	if (!conn)
300703b555e1SJohan Hedberg 		goto unlock;
300803b555e1SJohan Hedberg 
30090493684eSMarcel Holtmann 	hci_conn_hold(conn);
30100493684eSMarcel Holtmann 
3011a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
301203b555e1SJohan Hedberg 		goto unlock;
301303b555e1SJohan Hedberg 
3014a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
301503b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
301617fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
301717fa4b9dSJohan Hedberg 
301817fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30197a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
30207a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
30217a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
30227a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
30237cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
30247cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
302517fa4b9dSJohan Hedberg 
302658a681efSJohan Hedberg 		if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
3027ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
3028ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3029ce85ee13SSzymon Janc 		else
3030ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3031ce85ee13SSzymon Janc 
303217fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
303317fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
303403b555e1SJohan Hedberg 	} else {
303503b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
303603b555e1SJohan Hedberg 
303703b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30389f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
303903b555e1SJohan Hedberg 
304003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
304103b555e1SJohan Hedberg 							sizeof(cp), &cp);
304203b555e1SJohan Hedberg 	}
304303b555e1SJohan Hedberg 
304403b555e1SJohan Hedberg unlock:
304503b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
304603b555e1SJohan Hedberg }
304703b555e1SJohan Hedberg 
304803b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
304903b555e1SJohan Hedberg {
305003b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
305103b555e1SJohan Hedberg 	struct hci_conn *conn;
305203b555e1SJohan Hedberg 
305303b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
305403b555e1SJohan Hedberg 
305503b555e1SJohan Hedberg 	hci_dev_lock(hdev);
305603b555e1SJohan Hedberg 
305703b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
305803b555e1SJohan Hedberg 	if (!conn)
305903b555e1SJohan Hedberg 		goto unlock;
306003b555e1SJohan Hedberg 
306103b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
306203b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
306358a681efSJohan Hedberg 	if (ev->oob_data)
306458a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
306503b555e1SJohan Hedberg 
306603b555e1SJohan Hedberg unlock:
30670493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
30680493684eSMarcel Holtmann }
30690493684eSMarcel Holtmann 
3070a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3071a5c29683SJohan Hedberg 							struct sk_buff *skb)
3072a5c29683SJohan Hedberg {
3073a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
307455bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
30757a828908SJohan Hedberg 	struct hci_conn *conn;
3076a5c29683SJohan Hedberg 
3077a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3078a5c29683SJohan Hedberg 
3079a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3080a5c29683SJohan Hedberg 
3081a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
30827a828908SJohan Hedberg 		goto unlock;
30837a828908SJohan Hedberg 
30847a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
30857a828908SJohan Hedberg 	if (!conn)
30867a828908SJohan Hedberg 		goto unlock;
30877a828908SJohan Hedberg 
30887a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
30897a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
30907a828908SJohan Hedberg 
30917a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
30927a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
30937a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
30947a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
30957a828908SJohan Hedberg 	 * bit set. */
30967a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
30977a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
30987a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
30997a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
31007a828908SJohan Hedberg 		goto unlock;
31017a828908SJohan Hedberg 	}
31027a828908SJohan Hedberg 
31037a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
31047a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
31057a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
310655bc1a37SJohan Hedberg 
310755bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
310855bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
310955bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
311051a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
311155bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
311255bc1a37SJohan Hedberg 			confirm_hint = 1;
311355bc1a37SJohan Hedberg 			goto confirm;
311455bc1a37SJohan Hedberg 		}
311555bc1a37SJohan Hedberg 
31169f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
31179f61656aSJohan Hedberg 						hdev->auto_accept_delay);
31189f61656aSJohan Hedberg 
31199f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
31209f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
31219f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
31229f61656aSJohan Hedberg 			goto unlock;
31239f61656aSJohan Hedberg 		}
31249f61656aSJohan Hedberg 
31257a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
31267a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
31277a828908SJohan Hedberg 		goto unlock;
31287a828908SJohan Hedberg 	}
31297a828908SJohan Hedberg 
313055bc1a37SJohan Hedberg confirm:
3131272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
313255bc1a37SJohan Hedberg 								confirm_hint);
3133a5c29683SJohan Hedberg 
31347a828908SJohan Hedberg unlock:
3135a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3136a5c29683SJohan Hedberg }
3137a5c29683SJohan Hedberg 
31381143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
31391143d458SBrian Gix 							struct sk_buff *skb)
31401143d458SBrian Gix {
31411143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
31421143d458SBrian Gix 
31431143d458SBrian Gix 	BT_DBG("%s", hdev->name);
31441143d458SBrian Gix 
31451143d458SBrian Gix 	hci_dev_lock(hdev);
31461143d458SBrian Gix 
3147a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3148272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
31491143d458SBrian Gix 
31501143d458SBrian Gix 	hci_dev_unlock(hdev);
31511143d458SBrian Gix }
31521143d458SBrian Gix 
31530493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
31540493684eSMarcel Holtmann {
31550493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
31560493684eSMarcel Holtmann 	struct hci_conn *conn;
31570493684eSMarcel Holtmann 
31580493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31590493684eSMarcel Holtmann 
31600493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31610493684eSMarcel Holtmann 
31620493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31632a611692SJohan Hedberg 	if (!conn)
31642a611692SJohan Hedberg 		goto unlock;
31652a611692SJohan Hedberg 
31662a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
31672a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
31682a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
31692a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
31702a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
317151a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3172bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3173bab73cb6SJohan Hedberg 								ev->status);
31742a611692SJohan Hedberg 
31750493684eSMarcel Holtmann 	hci_conn_put(conn);
31760493684eSMarcel Holtmann 
31772a611692SJohan Hedberg unlock:
31780493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31790493684eSMarcel Holtmann }
31800493684eSMarcel Holtmann 
318141a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
318241a96212SMarcel Holtmann {
318341a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
318441a96212SMarcel Holtmann 	struct inquiry_entry *ie;
318541a96212SMarcel Holtmann 
318641a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
318741a96212SMarcel Holtmann 
318841a96212SMarcel Holtmann 	hci_dev_lock(hdev);
318941a96212SMarcel Holtmann 
3190cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3191cc11b9c1SAndrei Emeltchenko 	if (ie)
319241a96212SMarcel Holtmann 		ie->data.ssp_mode = (ev->features[0] & 0x01);
319341a96212SMarcel Holtmann 
319441a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
319541a96212SMarcel Holtmann }
319641a96212SMarcel Holtmann 
31972763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
31982763eda6SSzymon Janc 							struct sk_buff *skb)
31992763eda6SSzymon Janc {
32002763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
32012763eda6SSzymon Janc 	struct oob_data *data;
32022763eda6SSzymon Janc 
32032763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
32042763eda6SSzymon Janc 
32052763eda6SSzymon Janc 	hci_dev_lock(hdev);
32062763eda6SSzymon Janc 
3207a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3208e1ba1f15SSzymon Janc 		goto unlock;
3209e1ba1f15SSzymon Janc 
32102763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
32112763eda6SSzymon Janc 	if (data) {
32122763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
32132763eda6SSzymon Janc 
32142763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32152763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
32162763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
32172763eda6SSzymon Janc 
32182763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
32192763eda6SSzymon Janc 									&cp);
32202763eda6SSzymon Janc 	} else {
32212763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
32222763eda6SSzymon Janc 
32232763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32242763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
32252763eda6SSzymon Janc 									&cp);
32262763eda6SSzymon Janc 	}
32272763eda6SSzymon Janc 
3228e1ba1f15SSzymon Janc unlock:
32292763eda6SSzymon Janc 	hci_dev_unlock(hdev);
32302763eda6SSzymon Janc }
32312763eda6SSzymon Janc 
3232fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3233fcd89c09SVille Tervo {
3234fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3235fcd89c09SVille Tervo 	struct hci_conn *conn;
3236fcd89c09SVille Tervo 
3237fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3238fcd89c09SVille Tervo 
3239fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3240fcd89c09SVille Tervo 
3241fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3242b62f328bSVille Tervo 	if (!conn) {
3243b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3244b62f328bSVille Tervo 		if (!conn) {
3245b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3246b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3247b62f328bSVille Tervo 			return;
3248b62f328bSVille Tervo 		}
324929b7988aSAndre Guedes 
325029b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3251b62f328bSVille Tervo 	}
3252fcd89c09SVille Tervo 
3253fcd89c09SVille Tervo 	if (ev->status) {
325448264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
325548264f06SJohan Hedberg 						conn->dst_type, ev->status);
3256fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3257fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3258fcd89c09SVille Tervo 		hci_conn_del(conn);
3259fcd89c09SVille Tervo 		goto unlock;
3260fcd89c09SVille Tervo 	}
3261fcd89c09SVille Tervo 
3262b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3263b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
3264b644ba33SJohan Hedberg 						conn->dst_type, NULL, 0, 0);
326583bc71b4SVinicius Costa Gomes 
32667b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3267fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3268fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3269fcd89c09SVille Tervo 
3270fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3271fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3272fcd89c09SVille Tervo 
3273fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3274fcd89c09SVille Tervo 
3275fcd89c09SVille Tervo unlock:
3276fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3277fcd89c09SVille Tervo }
3278fcd89c09SVille Tervo 
32799aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
32809aa04c91SAndre Guedes 						struct sk_buff *skb)
32819aa04c91SAndre Guedes {
3282e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3283e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
32843c9e9195SAndre Guedes 	s8 rssi;
32859aa04c91SAndre Guedes 
32869aa04c91SAndre Guedes 	hci_dev_lock(hdev);
32879aa04c91SAndre Guedes 
3288e95beb41SAndre Guedes 	while (num_reports--) {
3289e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3290e95beb41SAndre Guedes 
32919aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
32929aa04c91SAndre Guedes 
32933c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
32943c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
32953c9e9195SAndre Guedes 					NULL, rssi, 0, ev->data, ev->length);
32963c9e9195SAndre Guedes 
3297e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
32989aa04c91SAndre Guedes 	}
32999aa04c91SAndre Guedes 
33009aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
33019aa04c91SAndre Guedes }
33029aa04c91SAndre Guedes 
3303a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3304a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3305a7a595f6SVinicius Costa Gomes {
3306a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3307a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3308bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3309a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3310c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3311a7a595f6SVinicius Costa Gomes 
3312a7a595f6SVinicius Costa Gomes 	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
3313a7a595f6SVinicius Costa Gomes 
3314a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3315a7a595f6SVinicius Costa Gomes 
3316a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3317bea710feSVinicius Costa Gomes 	if (conn == NULL)
3318bea710feSVinicius Costa Gomes 		goto not_found;
3319a7a595f6SVinicius Costa Gomes 
3320bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3321bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3322bea710feSVinicius Costa Gomes 		goto not_found;
3323bea710feSVinicius Costa Gomes 
3324bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3325a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3326c9839a11SVinicius Costa Gomes 
3327c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3328c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3329a7a595f6SVinicius Costa Gomes 
3330a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3331a7a595f6SVinicius Costa Gomes 
3332c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3333c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3334c9839a11SVinicius Costa Gomes 		kfree(ltk);
3335c9839a11SVinicius Costa Gomes 	}
3336c9839a11SVinicius Costa Gomes 
3337a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3338bea710feSVinicius Costa Gomes 
3339bea710feSVinicius Costa Gomes 	return;
3340bea710feSVinicius Costa Gomes 
3341bea710feSVinicius Costa Gomes not_found:
3342bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3343bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3344bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3345a7a595f6SVinicius Costa Gomes }
3346a7a595f6SVinicius Costa Gomes 
3347fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3348fcd89c09SVille Tervo {
3349fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3350fcd89c09SVille Tervo 
3351fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3352fcd89c09SVille Tervo 
3353fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3354fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3355fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3356fcd89c09SVille Tervo 		break;
3357fcd89c09SVille Tervo 
33589aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
33599aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
33609aa04c91SAndre Guedes 		break;
33619aa04c91SAndre Guedes 
3362a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3363a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3364a7a595f6SVinicius Costa Gomes 		break;
3365a7a595f6SVinicius Costa Gomes 
3366fcd89c09SVille Tervo 	default:
3367fcd89c09SVille Tervo 		break;
3368fcd89c09SVille Tervo 	}
3369fcd89c09SVille Tervo }
3370fcd89c09SVille Tervo 
33711da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
33721da177e4SLinus Torvalds {
3373a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3374a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
33751da177e4SLinus Torvalds 
33761da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
33771da177e4SLinus Torvalds 
3378a9de9248SMarcel Holtmann 	switch (event) {
33791da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
33801da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
33811da177e4SLinus Torvalds 		break;
33821da177e4SLinus Torvalds 
33831da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
33841da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
33851da177e4SLinus Torvalds 		break;
33861da177e4SLinus Torvalds 
3387a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3388a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
338921d9e30eSMarcel Holtmann 		break;
339021d9e30eSMarcel Holtmann 
33911da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
33921da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
33931da177e4SLinus Torvalds 		break;
33941da177e4SLinus Torvalds 
33951da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
33961da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
33971da177e4SLinus Torvalds 		break;
33981da177e4SLinus Torvalds 
33991da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
34001da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
34011da177e4SLinus Torvalds 		break;
34021da177e4SLinus Torvalds 
3403a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3404a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3405a9de9248SMarcel Holtmann 		break;
3406a9de9248SMarcel Holtmann 
34071da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
34081da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
34091da177e4SLinus Torvalds 		break;
34101da177e4SLinus Torvalds 
3411a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3412a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3413a9de9248SMarcel Holtmann 		break;
3414a9de9248SMarcel Holtmann 
3415a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3416a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3417a9de9248SMarcel Holtmann 		break;
3418a9de9248SMarcel Holtmann 
3419a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3420a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3421a9de9248SMarcel Holtmann 		break;
3422a9de9248SMarcel Holtmann 
3423a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3424a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3425a9de9248SMarcel Holtmann 		break;
3426a9de9248SMarcel Holtmann 
3427a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3428a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3429a9de9248SMarcel Holtmann 		break;
3430a9de9248SMarcel Holtmann 
3431a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3432a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3433a9de9248SMarcel Holtmann 		break;
3434a9de9248SMarcel Holtmann 
3435a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3436a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3437a9de9248SMarcel Holtmann 		break;
3438a9de9248SMarcel Holtmann 
3439a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3440a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3441a9de9248SMarcel Holtmann 		break;
3442a9de9248SMarcel Holtmann 
3443a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3444a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
34451da177e4SLinus Torvalds 		break;
34461da177e4SLinus Torvalds 
34471da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
34481da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
34491da177e4SLinus Torvalds 		break;
34501da177e4SLinus Torvalds 
34511da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
34521da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
34531da177e4SLinus Torvalds 		break;
34541da177e4SLinus Torvalds 
34551da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
34561da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
34571da177e4SLinus Torvalds 		break;
34581da177e4SLinus Torvalds 
34591da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
34601da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
34611da177e4SLinus Torvalds 		break;
34621da177e4SLinus Torvalds 
3463a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3464a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3465a8746417SMarcel Holtmann 		break;
3466a8746417SMarcel Holtmann 
346785a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
346885a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
346985a1e930SMarcel Holtmann 		break;
347085a1e930SMarcel Holtmann 
3471a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3472a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3473a9de9248SMarcel Holtmann 		break;
3474a9de9248SMarcel Holtmann 
3475a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3476a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3477a9de9248SMarcel Holtmann 		break;
3478a9de9248SMarcel Holtmann 
3479a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3480a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3481a9de9248SMarcel Holtmann 		break;
3482a9de9248SMarcel Holtmann 
3483a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3484a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3485a9de9248SMarcel Holtmann 		break;
3486a9de9248SMarcel Holtmann 
348704837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
348804837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
348904837f64SMarcel Holtmann 		break;
349004837f64SMarcel Holtmann 
3491a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3492a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
34931da177e4SLinus Torvalds 		break;
34941da177e4SLinus Torvalds 
34950493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
34960493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
34970493684eSMarcel Holtmann 		break;
34980493684eSMarcel Holtmann 
349903b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
350003b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
350103b555e1SJohan Hedberg 		break;
350203b555e1SJohan Hedberg 
3503a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3504a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3505a5c29683SJohan Hedberg 		break;
3506a5c29683SJohan Hedberg 
35071143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
35081143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
35091143d458SBrian Gix 		break;
35101143d458SBrian Gix 
35110493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
35120493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
35130493684eSMarcel Holtmann 		break;
35140493684eSMarcel Holtmann 
351541a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
351641a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
351741a96212SMarcel Holtmann 		break;
351841a96212SMarcel Holtmann 
3519fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3520fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3521fcd89c09SVille Tervo 		break;
3522fcd89c09SVille Tervo 
35232763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
35242763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
35252763eda6SSzymon Janc 		break;
35262763eda6SSzymon Janc 
352725e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
352825e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
352925e89e99SAndrei Emeltchenko 		break;
353025e89e99SAndrei Emeltchenko 
35311da177e4SLinus Torvalds 	default:
3532a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
35331da177e4SLinus Torvalds 		break;
35341da177e4SLinus Torvalds 	}
35351da177e4SLinus Torvalds 
35361da177e4SLinus Torvalds 	kfree_skb(skb);
35371da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
35381da177e4SLinus Torvalds }
3539