xref: /openbmc/linux/net/bluetooth/hci_event.c (revision bc3dd33c)
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 
4070f23020SAndrei Emeltchenko #include <linux/uaccess.h>
411da177e4SLinus Torvalds #include <asm/unaligned.h>
421da177e4SLinus Torvalds 
431da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
441da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds /* Handle HCI Event packets */
471da177e4SLinus Torvalds 
48a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
491da177e4SLinus Torvalds {
50a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
511da177e4SLinus Torvalds 
52a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
531da177e4SLinus Torvalds 
54e6d465cbSAndre Guedes 	if (status) {
55e6d465cbSAndre Guedes 		hci_dev_lock(hdev);
56e6d465cbSAndre Guedes 		mgmt_stop_discovery_failed(hdev, status);
57e6d465cbSAndre Guedes 		hci_dev_unlock(hdev);
58a9de9248SMarcel Holtmann 		return;
59e6d465cbSAndre Guedes 	}
601da177e4SLinus Torvalds 
6189352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
6289352e7dSAndre Guedes 
6356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
64ff9ef578SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
6556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
66a9de9248SMarcel Holtmann 
6723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
68a9de9248SMarcel Holtmann 
69a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
701da177e4SLinus Torvalds }
716bd57416SMarcel Holtmann 
72a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
731da177e4SLinus Torvalds {
74a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
75a9de9248SMarcel Holtmann 
76a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
77a9de9248SMarcel Holtmann 
78a9de9248SMarcel Holtmann 	if (status)
79a9de9248SMarcel Holtmann 		return;
80a9de9248SMarcel Holtmann 
81a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
82a9de9248SMarcel Holtmann }
83a9de9248SMarcel Holtmann 
84a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
85a9de9248SMarcel Holtmann {
86a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
87a9de9248SMarcel Holtmann }
88a9de9248SMarcel Holtmann 
89a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
90a9de9248SMarcel Holtmann {
91a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
921da177e4SLinus Torvalds 	struct hci_conn *conn;
931da177e4SLinus Torvalds 
94a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
951da177e4SLinus Torvalds 
96a9de9248SMarcel Holtmann 	if (rp->status)
97a9de9248SMarcel Holtmann 		return;
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1001da177e4SLinus Torvalds 
101a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1021da177e4SLinus Torvalds 	if (conn) {
103a9de9248SMarcel Holtmann 		if (rp->role)
1041da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1051da177e4SLinus Torvalds 		else
1061da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1071da177e4SLinus Torvalds 	}
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
110a9de9248SMarcel Holtmann }
1111da177e4SLinus Torvalds 
112e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
113e4e8e37cSMarcel Holtmann {
114e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
115e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
116e4e8e37cSMarcel Holtmann 
117e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
118e4e8e37cSMarcel Holtmann 
119e4e8e37cSMarcel Holtmann 	if (rp->status)
120e4e8e37cSMarcel Holtmann 		return;
121e4e8e37cSMarcel Holtmann 
122e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
123e4e8e37cSMarcel Holtmann 
124e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
125e4e8e37cSMarcel Holtmann 	if (conn)
126e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
127e4e8e37cSMarcel Holtmann 
128e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
129e4e8e37cSMarcel Holtmann }
130e4e8e37cSMarcel Holtmann 
131a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
132a9de9248SMarcel Holtmann {
133a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
134a9de9248SMarcel Holtmann 	struct hci_conn *conn;
135a9de9248SMarcel Holtmann 	void *sent;
136a9de9248SMarcel Holtmann 
137a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
138a9de9248SMarcel Holtmann 
139a9de9248SMarcel Holtmann 	if (rp->status)
140a9de9248SMarcel Holtmann 		return;
141a9de9248SMarcel Holtmann 
142a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14304837f64SMarcel Holtmann 	if (!sent)
144a9de9248SMarcel Holtmann 		return;
14504837f64SMarcel Holtmann 
14604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14704837f64SMarcel Holtmann 
148a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
149e4e8e37cSMarcel Holtmann 	if (conn)
15083985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15104837f64SMarcel Holtmann 
15204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1531da177e4SLinus Torvalds }
1541da177e4SLinus Torvalds 
155e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
156e4e8e37cSMarcel Holtmann {
157e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
158e4e8e37cSMarcel Holtmann 
159e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
160e4e8e37cSMarcel Holtmann 
161e4e8e37cSMarcel Holtmann 	if (rp->status)
162e4e8e37cSMarcel Holtmann 		return;
163e4e8e37cSMarcel Holtmann 
164e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
165e4e8e37cSMarcel Holtmann }
166e4e8e37cSMarcel Holtmann 
167e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
168e4e8e37cSMarcel Holtmann {
169e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
170e4e8e37cSMarcel Holtmann 	void *sent;
171e4e8e37cSMarcel Holtmann 
172e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
173e4e8e37cSMarcel Holtmann 
174e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
175e4e8e37cSMarcel Holtmann 	if (!sent)
176e4e8e37cSMarcel Holtmann 		return;
177e4e8e37cSMarcel Holtmann 
178e4e8e37cSMarcel Holtmann 	if (!status)
179e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
180e4e8e37cSMarcel Holtmann 
18123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
182e4e8e37cSMarcel Holtmann }
183e4e8e37cSMarcel Holtmann 
184a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1851da177e4SLinus Torvalds {
186a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
187a9de9248SMarcel Holtmann 
188a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
189a9de9248SMarcel Holtmann 
19010572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19110572132SGustavo F. Padovan 
19223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
193d23264a8SAndre Guedes 
194a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
1959f8ce967SJohan Hedberg 	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS));
19669775ff6SAndre Guedes 
19769775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
198a9de9248SMarcel Holtmann }
199a9de9248SMarcel Holtmann 
200a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
201a9de9248SMarcel Holtmann {
202a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2031da177e4SLinus Torvalds 	void *sent;
2041da177e4SLinus Torvalds 
205a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2061da177e4SLinus Torvalds 
207a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2081da177e4SLinus Torvalds 	if (!sent)
209a9de9248SMarcel Holtmann 		return;
2101da177e4SLinus Torvalds 
21156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21256e5cb86SJohan Hedberg 
213f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
214f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
21528cc7bdeSJohan Hedberg 	else if (!status)
21628cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
217f51d5b24SJohan Hedberg 
21856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
2193159d384SJohan Hedberg 
2203159d384SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
221a9de9248SMarcel Holtmann }
222a9de9248SMarcel Holtmann 
223a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
224a9de9248SMarcel Holtmann {
225a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
226a9de9248SMarcel Holtmann 
227a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
228a9de9248SMarcel Holtmann 
229a9de9248SMarcel Holtmann 	if (rp->status)
230a9de9248SMarcel Holtmann 		return;
231a9de9248SMarcel Holtmann 
232db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2331f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
234a9de9248SMarcel Holtmann }
235a9de9248SMarcel Holtmann 
236a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
237a9de9248SMarcel Holtmann {
238a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
239a9de9248SMarcel Holtmann 	void *sent;
240a9de9248SMarcel Holtmann 
241a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
242a9de9248SMarcel Holtmann 
243a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
244a9de9248SMarcel Holtmann 	if (!sent)
245a9de9248SMarcel Holtmann 		return;
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds 	if (!status) {
248a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
249a9de9248SMarcel Holtmann 
2501da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2511da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2521da177e4SLinus Torvalds 		else
2531da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2541da177e4SLinus Torvalds 	}
255a9de9248SMarcel Holtmann 
25633ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
25733ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
25833ef95edSJohan Hedberg 
25923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
260a9de9248SMarcel Holtmann }
2611da177e4SLinus Torvalds 
262a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
263a9de9248SMarcel Holtmann {
264a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
265a9de9248SMarcel Holtmann 	void *sent;
266a9de9248SMarcel Holtmann 
267a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
268a9de9248SMarcel Holtmann 
269a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2701da177e4SLinus Torvalds 	if (!sent)
271a9de9248SMarcel Holtmann 		return;
2721da177e4SLinus Torvalds 
2731da177e4SLinus Torvalds 	if (!status) {
274a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
275a9de9248SMarcel Holtmann 
2761da177e4SLinus Torvalds 		if (param)
2771da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2781da177e4SLinus Torvalds 		else
2791da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2801da177e4SLinus Torvalds 	}
281a9de9248SMarcel Holtmann 
28223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2831da177e4SLinus Torvalds }
2841da177e4SLinus Torvalds 
285a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
286a9de9248SMarcel Holtmann {
28736f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28836f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
289a9de9248SMarcel Holtmann 	void *sent;
2901da177e4SLinus Torvalds 
291a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
292a9de9248SMarcel Holtmann 
293a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2941da177e4SLinus Torvalds 	if (!sent)
295a9de9248SMarcel Holtmann 		return;
2961da177e4SLinus Torvalds 
29736f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
298a9de9248SMarcel Holtmann 
29956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
30056e5cb86SJohan Hedberg 
3012d7cee58SJohan Hedberg 	if (status != 0) {
302744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3032d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3042d7cee58SJohan Hedberg 		goto done;
3052d7cee58SJohan Hedberg 	}
3062d7cee58SJohan Hedberg 
3079fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3089fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
309a9de9248SMarcel Holtmann 
31073f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3111da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3129fbcbb45SJohan Hedberg 		if (!old_iscan)
313744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31416ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
31516ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31616ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31716ab91abSJohan Hedberg 									to);
31816ab91abSJohan Hedberg 		}
3199fbcbb45SJohan Hedberg 	} else if (old_iscan)
320744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3211da177e4SLinus Torvalds 
3229fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3231da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3249fbcbb45SJohan Hedberg 		if (!old_pscan)
325744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3269fbcbb45SJohan Hedberg 	} else if (old_pscan)
327744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
328a9de9248SMarcel Holtmann 
32936f7fc7eSJohan Hedberg done:
33056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
33123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3321da177e4SLinus Torvalds }
3331da177e4SLinus Torvalds 
334a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
335a9de9248SMarcel Holtmann {
336a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
337a9de9248SMarcel Holtmann 
338a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
339a9de9248SMarcel Holtmann 
340a9de9248SMarcel Holtmann 	if (rp->status)
341a9de9248SMarcel Holtmann 		return;
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
344a9de9248SMarcel Holtmann 
345a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
346a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
347a9de9248SMarcel Holtmann }
348a9de9248SMarcel Holtmann 
349a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
350a9de9248SMarcel Holtmann {
351a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
352a9de9248SMarcel Holtmann 	void *sent;
353a9de9248SMarcel Holtmann 
354a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
355a9de9248SMarcel Holtmann 
356a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
357a9de9248SMarcel Holtmann 	if (!sent)
358a9de9248SMarcel Holtmann 		return;
359a9de9248SMarcel Holtmann 
3607f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3617f9a903cSMarcel Holtmann 
3627f9a903cSMarcel Holtmann 	if (status == 0)
363a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3647f9a903cSMarcel Holtmann 
3657f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3667f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3677f9a903cSMarcel Holtmann 
3687f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
369a9de9248SMarcel Holtmann }
370a9de9248SMarcel Holtmann 
371a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
372a9de9248SMarcel Holtmann {
373a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
374a9de9248SMarcel Holtmann 	__u16 setting;
375a9de9248SMarcel Holtmann 
376a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
377a9de9248SMarcel Holtmann 
378a9de9248SMarcel Holtmann 	if (rp->status)
379a9de9248SMarcel Holtmann 		return;
380a9de9248SMarcel Holtmann 
381a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
382a9de9248SMarcel Holtmann 
383a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
384a9de9248SMarcel Holtmann 		return;
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
387a9de9248SMarcel Holtmann 
388a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
389a9de9248SMarcel Holtmann 
3903c54711cSGustavo F. Padovan 	if (hdev->notify)
391a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
392a9de9248SMarcel Holtmann }
393a9de9248SMarcel Holtmann 
394a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
395a9de9248SMarcel Holtmann {
396a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
397f383f275SMarcel Holtmann 	__u16 setting;
398a9de9248SMarcel Holtmann 	void *sent;
399a9de9248SMarcel Holtmann 
400a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
401a9de9248SMarcel Holtmann 
402f383f275SMarcel Holtmann 	if (status)
403f383f275SMarcel Holtmann 		return;
404f383f275SMarcel Holtmann 
405a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
406a9de9248SMarcel Holtmann 	if (!sent)
407a9de9248SMarcel Holtmann 		return;
408a9de9248SMarcel Holtmann 
409f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4101da177e4SLinus Torvalds 
411f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
412f383f275SMarcel Holtmann 		return;
413f383f275SMarcel Holtmann 
4141da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4151da177e4SLinus Torvalds 
416a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4171da177e4SLinus Torvalds 
4183c54711cSGustavo F. Padovan 	if (hdev->notify)
4191da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4201da177e4SLinus Torvalds }
4211da177e4SLinus Torvalds 
422a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4231da177e4SLinus Torvalds {
424a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4251da177e4SLinus Torvalds 
426a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4271da177e4SLinus Torvalds 
42823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4291143e5a6SMarcel Holtmann }
4301143e5a6SMarcel Holtmann 
431333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
432333140b5SMarcel Holtmann {
433333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
434333140b5SMarcel Holtmann 	void *sent;
435333140b5SMarcel Holtmann 
436333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
437333140b5SMarcel Holtmann 
438333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
439333140b5SMarcel Holtmann 	if (!sent)
440333140b5SMarcel Holtmann 		return;
441333140b5SMarcel Holtmann 
442c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
443c0ecddc2SJohan Hedberg 		mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
444c0ecddc2SJohan Hedberg 	else if (!status) {
44584bde9d6SJohan Hedberg 		if (*((u8 *) sent))
44684bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
44784bde9d6SJohan Hedberg 		else
44884bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
449c0ecddc2SJohan Hedberg 	}
450333140b5SMarcel Holtmann }
451333140b5SMarcel Holtmann 
452d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
453d5859e22SJohan Hedberg {
454d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
455d5859e22SJohan Hedberg 		return 2;
456d5859e22SJohan Hedberg 
457d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
458d5859e22SJohan Hedberg 		return 1;
459d5859e22SJohan Hedberg 
460d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
461d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
462d5859e22SJohan Hedberg 		return 1;
463d5859e22SJohan Hedberg 
464d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
465d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
466d5859e22SJohan Hedberg 			return 1;
467d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
468d5859e22SJohan Hedberg 			return 1;
469d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
470d5859e22SJohan Hedberg 			return 1;
471d5859e22SJohan Hedberg 	}
472d5859e22SJohan Hedberg 
473d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
474d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
475d5859e22SJohan Hedberg 		return 1;
476d5859e22SJohan Hedberg 
477d5859e22SJohan Hedberg 	return 0;
478d5859e22SJohan Hedberg }
479d5859e22SJohan Hedberg 
480d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
481d5859e22SJohan Hedberg {
482d5859e22SJohan Hedberg 	u8 mode;
483d5859e22SJohan Hedberg 
484d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
485d5859e22SJohan Hedberg 
486d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
487d5859e22SJohan Hedberg }
488d5859e22SJohan Hedberg 
489d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
490d5859e22SJohan Hedberg {
491d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
492d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
493d5859e22SJohan Hedberg 	 * command otherwise */
494d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
495d5859e22SJohan Hedberg 
4966de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
4976de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
4985a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
4996de6c18dSVille Tervo 		return;
5006de6c18dSVille Tervo 
501d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
502d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
503d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
504d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
505d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
506d5859e22SJohan Hedberg 
507d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
508d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Inquiry Result with RSSI */
509d5859e22SJohan Hedberg 
510d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
511d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
512d5859e22SJohan Hedberg 
513d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
514d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
515d5859e22SJohan Hedberg 
516d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
517d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
518d5859e22SJohan Hedberg 
519d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
520d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
521d5859e22SJohan Hedberg 
522d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
523d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
524d5859e22SJohan Hedberg 
525d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
526d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
527d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
528d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
529d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
530d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
531d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
532d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
533d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
534d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
535d5859e22SJohan Hedberg 					 * Features Notification */
536d5859e22SJohan Hedberg 	}
537d5859e22SJohan Hedberg 
538d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
539d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
540d5859e22SJohan Hedberg 
541d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
542d5859e22SJohan Hedberg }
543d5859e22SJohan Hedberg 
544d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
545d5859e22SJohan Hedberg {
546e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
547e61ef499SAndrei Emeltchenko 		return;
548e61ef499SAndrei Emeltchenko 
549d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
550d5859e22SJohan Hedberg 
551d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
552d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
553d5859e22SJohan Hedberg 
55454d04dbbSJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
55554d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
556d5859e22SJohan Hedberg 			u8 mode = 0x01;
55754d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
55854d04dbbSJohan Hedberg 				     sizeof(mode), &mode);
55954d04dbbSJohan Hedberg 		} else {
56054d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
56154d04dbbSJohan Hedberg 
56254d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
56354d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
56454d04dbbSJohan Hedberg 
56554d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
56654d04dbbSJohan Hedberg 		}
567d5859e22SJohan Hedberg 	}
568d5859e22SJohan Hedberg 
569d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
570d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
571d5859e22SJohan Hedberg 
572d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
573d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
574971e3a4bSAndre Guedes 
575971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
576971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
577971e3a4bSAndre Guedes 
578971e3a4bSAndre Guedes 		cp.page = 0x01;
57904124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
58004124681SGustavo F. Padovan 			     &cp);
581971e3a4bSAndre Guedes 	}
582e6100a25SAndre Guedes 
58347990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
58447990ea0SJohan Hedberg 		u8 enable = 1;
58504124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
58604124681SGustavo F. Padovan 			     &enable);
58747990ea0SJohan Hedberg 	}
588d5859e22SJohan Hedberg }
589d5859e22SJohan Hedberg 
590a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
591a9de9248SMarcel Holtmann {
592a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5931143e5a6SMarcel Holtmann 
594a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
5951143e5a6SMarcel Holtmann 
596a9de9248SMarcel Holtmann 	if (rp->status)
59728b8df77SAndrei Emeltchenko 		goto done;
5981143e5a6SMarcel Holtmann 
599a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
600e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
601d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
602e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
603d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6041da177e4SLinus Torvalds 
605a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
606a9de9248SMarcel Holtmann 					hdev->manufacturer,
607a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
608d5859e22SJohan Hedberg 
609d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
610d5859e22SJohan Hedberg 		hci_setup(hdev);
61128b8df77SAndrei Emeltchenko 
61228b8df77SAndrei Emeltchenko done:
61328b8df77SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
614d5859e22SJohan Hedberg }
615d5859e22SJohan Hedberg 
616d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
617d5859e22SJohan Hedberg {
618d5859e22SJohan Hedberg 	u16 link_policy = 0;
619d5859e22SJohan Hedberg 
620d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
621d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
622d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
623d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
624d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
625d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
626d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
627d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
628d5859e22SJohan Hedberg 
629d5859e22SJohan Hedberg 	link_policy = cpu_to_le16(link_policy);
63004124681SGustavo F. Padovan 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(link_policy),
63104124681SGustavo F. Padovan 		     &link_policy);
6321da177e4SLinus Torvalds }
6331da177e4SLinus Torvalds 
634a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
635a9de9248SMarcel Holtmann {
636a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
637a9de9248SMarcel Holtmann 
638a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
639a9de9248SMarcel Holtmann 
640a9de9248SMarcel Holtmann 	if (rp->status)
641d5859e22SJohan Hedberg 		goto done;
642a9de9248SMarcel Holtmann 
643a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
644d5859e22SJohan Hedberg 
645d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
646d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
647d5859e22SJohan Hedberg 
648d5859e22SJohan Hedberg done:
649d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
650a9de9248SMarcel Holtmann }
651a9de9248SMarcel Holtmann 
652a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
653a9de9248SMarcel Holtmann {
654a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
655a9de9248SMarcel Holtmann 
656a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
657a9de9248SMarcel Holtmann 
658a9de9248SMarcel Holtmann 	if (rp->status)
659a9de9248SMarcel Holtmann 		return;
660a9de9248SMarcel Holtmann 
661a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds 	/* Adjust default settings according to features
6641da177e4SLinus Torvalds 	 * supported by device. */
665a9de9248SMarcel Holtmann 
6661da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6671da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6681da177e4SLinus Torvalds 
6691da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6701da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6711da177e4SLinus Torvalds 
6725b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6731da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6745b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6755b7f9909SMarcel Holtmann 	}
6761da177e4SLinus Torvalds 
6775b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6781da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6795b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6805b7f9909SMarcel Holtmann 	}
6815b7f9909SMarcel Holtmann 
6825b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6835b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6845b7f9909SMarcel Holtmann 
6855b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6865b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6875b7f9909SMarcel Holtmann 
6885b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6895b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6901da177e4SLinus Torvalds 
691efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
692efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
693efc7688bSMarcel Holtmann 
694efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
695efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
696efc7688bSMarcel Holtmann 
697efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
698efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
699efc7688bSMarcel Holtmann 
700a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
701a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
702a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
703a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
704a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7051da177e4SLinus Torvalds }
7061da177e4SLinus Torvalds 
7078f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev)
7088f984dfaSJohan Hedberg {
7098f984dfaSJohan Hedberg 	struct hci_cp_write_le_host_supported cp;
7108f984dfaSJohan Hedberg 
7118f984dfaSJohan Hedberg 	memset(&cp, 0, sizeof(cp));
7128f984dfaSJohan Hedberg 
7138f984dfaSJohan Hedberg 	if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
7148f984dfaSJohan Hedberg 		cp.le = 1;
7158f984dfaSJohan Hedberg 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
7168f984dfaSJohan Hedberg 	}
7178f984dfaSJohan Hedberg 
7188f984dfaSJohan Hedberg 	if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
71904124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
72004124681SGustavo F. Padovan 			     &cp);
7218f984dfaSJohan Hedberg }
7228f984dfaSJohan Hedberg 
723971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
724971e3a4bSAndre Guedes 							struct sk_buff *skb)
725971e3a4bSAndre Guedes {
726971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
727971e3a4bSAndre Guedes 
728971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
729971e3a4bSAndre Guedes 
730971e3a4bSAndre Guedes 	if (rp->status)
7318f984dfaSJohan Hedberg 		goto done;
732971e3a4bSAndre Guedes 
733b5b32b65SAndre Guedes 	switch (rp->page) {
734b5b32b65SAndre Guedes 	case 0:
735b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
736b5b32b65SAndre Guedes 		break;
737b5b32b65SAndre Guedes 	case 1:
73859e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
739b5b32b65SAndre Guedes 		break;
740b5b32b65SAndre Guedes 	}
741971e3a4bSAndre Guedes 
7428f984dfaSJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE)
7438f984dfaSJohan Hedberg 		hci_set_le_support(hdev);
7448f984dfaSJohan Hedberg 
7458f984dfaSJohan Hedberg done:
746971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
747971e3a4bSAndre Guedes }
748971e3a4bSAndre Guedes 
7491e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7501e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7511e89cffbSAndrei Emeltchenko {
7521e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7531e89cffbSAndrei Emeltchenko 
7541e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7551e89cffbSAndrei Emeltchenko 
7561e89cffbSAndrei Emeltchenko 	if (rp->status)
7571e89cffbSAndrei Emeltchenko 		return;
7581e89cffbSAndrei Emeltchenko 
7591e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7601e89cffbSAndrei Emeltchenko 
7611e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7621e89cffbSAndrei Emeltchenko }
7631e89cffbSAndrei Emeltchenko 
764a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
765a9de9248SMarcel Holtmann {
766a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
767a9de9248SMarcel Holtmann 
768a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
769a9de9248SMarcel Holtmann 
770a9de9248SMarcel Holtmann 	if (rp->status)
771a9de9248SMarcel Holtmann 		return;
772a9de9248SMarcel Holtmann 
773a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
774a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
775a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
776a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
777da1f5198SMarcel Holtmann 
778da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
779da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
780da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
781da1f5198SMarcel Holtmann 	}
782da1f5198SMarcel Holtmann 
783da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
784da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7851da177e4SLinus Torvalds 
786a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
787a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
788a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
7891da177e4SLinus Torvalds }
7901da177e4SLinus Torvalds 
791a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
792a9de9248SMarcel Holtmann {
793a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7941da177e4SLinus Torvalds 
795a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
796a9de9248SMarcel Holtmann 
797a9de9248SMarcel Holtmann 	if (!rp->status)
798a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
799a9de9248SMarcel Holtmann 
80023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
80123bb5763SJohan Hedberg }
80223bb5763SJohan Hedberg 
803350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
804350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
805350ee4cfSAndrei Emeltchenko {
806350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
807350ee4cfSAndrei Emeltchenko 
808350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
809350ee4cfSAndrei Emeltchenko 
810350ee4cfSAndrei Emeltchenko 	if (rp->status)
811350ee4cfSAndrei Emeltchenko 		return;
812350ee4cfSAndrei Emeltchenko 
813350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
814350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
815350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
816350ee4cfSAndrei Emeltchenko 
817350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
818350ee4cfSAndrei Emeltchenko 
819350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
820350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
821350ee4cfSAndrei Emeltchenko 
822350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
823350ee4cfSAndrei Emeltchenko }
824350ee4cfSAndrei Emeltchenko 
82523bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
82623bb5763SJohan Hedberg {
82723bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
82823bb5763SJohan Hedberg 
82923bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
83023bb5763SJohan Hedberg 
83123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8321da177e4SLinus Torvalds }
8331da177e4SLinus Torvalds 
834928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
835928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
836928abaa7SAndrei Emeltchenko {
837928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
838928abaa7SAndrei Emeltchenko 
839928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
840928abaa7SAndrei Emeltchenko 
841928abaa7SAndrei Emeltchenko 	if (rp->status)
842928abaa7SAndrei Emeltchenko 		return;
843928abaa7SAndrei Emeltchenko 
844928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
845928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
846928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
847928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
848928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
849928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
850928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
851928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
852928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
853928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
854928abaa7SAndrei Emeltchenko 
855928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
856928abaa7SAndrei Emeltchenko }
857928abaa7SAndrei Emeltchenko 
858b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
859b0916ea0SJohan Hedberg 							struct sk_buff *skb)
860b0916ea0SJohan Hedberg {
861b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
862b0916ea0SJohan Hedberg 
863b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
864b0916ea0SJohan Hedberg 
865b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
866b0916ea0SJohan Hedberg }
867b0916ea0SJohan Hedberg 
868d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
869d5859e22SJohan Hedberg {
870d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
871d5859e22SJohan Hedberg 
872d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
873d5859e22SJohan Hedberg 
874d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
875d5859e22SJohan Hedberg }
876d5859e22SJohan Hedberg 
877d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
878d5859e22SJohan Hedberg 							struct sk_buff *skb)
879d5859e22SJohan Hedberg {
880d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
881d5859e22SJohan Hedberg 
882d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
883d5859e22SJohan Hedberg 
884d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
885d5859e22SJohan Hedberg }
886d5859e22SJohan Hedberg 
887d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
888d5859e22SJohan Hedberg 							struct sk_buff *skb)
889d5859e22SJohan Hedberg {
890d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
891d5859e22SJohan Hedberg 
892d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
893d5859e22SJohan Hedberg 
894d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
895d5859e22SJohan Hedberg }
896d5859e22SJohan Hedberg 
897d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
898d5859e22SJohan Hedberg {
899d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
900d5859e22SJohan Hedberg 
901d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
902d5859e22SJohan Hedberg 
903d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
904d5859e22SJohan Hedberg }
905d5859e22SJohan Hedberg 
906980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
907980e1a53SJohan Hedberg {
908980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
909980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
910980e1a53SJohan Hedberg 	struct hci_conn *conn;
911980e1a53SJohan Hedberg 
912980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
913980e1a53SJohan Hedberg 
91456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
91556e5cb86SJohan Hedberg 
916a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
917744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
918980e1a53SJohan Hedberg 
919980e1a53SJohan Hedberg 	if (rp->status != 0)
92056e5cb86SJohan Hedberg 		goto unlock;
921980e1a53SJohan Hedberg 
922980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
923980e1a53SJohan Hedberg 	if (!cp)
92456e5cb86SJohan Hedberg 		goto unlock;
925980e1a53SJohan Hedberg 
926980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
927980e1a53SJohan Hedberg 	if (conn)
928980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
92956e5cb86SJohan Hedberg 
93056e5cb86SJohan Hedberg unlock:
93156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
932980e1a53SJohan Hedberg }
933980e1a53SJohan Hedberg 
934980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
935980e1a53SJohan Hedberg {
936980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
937980e1a53SJohan Hedberg 
938980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
939980e1a53SJohan Hedberg 
94056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
94156e5cb86SJohan Hedberg 
942a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
943744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
944980e1a53SJohan Hedberg 								rp->status);
94556e5cb86SJohan Hedberg 
94656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
947980e1a53SJohan Hedberg }
94856e5cb86SJohan Hedberg 
9496ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9506ed58ec5SVille Tervo 				       struct sk_buff *skb)
9516ed58ec5SVille Tervo {
9526ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9536ed58ec5SVille Tervo 
9546ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9556ed58ec5SVille Tervo 
9566ed58ec5SVille Tervo 	if (rp->status)
9576ed58ec5SVille Tervo 		return;
9586ed58ec5SVille Tervo 
9596ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9606ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9616ed58ec5SVille Tervo 
9626ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9636ed58ec5SVille Tervo 
9646ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9656ed58ec5SVille Tervo 
9666ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9676ed58ec5SVille Tervo }
968980e1a53SJohan Hedberg 
969a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
970a5c29683SJohan Hedberg {
971a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
972a5c29683SJohan Hedberg 
973a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
974a5c29683SJohan Hedberg 
97556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
97656e5cb86SJohan Hedberg 
977a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
97804124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
97904124681SGustavo F. Padovan 						 rp->status);
98056e5cb86SJohan Hedberg 
98156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
982a5c29683SJohan Hedberg }
983a5c29683SJohan Hedberg 
984a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
985a5c29683SJohan Hedberg 							struct sk_buff *skb)
986a5c29683SJohan Hedberg {
987a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
988a5c29683SJohan Hedberg 
989a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
990a5c29683SJohan Hedberg 
99156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
99256e5cb86SJohan Hedberg 
993a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
994744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
99504124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
99656e5cb86SJohan Hedberg 
99756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
998a5c29683SJohan Hedberg }
999a5c29683SJohan Hedberg 
10001143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
10011143d458SBrian Gix {
10021143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10031143d458SBrian Gix 
10041143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10051143d458SBrian Gix 
10061143d458SBrian Gix 	hci_dev_lock(hdev);
10071143d458SBrian Gix 
1008a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1009272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1010272d90dfSJohan Hedberg 						 0, rp->status);
10111143d458SBrian Gix 
10121143d458SBrian Gix 	hci_dev_unlock(hdev);
10131143d458SBrian Gix }
10141143d458SBrian Gix 
10151143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10161143d458SBrian Gix 							struct sk_buff *skb)
10171143d458SBrian Gix {
10181143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10191143d458SBrian Gix 
10201143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10211143d458SBrian Gix 
10221143d458SBrian Gix 	hci_dev_lock(hdev);
10231143d458SBrian Gix 
1024a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10251143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
102604124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
10271143d458SBrian Gix 
10281143d458SBrian Gix 	hci_dev_unlock(hdev);
10291143d458SBrian Gix }
10301143d458SBrian Gix 
1031c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1032c35938b2SSzymon Janc 							struct sk_buff *skb)
1033c35938b2SSzymon Janc {
1034c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1035c35938b2SSzymon Janc 
1036c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1037c35938b2SSzymon Janc 
103856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1039744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1040c35938b2SSzymon Janc 						rp->randomizer, rp->status);
104156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1042c35938b2SSzymon Janc }
1043c35938b2SSzymon Janc 
104407f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
104507f7fa5dSAndre Guedes {
104607f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
104707f7fa5dSAndre Guedes 
104807f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
10497ba8b4beSAndre Guedes 
10507ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
10513fd24153SAndre Guedes 
10523fd24153SAndre Guedes 	if (status) {
10533fd24153SAndre Guedes 		hci_dev_lock(hdev);
10543fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
10553fd24153SAndre Guedes 		hci_dev_unlock(hdev);
10563fd24153SAndre Guedes 		return;
10573fd24153SAndre Guedes 	}
105807f7fa5dSAndre Guedes }
105907f7fa5dSAndre Guedes 
1060eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1061eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1062eb9d91f5SAndre Guedes {
1063eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1064eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1065eb9d91f5SAndre Guedes 
1066eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1067eb9d91f5SAndre Guedes 
1068eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1069eb9d91f5SAndre Guedes 	if (!cp)
1070eb9d91f5SAndre Guedes 		return;
1071eb9d91f5SAndre Guedes 
107268a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
107368a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
10747ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
10757ba8b4beSAndre Guedes 
10763fd24153SAndre Guedes 		if (status) {
10773fd24153SAndre Guedes 			hci_dev_lock(hdev);
10783fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
10793fd24153SAndre Guedes 			hci_dev_unlock(hdev);
10807ba8b4beSAndre Guedes 			return;
10813fd24153SAndre Guedes 		}
10827ba8b4beSAndre Guedes 
1083d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1084d23264a8SAndre Guedes 
1085db323f2fSGustavo F. Padovan 		cancel_delayed_work_sync(&hdev->adv_work);
1086a8f13c8cSAndre Guedes 
1087a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1088eb9d91f5SAndre Guedes 		hci_adv_entries_clear(hdev);
1089343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1090a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
109168a8aea4SAndrei Emeltchenko 		break;
109268a8aea4SAndrei Emeltchenko 
109368a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
10947ba8b4beSAndre Guedes 		if (status)
10957ba8b4beSAndre Guedes 			return;
10967ba8b4beSAndre Guedes 
1097d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1098d23264a8SAndre Guedes 
10995e0452c0SAndre Guedes 		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
11005e0452c0SAndre Guedes 
1101bc3dd33cSAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1102bc3dd33cSAndre Guedes 		    hdev->discovery.state == DISCOVERY_FINDING) {
11035e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
11045e0452c0SAndre Guedes 		} else {
1105c599008fSAndre Guedes 			hci_dev_lock(hdev);
1106c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1107c599008fSAndre Guedes 			hci_dev_unlock(hdev);
11085e0452c0SAndre Guedes 		}
1109c599008fSAndre Guedes 
111068a8aea4SAndrei Emeltchenko 		break;
111168a8aea4SAndrei Emeltchenko 
111268a8aea4SAndrei Emeltchenko 	default:
111368a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
111468a8aea4SAndrei Emeltchenko 		break;
111535815085SAndre Guedes 	}
1116eb9d91f5SAndre Guedes }
1117eb9d91f5SAndre Guedes 
1118a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1119a7a595f6SVinicius Costa Gomes {
1120a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1121a7a595f6SVinicius Costa Gomes 
1122a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1123a7a595f6SVinicius Costa Gomes 
1124a7a595f6SVinicius Costa Gomes 	if (rp->status)
1125a7a595f6SVinicius Costa Gomes 		return;
1126a7a595f6SVinicius Costa Gomes 
1127a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1128a7a595f6SVinicius Costa Gomes }
1129a7a595f6SVinicius Costa Gomes 
1130a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1131a7a595f6SVinicius Costa Gomes {
1132a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1133a7a595f6SVinicius Costa Gomes 
1134a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1135a7a595f6SVinicius Costa Gomes 
1136a7a595f6SVinicius Costa Gomes 	if (rp->status)
1137a7a595f6SVinicius Costa Gomes 		return;
1138a7a595f6SVinicius Costa Gomes 
1139a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1140a7a595f6SVinicius Costa Gomes }
1141a7a595f6SVinicius Costa Gomes 
1142f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1143f9b49306SAndre Guedes 							struct sk_buff *skb)
1144f9b49306SAndre Guedes {
114506199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1146f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1147f9b49306SAndre Guedes 
1148f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1149f9b49306SAndre Guedes 
115006199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
11518f984dfaSJohan Hedberg 	if (!sent)
1152f9b49306SAndre Guedes 		return;
1153f9b49306SAndre Guedes 
11548f984dfaSJohan Hedberg 	if (!status) {
11558f984dfaSJohan Hedberg 		if (sent->le)
11568f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
11578f984dfaSJohan Hedberg 		else
11588f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
11598f984dfaSJohan Hedberg 	}
11608f984dfaSJohan Hedberg 
11618f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
11628f984dfaSJohan Hedberg 					!test_bit(HCI_INIT, &hdev->flags))
11638f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
11648f984dfaSJohan Hedberg 
11658f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1166f9b49306SAndre Guedes }
1167f9b49306SAndre Guedes 
1168a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1169a9de9248SMarcel Holtmann {
1170a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1171a9de9248SMarcel Holtmann 
1172a9de9248SMarcel Holtmann 	if (status) {
117323bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1174a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
117556e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1176a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11777a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
117856e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1179314b2381SJohan Hedberg 		return;
1180314b2381SJohan Hedberg 	}
1181314b2381SJohan Hedberg 
118289352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
118389352e7dSAndre Guedes 
118456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1185343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
118656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1187a9de9248SMarcel Holtmann }
1188a9de9248SMarcel Holtmann 
11891da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11901da177e4SLinus Torvalds {
1191a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11921da177e4SLinus Torvalds 	struct hci_conn *conn;
11931da177e4SLinus Torvalds 
1194a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1195a9de9248SMarcel Holtmann 
1196a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11971da177e4SLinus Torvalds 	if (!cp)
11981da177e4SLinus Torvalds 		return;
11991da177e4SLinus Torvalds 
12001da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12011da177e4SLinus Torvalds 
12021da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
12031da177e4SLinus Torvalds 
1204a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
12051da177e4SLinus Torvalds 
12061da177e4SLinus Torvalds 	if (status) {
12071da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
12084c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
12091da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
12101da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
12111da177e4SLinus Torvalds 				hci_conn_del(conn);
12124c67bc74SMarcel Holtmann 			} else
12134c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
12141da177e4SLinus Torvalds 		}
12151da177e4SLinus Torvalds 	} else {
12161da177e4SLinus Torvalds 		if (!conn) {
12171da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
12181da177e4SLinus Torvalds 			if (conn) {
1219a0c808b3SJohan Hedberg 				conn->out = true;
12201da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
12211da177e4SLinus Torvalds 			} else
1222893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12231da177e4SLinus Torvalds 		}
12241da177e4SLinus Torvalds 	}
12251da177e4SLinus Torvalds 
12261da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12271da177e4SLinus Torvalds }
12281da177e4SLinus Torvalds 
1229a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12301da177e4SLinus Torvalds {
1231a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12321da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12331da177e4SLinus Torvalds 	__u16 handle;
12341da177e4SLinus Torvalds 
1235b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1236b6a0dc82SMarcel Holtmann 
1237a9de9248SMarcel Holtmann 	if (!status)
1238a9de9248SMarcel Holtmann 		return;
1239a9de9248SMarcel Holtmann 
1240a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12411da177e4SLinus Torvalds 	if (!cp)
1242a9de9248SMarcel Holtmann 		return;
12431da177e4SLinus Torvalds 
12441da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12451da177e4SLinus Torvalds 
1246a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
12471da177e4SLinus Torvalds 
12481da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12491da177e4SLinus Torvalds 
12501da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12515a08ecceSAndrei Emeltchenko 	if (acl) {
12525a08ecceSAndrei Emeltchenko 		sco = acl->link;
12535a08ecceSAndrei Emeltchenko 		if (sco) {
12541da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12551da177e4SLinus Torvalds 
12561da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12571da177e4SLinus Torvalds 			hci_conn_del(sco);
12581da177e4SLinus Torvalds 		}
12595a08ecceSAndrei Emeltchenko 	}
12601da177e4SLinus Torvalds 
12611da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12621da177e4SLinus Torvalds }
12631da177e4SLinus Torvalds 
1264f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1265f8558555SMarcel Holtmann {
1266f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1267f8558555SMarcel Holtmann 	struct hci_conn *conn;
1268f8558555SMarcel Holtmann 
1269f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1270f8558555SMarcel Holtmann 
1271f8558555SMarcel Holtmann 	if (!status)
1272f8558555SMarcel Holtmann 		return;
1273f8558555SMarcel Holtmann 
1274f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1275f8558555SMarcel Holtmann 	if (!cp)
1276f8558555SMarcel Holtmann 		return;
1277f8558555SMarcel Holtmann 
1278f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1279f8558555SMarcel Holtmann 
1280f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1281f8558555SMarcel Holtmann 	if (conn) {
1282f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1283f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1284f8558555SMarcel Holtmann 			hci_conn_put(conn);
1285f8558555SMarcel Holtmann 		}
1286f8558555SMarcel Holtmann 	}
1287f8558555SMarcel Holtmann 
1288f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1289f8558555SMarcel Holtmann }
1290f8558555SMarcel Holtmann 
1291f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1292f8558555SMarcel Holtmann {
1293f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1294f8558555SMarcel Holtmann 	struct hci_conn *conn;
1295f8558555SMarcel Holtmann 
1296f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1297f8558555SMarcel Holtmann 
1298f8558555SMarcel Holtmann 	if (!status)
1299f8558555SMarcel Holtmann 		return;
1300f8558555SMarcel Holtmann 
1301f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1302f8558555SMarcel Holtmann 	if (!cp)
1303f8558555SMarcel Holtmann 		return;
1304f8558555SMarcel Holtmann 
1305f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1306f8558555SMarcel Holtmann 
1307f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1308f8558555SMarcel Holtmann 	if (conn) {
1309f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1310f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1311f8558555SMarcel Holtmann 			hci_conn_put(conn);
1312f8558555SMarcel Holtmann 		}
1313f8558555SMarcel Holtmann 	}
1314f8558555SMarcel Holtmann 
1315f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1316f8558555SMarcel Holtmann }
1317f8558555SMarcel Holtmann 
1318127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1319392599b9SJohan Hedberg 							struct hci_conn *conn)
1320392599b9SJohan Hedberg {
1321392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1322392599b9SJohan Hedberg 		return 0;
1323392599b9SJohan Hedberg 
1324765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1325392599b9SJohan Hedberg 		return 0;
1326392599b9SJohan Hedberg 
1327392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1328e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1329aa64a8b5SJohan Hedberg 	if (!hci_conn_ssp_enabled(conn) &&
1330e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1331e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1332392599b9SJohan Hedberg 		return 0;
1333392599b9SJohan Hedberg 
1334392599b9SJohan Hedberg 	return 1;
1335392599b9SJohan Hedberg }
1336392599b9SJohan Hedberg 
133700abfe44SGustavo F. Padovan static inline int hci_resolve_name(struct hci_dev *hdev,
133800abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
133930dc78e1SJohan Hedberg {
134030dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
134130dc78e1SJohan Hedberg 
134230dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
134330dc78e1SJohan Hedberg 
134430dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
134530dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
134630dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
134730dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
134830dc78e1SJohan Hedberg 
134930dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
135030dc78e1SJohan Hedberg }
135130dc78e1SJohan Hedberg 
1352b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
135330dc78e1SJohan Hedberg {
135430dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
135530dc78e1SJohan Hedberg 	struct inquiry_entry *e;
135630dc78e1SJohan Hedberg 
1357b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1358b644ba33SJohan Hedberg 		return false;
1359b644ba33SJohan Hedberg 
1360b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1361b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1362b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1363b644ba33SJohan Hedberg 		return true;
1364b644ba33SJohan Hedberg 	}
1365b644ba33SJohan Hedberg 
1366b644ba33SJohan Hedberg 	return false;
1367b644ba33SJohan Hedberg }
1368b644ba33SJohan Hedberg 
1369b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1370b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1371b644ba33SJohan Hedberg {
1372b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1373b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1374b644ba33SJohan Hedberg 
1375b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
137604124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
137704124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1378b644ba33SJohan Hedberg 
1379b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1380b644ba33SJohan Hedberg 		return;
1381b644ba33SJohan Hedberg 
138230dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
138330dc78e1SJohan Hedberg 		goto discov_complete;
138430dc78e1SJohan Hedberg 
138530dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
138630dc78e1SJohan Hedberg 		return;
138730dc78e1SJohan Hedberg 
138830dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
138930dc78e1SJohan Hedberg 	if (e) {
139030dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
139130dc78e1SJohan Hedberg 		list_del(&e->list);
1392b644ba33SJohan Hedberg 		if (name)
1393b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1394b644ba33SJohan Hedberg 					 e->data.rssi, name, name_len);
139530dc78e1SJohan Hedberg 	}
139630dc78e1SJohan Hedberg 
1397b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
139830dc78e1SJohan Hedberg 		return;
139930dc78e1SJohan Hedberg 
140030dc78e1SJohan Hedberg discov_complete:
140130dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
140230dc78e1SJohan Hedberg }
140330dc78e1SJohan Hedberg 
1404a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
14051da177e4SLinus Torvalds {
1406127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1407127178d2SJohan Hedberg 	struct hci_conn *conn;
1408127178d2SJohan Hedberg 
1409a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1410127178d2SJohan Hedberg 
1411127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1412127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1413127178d2SJohan Hedberg 	if (!status)
1414127178d2SJohan Hedberg 		return;
1415127178d2SJohan Hedberg 
1416127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1417127178d2SJohan Hedberg 	if (!cp)
1418127178d2SJohan Hedberg 		return;
1419127178d2SJohan Hedberg 
1420127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1421127178d2SJohan Hedberg 
1422127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1423b644ba33SJohan Hedberg 
1424b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1425b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1426b644ba33SJohan Hedberg 
142779c6c70cSJohan Hedberg 	if (!conn)
142879c6c70cSJohan Hedberg 		goto unlock;
142979c6c70cSJohan Hedberg 
143079c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
143179c6c70cSJohan Hedberg 		goto unlock;
143279c6c70cSJohan Hedberg 
143351a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1434127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1435127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1436127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1437127178d2SJohan Hedberg 	}
1438127178d2SJohan Hedberg 
143979c6c70cSJohan Hedberg unlock:
1440127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1441a9de9248SMarcel Holtmann }
14421da177e4SLinus Torvalds 
1443769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1444769be974SMarcel Holtmann {
1445769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1446769be974SMarcel Holtmann 	struct hci_conn *conn;
1447769be974SMarcel Holtmann 
1448769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1449769be974SMarcel Holtmann 
1450769be974SMarcel Holtmann 	if (!status)
1451769be974SMarcel Holtmann 		return;
1452769be974SMarcel Holtmann 
1453769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1454769be974SMarcel Holtmann 	if (!cp)
1455769be974SMarcel Holtmann 		return;
1456769be974SMarcel Holtmann 
1457769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1458769be974SMarcel Holtmann 
1459769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1460769be974SMarcel Holtmann 	if (conn) {
1461769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1462769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1463769be974SMarcel Holtmann 			hci_conn_put(conn);
1464769be974SMarcel Holtmann 		}
1465769be974SMarcel Holtmann 	}
1466769be974SMarcel Holtmann 
1467769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1468769be974SMarcel Holtmann }
1469769be974SMarcel Holtmann 
1470769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1471769be974SMarcel Holtmann {
1472769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1473769be974SMarcel Holtmann 	struct hci_conn *conn;
1474769be974SMarcel Holtmann 
1475769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1476769be974SMarcel Holtmann 
1477769be974SMarcel Holtmann 	if (!status)
1478769be974SMarcel Holtmann 		return;
1479769be974SMarcel Holtmann 
1480769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1481769be974SMarcel Holtmann 	if (!cp)
1482769be974SMarcel Holtmann 		return;
1483769be974SMarcel Holtmann 
1484769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1485769be974SMarcel Holtmann 
1486769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1487769be974SMarcel Holtmann 	if (conn) {
1488769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1489769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1490769be974SMarcel Holtmann 			hci_conn_put(conn);
1491769be974SMarcel Holtmann 		}
1492769be974SMarcel Holtmann 	}
1493769be974SMarcel Holtmann 
1494769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1495769be974SMarcel Holtmann }
1496769be974SMarcel Holtmann 
1497a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1498a9de9248SMarcel Holtmann {
1499b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1500b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1501b6a0dc82SMarcel Holtmann 	__u16 handle;
1502b6a0dc82SMarcel Holtmann 
1503a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1504b6a0dc82SMarcel Holtmann 
1505b6a0dc82SMarcel Holtmann 	if (!status)
1506b6a0dc82SMarcel Holtmann 		return;
1507b6a0dc82SMarcel Holtmann 
1508b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1509b6a0dc82SMarcel Holtmann 	if (!cp)
1510b6a0dc82SMarcel Holtmann 		return;
1511b6a0dc82SMarcel Holtmann 
1512b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1513b6a0dc82SMarcel Holtmann 
1514b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1515b6a0dc82SMarcel Holtmann 
1516b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1517b6a0dc82SMarcel Holtmann 
1518b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15195a08ecceSAndrei Emeltchenko 	if (acl) {
15205a08ecceSAndrei Emeltchenko 		sco = acl->link;
15215a08ecceSAndrei Emeltchenko 		if (sco) {
1522b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1523b6a0dc82SMarcel Holtmann 
1524b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1525b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1526b6a0dc82SMarcel Holtmann 		}
15275a08ecceSAndrei Emeltchenko 	}
1528b6a0dc82SMarcel Holtmann 
1529b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1530a9de9248SMarcel Holtmann }
1531a9de9248SMarcel Holtmann 
1532a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1533a9de9248SMarcel Holtmann {
1534a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
153504837f64SMarcel Holtmann 	struct hci_conn *conn;
153604837f64SMarcel Holtmann 
1537a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1538a9de9248SMarcel Holtmann 
1539a9de9248SMarcel Holtmann 	if (!status)
1540a9de9248SMarcel Holtmann 		return;
1541a9de9248SMarcel Holtmann 
1542a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
154304837f64SMarcel Holtmann 	if (!cp)
1544a9de9248SMarcel Holtmann 		return;
154504837f64SMarcel Holtmann 
154604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
154704837f64SMarcel Holtmann 
154804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1549e73439d8SMarcel Holtmann 	if (conn) {
155051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
155104837f64SMarcel Holtmann 
155251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1553e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1554e73439d8SMarcel Holtmann 	}
1555e73439d8SMarcel Holtmann 
155604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
155704837f64SMarcel Holtmann }
155804837f64SMarcel Holtmann 
1559a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1560a9de9248SMarcel Holtmann {
1561a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
156204837f64SMarcel Holtmann 	struct hci_conn *conn;
156304837f64SMarcel Holtmann 
1564a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1565a9de9248SMarcel Holtmann 
1566a9de9248SMarcel Holtmann 	if (!status)
1567a9de9248SMarcel Holtmann 		return;
1568a9de9248SMarcel Holtmann 
1569a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
157004837f64SMarcel Holtmann 	if (!cp)
1571a9de9248SMarcel Holtmann 		return;
157204837f64SMarcel Holtmann 
157304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
157404837f64SMarcel Holtmann 
157504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1576e73439d8SMarcel Holtmann 	if (conn) {
157751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
157804837f64SMarcel Holtmann 
157951a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1580e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1581e73439d8SMarcel Holtmann 	}
1582e73439d8SMarcel Holtmann 
158304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
158404837f64SMarcel Holtmann }
158504837f64SMarcel Holtmann 
158688c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
158788c3df13SJohan Hedberg {
158888c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
158988c3df13SJohan Hedberg 	struct hci_conn *conn;
159088c3df13SJohan Hedberg 
159188c3df13SJohan Hedberg 	if (!status)
159288c3df13SJohan Hedberg 		return;
159388c3df13SJohan Hedberg 
159488c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
159588c3df13SJohan Hedberg 	if (!cp)
159688c3df13SJohan Hedberg 		return;
159788c3df13SJohan Hedberg 
159888c3df13SJohan Hedberg 	hci_dev_lock(hdev);
159988c3df13SJohan Hedberg 
160088c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
160188c3df13SJohan Hedberg 	if (conn)
160288c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
160388c3df13SJohan Hedberg 				       conn->dst_type, status);
160488c3df13SJohan Hedberg 
160588c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
160688c3df13SJohan Hedberg }
160788c3df13SJohan Hedberg 
1608fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1609fcd89c09SVille Tervo {
1610fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1611fcd89c09SVille Tervo 	struct hci_conn *conn;
1612fcd89c09SVille Tervo 
1613fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1614fcd89c09SVille Tervo 
1615fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1616fcd89c09SVille Tervo 	if (!cp)
1617fcd89c09SVille Tervo 		return;
1618fcd89c09SVille Tervo 
1619fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1620fcd89c09SVille Tervo 
1621fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1622fcd89c09SVille Tervo 
1623fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1624fcd89c09SVille Tervo 		conn);
1625fcd89c09SVille Tervo 
1626fcd89c09SVille Tervo 	if (status) {
1627fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1628fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1629fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1630fcd89c09SVille Tervo 			hci_conn_del(conn);
1631fcd89c09SVille Tervo 		}
1632fcd89c09SVille Tervo 	} else {
1633fcd89c09SVille Tervo 		if (!conn) {
1634fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
163529b7988aSAndre Guedes 			if (conn) {
163629b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1637a0c808b3SJohan Hedberg 				conn->out = true;
163829b7988aSAndre Guedes 			} else {
1639fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1640fcd89c09SVille Tervo 			}
1641fcd89c09SVille Tervo 		}
164229b7988aSAndre Guedes 	}
1643fcd89c09SVille Tervo 
1644fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1645fcd89c09SVille Tervo }
1646fcd89c09SVille Tervo 
1647a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1648a7a595f6SVinicius Costa Gomes {
1649a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1650a7a595f6SVinicius Costa Gomes }
1651a7a595f6SVinicius Costa Gomes 
16521da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16531da177e4SLinus Torvalds {
16541da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
165530dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
165630dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16571da177e4SLinus Torvalds 
16581da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
16591da177e4SLinus Torvalds 
166023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16616bd57416SMarcel Holtmann 
1662a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
166389352e7dSAndre Guedes 
166489352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
166589352e7dSAndre Guedes 		return;
166689352e7dSAndre Guedes 
1667a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
166830dc78e1SJohan Hedberg 		return;
166930dc78e1SJohan Hedberg 
167056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
167130dc78e1SJohan Hedberg 
1672343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
167330dc78e1SJohan Hedberg 		goto unlock;
167430dc78e1SJohan Hedberg 
167530dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1676ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
167730dc78e1SJohan Hedberg 		goto unlock;
167830dc78e1SJohan Hedberg 	}
167930dc78e1SJohan Hedberg 
168030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
168130dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
168230dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
168330dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
168430dc78e1SJohan Hedberg 	} else {
168530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
168630dc78e1SJohan Hedberg 	}
168730dc78e1SJohan Hedberg 
168830dc78e1SJohan Hedberg unlock:
168956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16901da177e4SLinus Torvalds }
16911da177e4SLinus Torvalds 
16921da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16931da177e4SLinus Torvalds {
169445bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1695a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16961da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16971da177e4SLinus Torvalds 
16981da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16991da177e4SLinus Torvalds 
170045bb4bf0SMarcel Holtmann 	if (!num_rsp)
170145bb4bf0SMarcel Holtmann 		return;
170245bb4bf0SMarcel Holtmann 
17031da177e4SLinus Torvalds 	hci_dev_lock(hdev);
170445bb4bf0SMarcel Holtmann 
1705e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1706388fc8faSJohan Hedberg 		bool name_known, ssp;
17073175405bSJohan Hedberg 
17081da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
17091da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
17101da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
17111da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
17121da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
17131da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17141da177e4SLinus Torvalds 		data.rssi		= 0x00;
171541a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17163175405bSJohan Hedberg 
1717388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
171848264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
171904124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
172004124681SGustavo F. Padovan 				  0);
17211da177e4SLinus Torvalds 	}
172245bb4bf0SMarcel Holtmann 
17231da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17241da177e4SLinus Torvalds }
17251da177e4SLinus Torvalds 
1726a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17271da177e4SLinus Torvalds {
1728a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1729a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17301da177e4SLinus Torvalds 
1731a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
173245bb4bf0SMarcel Holtmann 
17331da177e4SLinus Torvalds 	hci_dev_lock(hdev);
173445bb4bf0SMarcel Holtmann 
1735a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17369499237aSMarcel Holtmann 	if (!conn) {
17379499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17389499237aSMarcel Holtmann 			goto unlock;
17399499237aSMarcel Holtmann 
17409499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1741a9de9248SMarcel Holtmann 		if (!conn)
1742a9de9248SMarcel Holtmann 			goto unlock;
174345bb4bf0SMarcel Holtmann 
17449499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17459499237aSMarcel Holtmann 	}
17469499237aSMarcel Holtmann 
1747a9de9248SMarcel Holtmann 	if (!ev->status) {
1748a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1749769be974SMarcel Holtmann 
1750769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1751769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1752769be974SMarcel Holtmann 			hci_conn_hold(conn);
1753052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1754769be974SMarcel Holtmann 		} else
1755a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1756a9de9248SMarcel Holtmann 
17579eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
17587d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17597d0db0a3SMarcel Holtmann 
1760a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1761a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1762a9de9248SMarcel Holtmann 
1763a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1764a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1765a9de9248SMarcel Holtmann 
1766a9de9248SMarcel Holtmann 		/* Get remote features */
1767a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1768a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1769a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1770769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1771769be974SMarcel Holtmann 				     sizeof(cp), &cp);
177245bb4bf0SMarcel Holtmann 		}
1773a9de9248SMarcel Holtmann 
1774a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1775d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1776a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1777a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1778a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
177904124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
178004124681SGustavo F. Padovan 				     &cp);
1781a9de9248SMarcel Holtmann 		}
178217d5c04cSJohan Hedberg 	} else {
1783a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
178417d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1785744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
178648264f06SJohan Hedberg 					    conn->dst_type, ev->status);
178717d5c04cSJohan Hedberg 	}
178845bb4bf0SMarcel Holtmann 
1789e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1790e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
179145bb4bf0SMarcel Holtmann 
1792769be974SMarcel Holtmann 	if (ev->status) {
1793a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1794a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1795c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1796c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1797a9de9248SMarcel Holtmann 
1798a9de9248SMarcel Holtmann unlock:
17991da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1800a9de9248SMarcel Holtmann 
1801a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
18021da177e4SLinus Torvalds }
18031da177e4SLinus Torvalds 
18041da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18051da177e4SLinus Torvalds {
1806a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
18071da177e4SLinus Torvalds 	int mask = hdev->link_mode;
18081da177e4SLinus Torvalds 
1809a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
18101da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
18111da177e4SLinus Torvalds 
18121da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
18131da177e4SLinus Torvalds 
1814138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1815138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
18161da177e4SLinus Torvalds 		/* Connection accepted */
1817c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
18181da177e4SLinus Torvalds 		struct hci_conn *conn;
18191da177e4SLinus Torvalds 
18201da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1821b6a0dc82SMarcel Holtmann 
1822cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1823cc11b9c1SAndrei Emeltchenko 		if (ie)
1824c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1825c7bdd502SMarcel Holtmann 
18261da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
18271da177e4SLinus Torvalds 		if (!conn) {
1828cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1829cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1830893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
18311da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
18321da177e4SLinus Torvalds 				return;
18331da177e4SLinus Torvalds 			}
18341da177e4SLinus Torvalds 		}
1835b6a0dc82SMarcel Holtmann 
18361da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
18371da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1838b6a0dc82SMarcel Holtmann 
18391da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
18401da177e4SLinus Torvalds 
1841b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1842b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1843b6a0dc82SMarcel Holtmann 
18441da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
18451da177e4SLinus Torvalds 
18461da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
18471da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
18481da177e4SLinus Torvalds 			else
18491da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
18501da177e4SLinus Torvalds 
185104124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
185204124681SGustavo F. Padovan 				     &cp);
1853b6a0dc82SMarcel Holtmann 		} else {
1854b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1855b6a0dc82SMarcel Holtmann 
1856b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1857a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1858b6a0dc82SMarcel Holtmann 
1859b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1860b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1861b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1862b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1863b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1864b6a0dc82SMarcel Holtmann 
1865b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1866b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
1867b6a0dc82SMarcel Holtmann 		}
18681da177e4SLinus Torvalds 	} else {
18691da177e4SLinus Torvalds 		/* Connection rejected */
18701da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18711da177e4SLinus Torvalds 
18721da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18739f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1874a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18751da177e4SLinus Torvalds 	}
18761da177e4SLinus Torvalds }
18771da177e4SLinus Torvalds 
18781da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18791da177e4SLinus Torvalds {
1880a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
188104837f64SMarcel Holtmann 	struct hci_conn *conn;
18821da177e4SLinus Torvalds 
18831da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
18841da177e4SLinus Torvalds 
18851da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18861da177e4SLinus Torvalds 
188704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1888f7520543SJohan Hedberg 	if (!conn)
1889f7520543SJohan Hedberg 		goto unlock;
1890f7520543SJohan Hedberg 
189137d9ef76SJohan Hedberg 	if (ev->status == 0)
18921da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18937d0db0a3SMarcel Holtmann 
1894b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1895b644ba33SJohan Hedberg 			(conn->type == ACL_LINK || conn->type == LE_LINK)) {
189637d9ef76SJohan Hedberg 		if (ev->status != 0)
189788c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
189888c3df13SJohan Hedberg 						conn->dst_type, ev->status);
189937d9ef76SJohan Hedberg 		else
1900afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
190148264f06SJohan Hedberg 						 conn->dst_type);
190237d9ef76SJohan Hedberg 	}
1903f7520543SJohan Hedberg 
190437d9ef76SJohan Hedberg 	if (ev->status == 0) {
19056ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
19066ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
19072950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
19081da177e4SLinus Torvalds 		hci_conn_del(conn);
190937d9ef76SJohan Hedberg 	}
19101da177e4SLinus Torvalds 
1911f7520543SJohan Hedberg unlock:
19121da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19131da177e4SLinus Torvalds }
19141da177e4SLinus Torvalds 
1915a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1916a9de9248SMarcel Holtmann {
1917a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1918a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1919a9de9248SMarcel Holtmann 
1920a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1921a9de9248SMarcel Holtmann 
1922a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1923a9de9248SMarcel Holtmann 
1924a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1925d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1926d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1927d7556e20SWaldemar Rymarkiewicz 
1928765c2a96SJohan Hedberg 	if (!ev->status) {
1929aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
193051a8efd7SJohan Hedberg 				test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1931d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
193219f8def0SWaldemar Rymarkiewicz 		} else {
1933a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1934765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
193519f8def0SWaldemar Rymarkiewicz 		}
19362a611692SJohan Hedberg 	} else {
1937bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1938bab73cb6SJohan Hedberg 				 ev->status);
19392a611692SJohan Hedberg 	}
1940a9de9248SMarcel Holtmann 
194151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
194251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1943a9de9248SMarcel Holtmann 
1944f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1945aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1946f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1947f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1948f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1949d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1950d7556e20SWaldemar Rymarkiewicz 									&cp);
1951f8558555SMarcel Holtmann 		} else {
1952f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1953f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1954f8558555SMarcel Holtmann 			hci_conn_put(conn);
1955f8558555SMarcel Holtmann 		}
1956052b30b0SMarcel Holtmann 	} else {
1957a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1958a9de9248SMarcel Holtmann 
1959052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1960052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1961052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1962052b30b0SMarcel Holtmann 	}
1963052b30b0SMarcel Holtmann 
196451a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1965a9de9248SMarcel Holtmann 		if (!ev->status) {
1966a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1967f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1968f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1969d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1970d7556e20SWaldemar Rymarkiewicz 									&cp);
1971a9de9248SMarcel Holtmann 		} else {
197251a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1973a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1974a9de9248SMarcel Holtmann 		}
1975a9de9248SMarcel Holtmann 	}
1976a9de9248SMarcel Holtmann 
1977d7556e20SWaldemar Rymarkiewicz unlock:
1978a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1979a9de9248SMarcel Holtmann }
1980a9de9248SMarcel Holtmann 
1981a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1982a9de9248SMarcel Holtmann {
1983127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1984127178d2SJohan Hedberg 	struct hci_conn *conn;
1985127178d2SJohan Hedberg 
1986a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1987a9de9248SMarcel Holtmann 
1988a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1989127178d2SJohan Hedberg 
1990127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1991127178d2SJohan Hedberg 
1992127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1993b644ba33SJohan Hedberg 
1994b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1995b644ba33SJohan Hedberg 		goto check_auth;
1996b644ba33SJohan Hedberg 
1997b644ba33SJohan Hedberg 	if (ev->status == 0)
1998b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1999b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2000b644ba33SJohan Hedberg 	else
2001b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2002b644ba33SJohan Hedberg 
2003b644ba33SJohan Hedberg check_auth:
200479c6c70cSJohan Hedberg 	if (!conn)
200579c6c70cSJohan Hedberg 		goto unlock;
200679c6c70cSJohan Hedberg 
200779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
200879c6c70cSJohan Hedberg 		goto unlock;
200979c6c70cSJohan Hedberg 
201051a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2011127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2012127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2013127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2014127178d2SJohan Hedberg 	}
2015127178d2SJohan Hedberg 
201679c6c70cSJohan Hedberg unlock:
2017127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2018a9de9248SMarcel Holtmann }
2019a9de9248SMarcel Holtmann 
2020a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2021a9de9248SMarcel Holtmann {
2022a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2023a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2024a9de9248SMarcel Holtmann 
2025a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2026a9de9248SMarcel Holtmann 
2027a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2028a9de9248SMarcel Holtmann 
2029a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2030a9de9248SMarcel Holtmann 	if (conn) {
2031a9de9248SMarcel Holtmann 		if (!ev->status) {
2032ae293196SMarcel Holtmann 			if (ev->encrypt) {
2033ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2034ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2035a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2036da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2037ae293196SMarcel Holtmann 			} else
2038a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2039a9de9248SMarcel Holtmann 		}
2040a9de9248SMarcel Holtmann 
204151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2042a9de9248SMarcel Holtmann 
2043f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2044f8558555SMarcel Holtmann 			if (!ev->status)
2045f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2046f8558555SMarcel Holtmann 
2047f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2048f8558555SMarcel Holtmann 			hci_conn_put(conn);
2049f8558555SMarcel Holtmann 		} else
2050a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2051a9de9248SMarcel Holtmann 	}
2052a9de9248SMarcel Holtmann 
2053a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2054a9de9248SMarcel Holtmann }
2055a9de9248SMarcel Holtmann 
2056a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2057a9de9248SMarcel Holtmann {
2058a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2059a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2060a9de9248SMarcel Holtmann 
2061a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2062a9de9248SMarcel Holtmann 
2063a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2064a9de9248SMarcel Holtmann 
2065a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2066a9de9248SMarcel Holtmann 	if (conn) {
2067a9de9248SMarcel Holtmann 		if (!ev->status)
2068a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2069a9de9248SMarcel Holtmann 
207051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2071a9de9248SMarcel Holtmann 
2072a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2073a9de9248SMarcel Holtmann 	}
2074a9de9248SMarcel Holtmann 
2075a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2076a9de9248SMarcel Holtmann }
2077a9de9248SMarcel Holtmann 
2078a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2079a9de9248SMarcel Holtmann {
2080a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2081a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2082a9de9248SMarcel Holtmann 
2083a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2084a9de9248SMarcel Holtmann 
2085a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2086a9de9248SMarcel Holtmann 
2087a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2088ccd556feSJohan Hedberg 	if (!conn)
2089ccd556feSJohan Hedberg 		goto unlock;
2090ccd556feSJohan Hedberg 
2091769be974SMarcel Holtmann 	if (!ev->status)
2092a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2093a9de9248SMarcel Holtmann 
2094ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2095ccd556feSJohan Hedberg 		goto unlock;
2096ccd556feSJohan Hedberg 
2097ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2098769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2099769be974SMarcel Holtmann 		cp.handle = ev->handle;
2100769be974SMarcel Holtmann 		cp.page = 0x01;
2101ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2102769be974SMarcel Holtmann 							sizeof(cp), &cp);
2103392599b9SJohan Hedberg 		goto unlock;
2104392599b9SJohan Hedberg 	}
2105392599b9SJohan Hedberg 
2106127178d2SJohan Hedberg 	if (!ev->status) {
2107127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2108127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2109127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2110127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2111127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2112b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2113b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
211408c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2115b644ba33SJohan Hedberg 				      conn->dev_class);
2116392599b9SJohan Hedberg 
2117127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2118769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2119769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2120769be974SMarcel Holtmann 		hci_conn_put(conn);
2121769be974SMarcel Holtmann 	}
2122769be974SMarcel Holtmann 
2123ccd556feSJohan Hedberg unlock:
2124a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2125a9de9248SMarcel Holtmann }
2126a9de9248SMarcel Holtmann 
2127a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2128a9de9248SMarcel Holtmann {
2129a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2130a9de9248SMarcel Holtmann }
2131a9de9248SMarcel Holtmann 
2132a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2133a9de9248SMarcel Holtmann {
2134a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2135a9de9248SMarcel Holtmann }
2136a9de9248SMarcel Holtmann 
2137a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2138a9de9248SMarcel Holtmann {
2139a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2140a9de9248SMarcel Holtmann 	__u16 opcode;
2141a9de9248SMarcel Holtmann 
2142a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2143a9de9248SMarcel Holtmann 
2144a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2145a9de9248SMarcel Holtmann 
2146a9de9248SMarcel Holtmann 	switch (opcode) {
2147a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2148a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2149a9de9248SMarcel Holtmann 		break;
2150a9de9248SMarcel Holtmann 
2151a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2152a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2153a9de9248SMarcel Holtmann 		break;
2154a9de9248SMarcel Holtmann 
2155a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2156a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2157a9de9248SMarcel Holtmann 		break;
2158a9de9248SMarcel Holtmann 
2159a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2160a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2161a9de9248SMarcel Holtmann 		break;
2162a9de9248SMarcel Holtmann 
2163e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2164e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2165e4e8e37cSMarcel Holtmann 		break;
2166e4e8e37cSMarcel Holtmann 
2167a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2168a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2169a9de9248SMarcel Holtmann 		break;
2170a9de9248SMarcel Holtmann 
2171e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2172e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2173e4e8e37cSMarcel Holtmann 		break;
2174e4e8e37cSMarcel Holtmann 
2175e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2176e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2177e4e8e37cSMarcel Holtmann 		break;
2178e4e8e37cSMarcel Holtmann 
2179a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2180a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2181a9de9248SMarcel Holtmann 		break;
2182a9de9248SMarcel Holtmann 
2183a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2184a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2185a9de9248SMarcel Holtmann 		break;
2186a9de9248SMarcel Holtmann 
2187a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2188a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2189a9de9248SMarcel Holtmann 		break;
2190a9de9248SMarcel Holtmann 
2191a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2192a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2193a9de9248SMarcel Holtmann 		break;
2194a9de9248SMarcel Holtmann 
2195a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2196a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2197a9de9248SMarcel Holtmann 		break;
2198a9de9248SMarcel Holtmann 
2199a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2200a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2201a9de9248SMarcel Holtmann 		break;
2202a9de9248SMarcel Holtmann 
2203a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2204a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2205a9de9248SMarcel Holtmann 		break;
2206a9de9248SMarcel Holtmann 
2207a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2208a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2209a9de9248SMarcel Holtmann 		break;
2210a9de9248SMarcel Holtmann 
2211a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2212a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2213a9de9248SMarcel Holtmann 		break;
2214a9de9248SMarcel Holtmann 
2215a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2216a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2217a9de9248SMarcel Holtmann 		break;
2218a9de9248SMarcel Holtmann 
2219a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2220a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2221a9de9248SMarcel Holtmann 		break;
2222a9de9248SMarcel Holtmann 
2223333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2224333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2225333140b5SMarcel Holtmann 		break;
2226333140b5SMarcel Holtmann 
2227a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2228a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2229a9de9248SMarcel Holtmann 		break;
2230a9de9248SMarcel Holtmann 
2231a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2232a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2233a9de9248SMarcel Holtmann 		break;
2234a9de9248SMarcel Holtmann 
2235a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2236a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2237a9de9248SMarcel Holtmann 		break;
2238a9de9248SMarcel Holtmann 
2239971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2240971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2241971e3a4bSAndre Guedes 		break;
2242971e3a4bSAndre Guedes 
2243a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2244a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2245a9de9248SMarcel Holtmann 		break;
2246a9de9248SMarcel Holtmann 
2247a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2248a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2249a9de9248SMarcel Holtmann 		break;
2250a9de9248SMarcel Holtmann 
2251350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2252350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2253350ee4cfSAndrei Emeltchenko 		break;
2254350ee4cfSAndrei Emeltchenko 
225523bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
225623bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
225723bb5763SJohan Hedberg 		break;
225823bb5763SJohan Hedberg 
22591e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22601e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22611e89cffbSAndrei Emeltchenko 		break;
22621e89cffbSAndrei Emeltchenko 
2263928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2264928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2265928abaa7SAndrei Emeltchenko 		break;
2266928abaa7SAndrei Emeltchenko 
2267b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2268b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2269b0916ea0SJohan Hedberg 		break;
2270b0916ea0SJohan Hedberg 
2271d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2272d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2273d5859e22SJohan Hedberg 		break;
2274d5859e22SJohan Hedberg 
2275d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2276d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2277d5859e22SJohan Hedberg 		break;
2278d5859e22SJohan Hedberg 
2279d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2280d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2281d5859e22SJohan Hedberg 		break;
2282d5859e22SJohan Hedberg 
2283d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2284d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2285d5859e22SJohan Hedberg 		break;
2286d5859e22SJohan Hedberg 
2287980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2288980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2289980e1a53SJohan Hedberg 		break;
2290980e1a53SJohan Hedberg 
2291980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2292980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2293980e1a53SJohan Hedberg 		break;
2294980e1a53SJohan Hedberg 
2295c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2296c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2297c35938b2SSzymon Janc 		break;
2298c35938b2SSzymon Janc 
22996ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
23006ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
23016ed58ec5SVille Tervo 		break;
23026ed58ec5SVille Tervo 
2303a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2304a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2305a5c29683SJohan Hedberg 		break;
2306a5c29683SJohan Hedberg 
2307a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2308a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2309a5c29683SJohan Hedberg 		break;
2310a5c29683SJohan Hedberg 
23111143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
23121143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
23131143d458SBrian Gix 		break;
23141143d458SBrian Gix 
23151143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23161143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
231716cde993SSzymon Janc 		break;
231807f7fa5dSAndre Guedes 
231907f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
232007f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
23211143d458SBrian Gix 		break;
23221143d458SBrian Gix 
2323eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2324eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2325eb9d91f5SAndre Guedes 		break;
2326eb9d91f5SAndre Guedes 
2327a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2328a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2329a7a595f6SVinicius Costa Gomes 		break;
2330a7a595f6SVinicius Costa Gomes 
2331a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2332a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2333a7a595f6SVinicius Costa Gomes 		break;
2334a7a595f6SVinicius Costa Gomes 
2335f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2336f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2337f9b49306SAndre Guedes 		break;
2338f9b49306SAndre Guedes 
2339a9de9248SMarcel Holtmann 	default:
2340a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2341a9de9248SMarcel Holtmann 		break;
2342a9de9248SMarcel Holtmann 	}
2343a9de9248SMarcel Holtmann 
23446bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23456bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23466bd32326SVille Tervo 
2347a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2348a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2349a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2350c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2351a9de9248SMarcel Holtmann 	}
2352a9de9248SMarcel Holtmann }
2353a9de9248SMarcel Holtmann 
2354a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2355a9de9248SMarcel Holtmann {
2356a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2357a9de9248SMarcel Holtmann 	__u16 opcode;
2358a9de9248SMarcel Holtmann 
2359a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2360a9de9248SMarcel Holtmann 
2361a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2362a9de9248SMarcel Holtmann 
2363a9de9248SMarcel Holtmann 	switch (opcode) {
2364a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2365a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2366a9de9248SMarcel Holtmann 		break;
2367a9de9248SMarcel Holtmann 
2368a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2369a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2370a9de9248SMarcel Holtmann 		break;
2371a9de9248SMarcel Holtmann 
2372a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2373a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2374a9de9248SMarcel Holtmann 		break;
2375a9de9248SMarcel Holtmann 
2376f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2377f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2378f8558555SMarcel Holtmann 		break;
2379f8558555SMarcel Holtmann 
2380f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2381f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2382f8558555SMarcel Holtmann 		break;
2383f8558555SMarcel Holtmann 
2384a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2385a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2386a9de9248SMarcel Holtmann 		break;
2387a9de9248SMarcel Holtmann 
2388769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2389769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2390769be974SMarcel Holtmann 		break;
2391769be974SMarcel Holtmann 
2392769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2393769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2394769be974SMarcel Holtmann 		break;
2395769be974SMarcel Holtmann 
2396a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2397a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2398a9de9248SMarcel Holtmann 		break;
2399a9de9248SMarcel Holtmann 
2400a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2401a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2402a9de9248SMarcel Holtmann 		break;
2403a9de9248SMarcel Holtmann 
2404a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2405a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2406a9de9248SMarcel Holtmann 		break;
2407a9de9248SMarcel Holtmann 
24088962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
240988c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
24108962ee74SJohan Hedberg 		break;
24118962ee74SJohan Hedberg 
2412fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2413fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2414fcd89c09SVille Tervo 		break;
2415fcd89c09SVille Tervo 
2416a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2417a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2418a7a595f6SVinicius Costa Gomes 		break;
2419a7a595f6SVinicius Costa Gomes 
2420a9de9248SMarcel Holtmann 	default:
2421a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2422a9de9248SMarcel Holtmann 		break;
2423a9de9248SMarcel Holtmann 	}
2424a9de9248SMarcel Holtmann 
24256bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
24266bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24276bd32326SVille Tervo 
242810572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2429a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2430a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2431c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2432a9de9248SMarcel Holtmann 	}
2433a9de9248SMarcel Holtmann }
2434a9de9248SMarcel Holtmann 
2435a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2436a9de9248SMarcel Holtmann {
2437a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2438a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2439a9de9248SMarcel Holtmann 
2440a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2441a9de9248SMarcel Holtmann 
2442a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2443a9de9248SMarcel Holtmann 
2444a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2445a9de9248SMarcel Holtmann 	if (conn) {
2446a9de9248SMarcel Holtmann 		if (!ev->status) {
2447a9de9248SMarcel Holtmann 			if (ev->role)
2448a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2449a9de9248SMarcel Holtmann 			else
2450a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2451a9de9248SMarcel Holtmann 		}
2452a9de9248SMarcel Holtmann 
245351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2454a9de9248SMarcel Holtmann 
2455a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2456a9de9248SMarcel Holtmann 	}
2457a9de9248SMarcel Holtmann 
2458a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2459a9de9248SMarcel Holtmann }
2460a9de9248SMarcel Holtmann 
24611da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24621da177e4SLinus Torvalds {
2463a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24641da177e4SLinus Torvalds 	int i;
24651da177e4SLinus Torvalds 
246632ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
246732ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
246832ac5b9bSAndrei Emeltchenko 		return;
246932ac5b9bSAndrei Emeltchenko 	}
247032ac5b9bSAndrei Emeltchenko 
2471c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2472c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24731da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24741da177e4SLinus Torvalds 		return;
24751da177e4SLinus Torvalds 	}
24761da177e4SLinus Torvalds 
2477c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2478c5993de8SAndrei Emeltchenko 
2479613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2480613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24811da177e4SLinus Torvalds 		struct hci_conn *conn;
24821da177e4SLinus Torvalds 		__u16  handle, count;
24831da177e4SLinus Torvalds 
2484613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2485613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24861da177e4SLinus Torvalds 
24871da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2488f4280918SAndrei Emeltchenko 		if (!conn)
2489f4280918SAndrei Emeltchenko 			continue;
2490f4280918SAndrei Emeltchenko 
24911da177e4SLinus Torvalds 		conn->sent -= count;
24921da177e4SLinus Torvalds 
2493f4280918SAndrei Emeltchenko 		switch (conn->type) {
2494f4280918SAndrei Emeltchenko 		case ACL_LINK:
249570f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
249670f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24971da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2498f4280918SAndrei Emeltchenko 			break;
2499f4280918SAndrei Emeltchenko 
2500f4280918SAndrei Emeltchenko 		case LE_LINK:
25016ed58ec5SVille Tervo 			if (hdev->le_pkts) {
25026ed58ec5SVille Tervo 				hdev->le_cnt += count;
25036ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
25046ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
25056ed58ec5SVille Tervo 			} else {
25066ed58ec5SVille Tervo 				hdev->acl_cnt += count;
25076ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
25086ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
25096ed58ec5SVille Tervo 			}
2510f4280918SAndrei Emeltchenko 			break;
2511f4280918SAndrei Emeltchenko 
2512f4280918SAndrei Emeltchenko 		case SCO_LINK:
251370f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
251470f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
25155b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2516f4280918SAndrei Emeltchenko 			break;
2517f4280918SAndrei Emeltchenko 
2518f4280918SAndrei Emeltchenko 		default:
2519f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2520f4280918SAndrei Emeltchenko 			break;
25211da177e4SLinus Torvalds 		}
25221da177e4SLinus Torvalds 	}
2523a9de9248SMarcel Holtmann 
25243eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25251da177e4SLinus Torvalds }
25261da177e4SLinus Torvalds 
252725e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
252825e89e99SAndrei Emeltchenko 					   struct sk_buff *skb)
252925e89e99SAndrei Emeltchenko {
253025e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
253125e89e99SAndrei Emeltchenko 	int i;
253225e89e99SAndrei Emeltchenko 
253325e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
253425e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
253525e89e99SAndrei Emeltchenko 		return;
253625e89e99SAndrei Emeltchenko 	}
253725e89e99SAndrei Emeltchenko 
253825e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
253925e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
254025e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
254125e89e99SAndrei Emeltchenko 		return;
254225e89e99SAndrei Emeltchenko 	}
254325e89e99SAndrei Emeltchenko 
254425e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
254525e89e99SAndrei Emeltchenko 								ev->num_hndl);
254625e89e99SAndrei Emeltchenko 
254725e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
254825e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
254925e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
255025e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
255125e89e99SAndrei Emeltchenko 
255225e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
255325e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
255425e89e99SAndrei Emeltchenko 
255525e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
255625e89e99SAndrei Emeltchenko 		if (!conn)
255725e89e99SAndrei Emeltchenko 			continue;
255825e89e99SAndrei Emeltchenko 
255925e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
256025e89e99SAndrei Emeltchenko 
256125e89e99SAndrei Emeltchenko 		switch (conn->type) {
256225e89e99SAndrei Emeltchenko 		case ACL_LINK:
256325e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
256425e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
256525e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
256625e89e99SAndrei Emeltchenko 			break;
256725e89e99SAndrei Emeltchenko 
256825e89e99SAndrei Emeltchenko 		default:
256925e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
257025e89e99SAndrei Emeltchenko 			break;
257125e89e99SAndrei Emeltchenko 		}
257225e89e99SAndrei Emeltchenko 	}
257325e89e99SAndrei Emeltchenko 
257425e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
257525e89e99SAndrei Emeltchenko }
257625e89e99SAndrei Emeltchenko 
257704837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25781da177e4SLinus Torvalds {
2579a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
258004837f64SMarcel Holtmann 	struct hci_conn *conn;
25811da177e4SLinus Torvalds 
25821da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
25831da177e4SLinus Torvalds 
25841da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25851da177e4SLinus Torvalds 
258604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
258704837f64SMarcel Holtmann 	if (conn) {
258804837f64SMarcel Holtmann 		conn->mode = ev->mode;
258904837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
259004837f64SMarcel Holtmann 
259151a8efd7SJohan Hedberg 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
259204837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
259358a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
259404837f64SMarcel Holtmann 			else
259558a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
259604837f64SMarcel Holtmann 		}
2597e73439d8SMarcel Holtmann 
259851a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2599e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
260004837f64SMarcel Holtmann 	}
260104837f64SMarcel Holtmann 
260204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
260304837f64SMarcel Holtmann }
260404837f64SMarcel Holtmann 
26051da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26061da177e4SLinus Torvalds {
2607052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2608052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2609052b30b0SMarcel Holtmann 
2610a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2611052b30b0SMarcel Holtmann 
2612052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2613052b30b0SMarcel Holtmann 
2614052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2615b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2616b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2617b6f98044SWaldemar Rymarkiewicz 
2618b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2619052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2620052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2621052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2622052b30b0SMarcel Holtmann 	}
2623052b30b0SMarcel Holtmann 
2624a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
262503b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
262603b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2627a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2628a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2629a770bb5aSWaldemar Rymarkiewicz 
2630a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2631a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2632a770bb5aSWaldemar Rymarkiewicz 		else
2633a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2634a770bb5aSWaldemar Rymarkiewicz 
2635744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2636a770bb5aSWaldemar Rymarkiewicz 	}
2637980e1a53SJohan Hedberg 
2638b6f98044SWaldemar Rymarkiewicz unlock:
2639052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26401da177e4SLinus Torvalds }
26411da177e4SLinus Torvalds 
26421da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26431da177e4SLinus Torvalds {
264455ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
264555ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
264655ed8ca1SJohan Hedberg 	struct hci_conn *conn;
264755ed8ca1SJohan Hedberg 	struct link_key *key;
264855ed8ca1SJohan Hedberg 
2649a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
265055ed8ca1SJohan Hedberg 
2651a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
265255ed8ca1SJohan Hedberg 		return;
265355ed8ca1SJohan Hedberg 
265455ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
265555ed8ca1SJohan Hedberg 
265655ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
265755ed8ca1SJohan Hedberg 	if (!key) {
265855ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
265955ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
266055ed8ca1SJohan Hedberg 		goto not_found;
266155ed8ca1SJohan Hedberg 	}
266255ed8ca1SJohan Hedberg 
266355ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
266455ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
266555ed8ca1SJohan Hedberg 
2666a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2667b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
266855ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
266955ed8ca1SJohan Hedberg 		goto not_found;
267055ed8ca1SJohan Hedberg 	}
267155ed8ca1SJohan Hedberg 
267255ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
267360b83f57SWaldemar Rymarkiewicz 	if (conn) {
267460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
267560b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
267660b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
267755ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
267855ed8ca1SJohan Hedberg 			goto not_found;
267955ed8ca1SJohan Hedberg 		}
268055ed8ca1SJohan Hedberg 
268160b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
268260b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
268360b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
268460b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
268560b83f57SWaldemar Rymarkiewicz 			goto not_found;
268660b83f57SWaldemar Rymarkiewicz 		}
268760b83f57SWaldemar Rymarkiewicz 
268860b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
268960b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
269060b83f57SWaldemar Rymarkiewicz 	}
269160b83f57SWaldemar Rymarkiewicz 
269255ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
269355ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
269455ed8ca1SJohan Hedberg 
269555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
269655ed8ca1SJohan Hedberg 
269755ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
269855ed8ca1SJohan Hedberg 
269955ed8ca1SJohan Hedberg 	return;
270055ed8ca1SJohan Hedberg 
270155ed8ca1SJohan Hedberg not_found:
270255ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
270355ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
27041da177e4SLinus Torvalds }
27051da177e4SLinus Torvalds 
27061da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
27071da177e4SLinus Torvalds {
2708052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2709052b30b0SMarcel Holtmann 	struct hci_conn *conn;
271055ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2711052b30b0SMarcel Holtmann 
2712a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2713052b30b0SMarcel Holtmann 
2714052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2715052b30b0SMarcel Holtmann 
2716052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2717052b30b0SMarcel Holtmann 	if (conn) {
2718052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2719052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2720980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
272113d39315SWaldemar Rymarkiewicz 
272213d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
272313d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
272413d39315SWaldemar Rymarkiewicz 
2725052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2726052b30b0SMarcel Holtmann 	}
2727052b30b0SMarcel Holtmann 
2728a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2729d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
273055ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
273155ed8ca1SJohan Hedberg 
2732052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27331da177e4SLinus Torvalds }
27341da177e4SLinus Torvalds 
273504837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
273604837f64SMarcel Holtmann {
2737a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
273804837f64SMarcel Holtmann 	struct hci_conn *conn;
273904837f64SMarcel Holtmann 
274004837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
274104837f64SMarcel Holtmann 
274204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
274304837f64SMarcel Holtmann 
274404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27451da177e4SLinus Torvalds 	if (conn && !ev->status) {
27461da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27471da177e4SLinus Torvalds 
2748cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2749cc11b9c1SAndrei Emeltchenko 		if (ie) {
27501da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27511da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27521da177e4SLinus Torvalds 		}
27531da177e4SLinus Torvalds 	}
27541da177e4SLinus Torvalds 
27551da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27561da177e4SLinus Torvalds }
27571da177e4SLinus Torvalds 
2758a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2759a8746417SMarcel Holtmann {
2760a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2761a8746417SMarcel Holtmann 	struct hci_conn *conn;
2762a8746417SMarcel Holtmann 
2763a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2764a8746417SMarcel Holtmann 
2765a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2766a8746417SMarcel Holtmann 
2767a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2768a8746417SMarcel Holtmann 	if (conn && !ev->status)
2769a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2770a8746417SMarcel Holtmann 
2771a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2772a8746417SMarcel Holtmann }
2773a8746417SMarcel Holtmann 
277485a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
277585a1e930SMarcel Holtmann {
2776a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
277785a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
277885a1e930SMarcel Holtmann 
277985a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
278085a1e930SMarcel Holtmann 
278185a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
278285a1e930SMarcel Holtmann 
2783cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2784cc11b9c1SAndrei Emeltchenko 	if (ie) {
278585a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
278685a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
278785a1e930SMarcel Holtmann 	}
278885a1e930SMarcel Holtmann 
278985a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
279085a1e930SMarcel Holtmann }
279185a1e930SMarcel Holtmann 
2792a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2793a9de9248SMarcel Holtmann {
2794a9de9248SMarcel Holtmann 	struct inquiry_data data;
2795a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2796388fc8faSJohan Hedberg 	bool name_known, ssp;
2797a9de9248SMarcel Holtmann 
2798a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2799a9de9248SMarcel Holtmann 
2800a9de9248SMarcel Holtmann 	if (!num_rsp)
2801a9de9248SMarcel Holtmann 		return;
2802a9de9248SMarcel Holtmann 
2803a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2804a9de9248SMarcel Holtmann 
2805a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2806138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2807138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2808a9de9248SMarcel Holtmann 
2809e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2810a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2811a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2812a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2813a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2814a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2815a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2816a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
281741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28183175405bSJohan Hedberg 
28193175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2820388fc8faSJohan Hedberg 							      false, &ssp);
282148264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2822e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2823388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2824a9de9248SMarcel Holtmann 		}
2825a9de9248SMarcel Holtmann 	} else {
2826a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2827a9de9248SMarcel Holtmann 
2828e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2829a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2830a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2831a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2832a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2833a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2834a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2835a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
283641a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28373175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2838388fc8faSJohan Hedberg 							      false, &ssp);
283948264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2840e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2841388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2842a9de9248SMarcel Holtmann 		}
2843a9de9248SMarcel Holtmann 	}
2844a9de9248SMarcel Holtmann 
2845a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2846a9de9248SMarcel Holtmann }
2847a9de9248SMarcel Holtmann 
2848a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2849a9de9248SMarcel Holtmann {
285041a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
285141a96212SMarcel Holtmann 	struct hci_conn *conn;
285241a96212SMarcel Holtmann 
2853a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
285441a96212SMarcel Holtmann 
285541a96212SMarcel Holtmann 	hci_dev_lock(hdev);
285641a96212SMarcel Holtmann 
285741a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2858ccd556feSJohan Hedberg 	if (!conn)
2859ccd556feSJohan Hedberg 		goto unlock;
2860ccd556feSJohan Hedberg 
2861769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
286241a96212SMarcel Holtmann 		struct inquiry_entry *ie;
286341a96212SMarcel Holtmann 
2864cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2865cc11b9c1SAndrei Emeltchenko 		if (ie)
286602b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
286741a96212SMarcel Holtmann 
286802b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
286958a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
287041a96212SMarcel Holtmann 	}
287141a96212SMarcel Holtmann 
2872ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2873ccd556feSJohan Hedberg 		goto unlock;
2874ccd556feSJohan Hedberg 
2875127178d2SJohan Hedberg 	if (!ev->status) {
2876127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2877127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2878127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2879127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2880127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2881b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2882b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
288308c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2884b644ba33SJohan Hedberg 				      conn->dev_class);
2885392599b9SJohan Hedberg 
2886127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2887769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2888769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2889769be974SMarcel Holtmann 		hci_conn_put(conn);
2890769be974SMarcel Holtmann 	}
2891769be974SMarcel Holtmann 
2892ccd556feSJohan Hedberg unlock:
289341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2894a9de9248SMarcel Holtmann }
2895a9de9248SMarcel Holtmann 
2896a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2897a9de9248SMarcel Holtmann {
2898b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2899b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2900b6a0dc82SMarcel Holtmann 
2901b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2902b6a0dc82SMarcel Holtmann 
2903b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2904b6a0dc82SMarcel Holtmann 
2905b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
29069dc0a3afSMarcel Holtmann 	if (!conn) {
29079dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
29089dc0a3afSMarcel Holtmann 			goto unlock;
29099dc0a3afSMarcel Holtmann 
29109dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2911b6a0dc82SMarcel Holtmann 		if (!conn)
2912b6a0dc82SMarcel Holtmann 			goto unlock;
2913b6a0dc82SMarcel Holtmann 
29149dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
29159dc0a3afSMarcel Holtmann 	}
29169dc0a3afSMarcel Holtmann 
2917732547f9SMarcel Holtmann 	switch (ev->status) {
2918732547f9SMarcel Holtmann 	case 0x00:
2919732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2920732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2921732547f9SMarcel Holtmann 
29229eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2923732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2924732547f9SMarcel Holtmann 		break;
2925732547f9SMarcel Holtmann 
2926705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2927732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29281038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2929732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2930732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2931efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2932efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2933efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2934efc7688bSMarcel Holtmann 			goto unlock;
2935efc7688bSMarcel Holtmann 		}
2936732547f9SMarcel Holtmann 		/* fall through */
2937efc7688bSMarcel Holtmann 
2938732547f9SMarcel Holtmann 	default:
2939b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2940732547f9SMarcel Holtmann 		break;
2941732547f9SMarcel Holtmann 	}
2942b6a0dc82SMarcel Holtmann 
2943b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2944b6a0dc82SMarcel Holtmann 	if (ev->status)
2945b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2946b6a0dc82SMarcel Holtmann 
2947b6a0dc82SMarcel Holtmann unlock:
2948b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2949a9de9248SMarcel Holtmann }
2950a9de9248SMarcel Holtmann 
2951a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2952a9de9248SMarcel Holtmann {
2953a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2954a9de9248SMarcel Holtmann }
2955a9de9248SMarcel Holtmann 
295604837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
295704837f64SMarcel Holtmann {
2958a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
295904837f64SMarcel Holtmann 
296004837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
296104837f64SMarcel Holtmann }
296204837f64SMarcel Holtmann 
2963a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2964a9de9248SMarcel Holtmann {
2965a9de9248SMarcel Holtmann 	struct inquiry_data data;
2966a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2967a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2968a9de9248SMarcel Holtmann 
2969a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2970a9de9248SMarcel Holtmann 
2971a9de9248SMarcel Holtmann 	if (!num_rsp)
2972a9de9248SMarcel Holtmann 		return;
2973a9de9248SMarcel Holtmann 
2974a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2975a9de9248SMarcel Holtmann 
2976e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2977388fc8faSJohan Hedberg 		bool name_known, ssp;
2978561aafbcSJohan Hedberg 
2979a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2980a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2981a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2982a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2983a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2984a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2985a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
298641a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2987561aafbcSJohan Hedberg 
2988a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29894ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29904ddb1930SJohan Hedberg 						       sizeof(info->data),
29914ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
2992561aafbcSJohan Hedberg 		else
2993561aafbcSJohan Hedberg 			name_known = true;
2994561aafbcSJohan Hedberg 
2995388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
2996388fc8faSJohan Hedberg 						      &ssp);
299748264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
299804124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
299904124681SGustavo F. Padovan 				  ssp, info->data, sizeof(info->data));
3000a9de9248SMarcel Holtmann 	}
3001a9de9248SMarcel Holtmann 
3002a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3003a9de9248SMarcel Holtmann }
3004a9de9248SMarcel Holtmann 
300517fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
300617fa4b9dSJohan Hedberg {
300717fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
300817fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
300917fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
301017fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
301117fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
301217fa4b9dSJohan Hedberg 			return 0x02;
301317fa4b9dSJohan Hedberg 		else
301417fa4b9dSJohan Hedberg 			return 0x03;
301517fa4b9dSJohan Hedberg 	}
301617fa4b9dSJohan Hedberg 
301717fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
301817fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
301958797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
302017fa4b9dSJohan Hedberg 
302117fa4b9dSJohan Hedberg 	return conn->auth_type;
302217fa4b9dSJohan Hedberg }
302317fa4b9dSJohan Hedberg 
30240493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
30250493684eSMarcel Holtmann {
30260493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
30270493684eSMarcel Holtmann 	struct hci_conn *conn;
30280493684eSMarcel Holtmann 
30290493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30300493684eSMarcel Holtmann 
30310493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30320493684eSMarcel Holtmann 
30330493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
303403b555e1SJohan Hedberg 	if (!conn)
303503b555e1SJohan Hedberg 		goto unlock;
303603b555e1SJohan Hedberg 
30370493684eSMarcel Holtmann 	hci_conn_hold(conn);
30380493684eSMarcel Holtmann 
3039a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
304003b555e1SJohan Hedberg 		goto unlock;
304103b555e1SJohan Hedberg 
3042a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
304303b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
304417fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
304517fa4b9dSJohan Hedberg 
304617fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30477a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
30487a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
30497a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
30507a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
30517cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
30527cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
305317fa4b9dSJohan Hedberg 
305458a681efSJohan Hedberg 		if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
3055ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
3056ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3057ce85ee13SSzymon Janc 		else
3058ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3059ce85ee13SSzymon Janc 
306017fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
306117fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
306203b555e1SJohan Hedberg 	} else {
306303b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
306403b555e1SJohan Hedberg 
306503b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30669f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
306703b555e1SJohan Hedberg 
306803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
306903b555e1SJohan Hedberg 							sizeof(cp), &cp);
307003b555e1SJohan Hedberg 	}
307103b555e1SJohan Hedberg 
307203b555e1SJohan Hedberg unlock:
307303b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
307403b555e1SJohan Hedberg }
307503b555e1SJohan Hedberg 
307603b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
307703b555e1SJohan Hedberg {
307803b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
307903b555e1SJohan Hedberg 	struct hci_conn *conn;
308003b555e1SJohan Hedberg 
308103b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
308203b555e1SJohan Hedberg 
308303b555e1SJohan Hedberg 	hci_dev_lock(hdev);
308403b555e1SJohan Hedberg 
308503b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
308603b555e1SJohan Hedberg 	if (!conn)
308703b555e1SJohan Hedberg 		goto unlock;
308803b555e1SJohan Hedberg 
308903b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
309003b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
309158a681efSJohan Hedberg 	if (ev->oob_data)
309258a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
309303b555e1SJohan Hedberg 
309403b555e1SJohan Hedberg unlock:
30950493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
30960493684eSMarcel Holtmann }
30970493684eSMarcel Holtmann 
3098a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3099a5c29683SJohan Hedberg 							struct sk_buff *skb)
3100a5c29683SJohan Hedberg {
3101a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
310255bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
31037a828908SJohan Hedberg 	struct hci_conn *conn;
3104a5c29683SJohan Hedberg 
3105a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3106a5c29683SJohan Hedberg 
3107a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3108a5c29683SJohan Hedberg 
3109a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
31107a828908SJohan Hedberg 		goto unlock;
31117a828908SJohan Hedberg 
31127a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31137a828908SJohan Hedberg 	if (!conn)
31147a828908SJohan Hedberg 		goto unlock;
31157a828908SJohan Hedberg 
31167a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
31177a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
31187a828908SJohan Hedberg 
31197a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
31207a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
31217a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
31227a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
31237a828908SJohan Hedberg 	 * bit set. */
31247a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
31257a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
31267a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
31277a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
31287a828908SJohan Hedberg 		goto unlock;
31297a828908SJohan Hedberg 	}
31307a828908SJohan Hedberg 
31317a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
31327a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
31337a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
313455bc1a37SJohan Hedberg 
313555bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
313655bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
313755bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
313851a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
313955bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
314055bc1a37SJohan Hedberg 			confirm_hint = 1;
314155bc1a37SJohan Hedberg 			goto confirm;
314255bc1a37SJohan Hedberg 		}
314355bc1a37SJohan Hedberg 
31449f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
31459f61656aSJohan Hedberg 						hdev->auto_accept_delay);
31469f61656aSJohan Hedberg 
31479f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
31489f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
31499f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
31509f61656aSJohan Hedberg 			goto unlock;
31519f61656aSJohan Hedberg 		}
31529f61656aSJohan Hedberg 
31537a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
31547a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
31557a828908SJohan Hedberg 		goto unlock;
31567a828908SJohan Hedberg 	}
31577a828908SJohan Hedberg 
315855bc1a37SJohan Hedberg confirm:
3159272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
316055bc1a37SJohan Hedberg 				  confirm_hint);
3161a5c29683SJohan Hedberg 
31627a828908SJohan Hedberg unlock:
3163a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3164a5c29683SJohan Hedberg }
3165a5c29683SJohan Hedberg 
31661143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
31671143d458SBrian Gix 							struct sk_buff *skb)
31681143d458SBrian Gix {
31691143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
31701143d458SBrian Gix 
31711143d458SBrian Gix 	BT_DBG("%s", hdev->name);
31721143d458SBrian Gix 
31731143d458SBrian Gix 	hci_dev_lock(hdev);
31741143d458SBrian Gix 
3175a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3176272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
31771143d458SBrian Gix 
31781143d458SBrian Gix 	hci_dev_unlock(hdev);
31791143d458SBrian Gix }
31801143d458SBrian Gix 
31810493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
31820493684eSMarcel Holtmann {
31830493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
31840493684eSMarcel Holtmann 	struct hci_conn *conn;
31850493684eSMarcel Holtmann 
31860493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31870493684eSMarcel Holtmann 
31880493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31890493684eSMarcel Holtmann 
31900493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31912a611692SJohan Hedberg 	if (!conn)
31922a611692SJohan Hedberg 		goto unlock;
31932a611692SJohan Hedberg 
31942a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
31952a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
31962a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
31972a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
31982a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
319951a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3200bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3201bab73cb6SJohan Hedberg 				 ev->status);
32022a611692SJohan Hedberg 
32030493684eSMarcel Holtmann 	hci_conn_put(conn);
32040493684eSMarcel Holtmann 
32052a611692SJohan Hedberg unlock:
32060493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32070493684eSMarcel Holtmann }
32080493684eSMarcel Holtmann 
320941a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
321041a96212SMarcel Holtmann {
321141a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
321241a96212SMarcel Holtmann 	struct inquiry_entry *ie;
321341a96212SMarcel Holtmann 
321441a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
321541a96212SMarcel Holtmann 
321641a96212SMarcel Holtmann 	hci_dev_lock(hdev);
321741a96212SMarcel Holtmann 
3218cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3219cc11b9c1SAndrei Emeltchenko 	if (ie)
322002b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
322141a96212SMarcel Holtmann 
322241a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
322341a96212SMarcel Holtmann }
322441a96212SMarcel Holtmann 
32252763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
32262763eda6SSzymon Janc 						   struct sk_buff *skb)
32272763eda6SSzymon Janc {
32282763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
32292763eda6SSzymon Janc 	struct oob_data *data;
32302763eda6SSzymon Janc 
32312763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
32322763eda6SSzymon Janc 
32332763eda6SSzymon Janc 	hci_dev_lock(hdev);
32342763eda6SSzymon Janc 
3235a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3236e1ba1f15SSzymon Janc 		goto unlock;
3237e1ba1f15SSzymon Janc 
32382763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
32392763eda6SSzymon Janc 	if (data) {
32402763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
32412763eda6SSzymon Janc 
32422763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32432763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
32442763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
32452763eda6SSzymon Janc 
32462763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
32472763eda6SSzymon Janc 									&cp);
32482763eda6SSzymon Janc 	} else {
32492763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
32502763eda6SSzymon Janc 
32512763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32522763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
32532763eda6SSzymon Janc 									&cp);
32542763eda6SSzymon Janc 	}
32552763eda6SSzymon Janc 
3256e1ba1f15SSzymon Janc unlock:
32572763eda6SSzymon Janc 	hci_dev_unlock(hdev);
32582763eda6SSzymon Janc }
32592763eda6SSzymon Janc 
3260fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3261fcd89c09SVille Tervo {
3262fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3263fcd89c09SVille Tervo 	struct hci_conn *conn;
3264fcd89c09SVille Tervo 
3265fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3266fcd89c09SVille Tervo 
3267fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3268fcd89c09SVille Tervo 
3269fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3270b62f328bSVille Tervo 	if (!conn) {
3271b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3272b62f328bSVille Tervo 		if (!conn) {
3273b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3274b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3275b62f328bSVille Tervo 			return;
3276b62f328bSVille Tervo 		}
327729b7988aSAndre Guedes 
327829b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3279b62f328bSVille Tervo 	}
3280fcd89c09SVille Tervo 
3281fcd89c09SVille Tervo 	if (ev->status) {
328248264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
328348264f06SJohan Hedberg 						conn->dst_type, ev->status);
3284fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3285fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3286fcd89c09SVille Tervo 		hci_conn_del(conn);
3287fcd89c09SVille Tervo 		goto unlock;
3288fcd89c09SVille Tervo 	}
3289fcd89c09SVille Tervo 
3290b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3291b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
329295b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
329383bc71b4SVinicius Costa Gomes 
32947b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3295fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3296fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3297fcd89c09SVille Tervo 
3298fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3299fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3300fcd89c09SVille Tervo 
3301fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3302fcd89c09SVille Tervo 
3303fcd89c09SVille Tervo unlock:
3304fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3305fcd89c09SVille Tervo }
3306fcd89c09SVille Tervo 
33079aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
33089aa04c91SAndre Guedes 						struct sk_buff *skb)
33099aa04c91SAndre Guedes {
3310e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3311e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
33123c9e9195SAndre Guedes 	s8 rssi;
33139aa04c91SAndre Guedes 
33149aa04c91SAndre Guedes 	hci_dev_lock(hdev);
33159aa04c91SAndre Guedes 
3316e95beb41SAndre Guedes 	while (num_reports--) {
3317e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3318e95beb41SAndre Guedes 
33199aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
33209aa04c91SAndre Guedes 
33213c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
33223c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
332304124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
33243c9e9195SAndre Guedes 
3325e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
33269aa04c91SAndre Guedes 	}
33279aa04c91SAndre Guedes 
33289aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
33299aa04c91SAndre Guedes }
33309aa04c91SAndre Guedes 
3331a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3332a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3333a7a595f6SVinicius Costa Gomes {
3334a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3335a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3336bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3337a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3338c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3339a7a595f6SVinicius Costa Gomes 
3340e4666881SAndrei Emeltchenko 	BT_DBG("%s handle %d", hdev->name, __le16_to_cpu(ev->handle));
3341a7a595f6SVinicius Costa Gomes 
3342a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3343a7a595f6SVinicius Costa Gomes 
3344a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3345bea710feSVinicius Costa Gomes 	if (conn == NULL)
3346bea710feSVinicius Costa Gomes 		goto not_found;
3347a7a595f6SVinicius Costa Gomes 
3348bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3349bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3350bea710feSVinicius Costa Gomes 		goto not_found;
3351bea710feSVinicius Costa Gomes 
3352bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3353a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3354c9839a11SVinicius Costa Gomes 
3355c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3356c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3357a7a595f6SVinicius Costa Gomes 
3358a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3359a7a595f6SVinicius Costa Gomes 
3360c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3361c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3362c9839a11SVinicius Costa Gomes 		kfree(ltk);
3363c9839a11SVinicius Costa Gomes 	}
3364c9839a11SVinicius Costa Gomes 
3365a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3366bea710feSVinicius Costa Gomes 
3367bea710feSVinicius Costa Gomes 	return;
3368bea710feSVinicius Costa Gomes 
3369bea710feSVinicius Costa Gomes not_found:
3370bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3371bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3372bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3373a7a595f6SVinicius Costa Gomes }
3374a7a595f6SVinicius Costa Gomes 
3375fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3376fcd89c09SVille Tervo {
3377fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3378fcd89c09SVille Tervo 
3379fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3380fcd89c09SVille Tervo 
3381fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3382fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3383fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3384fcd89c09SVille Tervo 		break;
3385fcd89c09SVille Tervo 
33869aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
33879aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
33889aa04c91SAndre Guedes 		break;
33899aa04c91SAndre Guedes 
3390a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3391a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3392a7a595f6SVinicius Costa Gomes 		break;
3393a7a595f6SVinicius Costa Gomes 
3394fcd89c09SVille Tervo 	default:
3395fcd89c09SVille Tervo 		break;
3396fcd89c09SVille Tervo 	}
3397fcd89c09SVille Tervo }
3398fcd89c09SVille Tervo 
33991da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
34001da177e4SLinus Torvalds {
3401a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3402a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
34031da177e4SLinus Torvalds 
34041da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
34051da177e4SLinus Torvalds 
3406a9de9248SMarcel Holtmann 	switch (event) {
34071da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
34081da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
34091da177e4SLinus Torvalds 		break;
34101da177e4SLinus Torvalds 
34111da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
34121da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
34131da177e4SLinus Torvalds 		break;
34141da177e4SLinus Torvalds 
3415a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3416a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
341721d9e30eSMarcel Holtmann 		break;
341821d9e30eSMarcel Holtmann 
34191da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
34201da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
34211da177e4SLinus Torvalds 		break;
34221da177e4SLinus Torvalds 
34231da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
34241da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
34251da177e4SLinus Torvalds 		break;
34261da177e4SLinus Torvalds 
34271da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
34281da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
34291da177e4SLinus Torvalds 		break;
34301da177e4SLinus Torvalds 
3431a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3432a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3433a9de9248SMarcel Holtmann 		break;
3434a9de9248SMarcel Holtmann 
34351da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
34361da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
34371da177e4SLinus Torvalds 		break;
34381da177e4SLinus Torvalds 
3439a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3440a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3441a9de9248SMarcel Holtmann 		break;
3442a9de9248SMarcel Holtmann 
3443a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3444a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3445a9de9248SMarcel Holtmann 		break;
3446a9de9248SMarcel Holtmann 
3447a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3448a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3449a9de9248SMarcel Holtmann 		break;
3450a9de9248SMarcel Holtmann 
3451a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3452a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3453a9de9248SMarcel Holtmann 		break;
3454a9de9248SMarcel Holtmann 
3455a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3456a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3457a9de9248SMarcel Holtmann 		break;
3458a9de9248SMarcel Holtmann 
3459a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3460a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3461a9de9248SMarcel Holtmann 		break;
3462a9de9248SMarcel Holtmann 
3463a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3464a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3465a9de9248SMarcel Holtmann 		break;
3466a9de9248SMarcel Holtmann 
3467a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3468a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3469a9de9248SMarcel Holtmann 		break;
3470a9de9248SMarcel Holtmann 
3471a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3472a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
34731da177e4SLinus Torvalds 		break;
34741da177e4SLinus Torvalds 
34751da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
34761da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
34771da177e4SLinus Torvalds 		break;
34781da177e4SLinus Torvalds 
34791da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
34801da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
34811da177e4SLinus Torvalds 		break;
34821da177e4SLinus Torvalds 
34831da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
34841da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
34851da177e4SLinus Torvalds 		break;
34861da177e4SLinus Torvalds 
34871da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
34881da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
34891da177e4SLinus Torvalds 		break;
34901da177e4SLinus Torvalds 
3491a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3492a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3493a8746417SMarcel Holtmann 		break;
3494a8746417SMarcel Holtmann 
349585a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
349685a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
349785a1e930SMarcel Holtmann 		break;
349885a1e930SMarcel Holtmann 
3499a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3500a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3501a9de9248SMarcel Holtmann 		break;
3502a9de9248SMarcel Holtmann 
3503a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3504a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3505a9de9248SMarcel Holtmann 		break;
3506a9de9248SMarcel Holtmann 
3507a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3508a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3509a9de9248SMarcel Holtmann 		break;
3510a9de9248SMarcel Holtmann 
3511a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3512a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3513a9de9248SMarcel Holtmann 		break;
3514a9de9248SMarcel Holtmann 
351504837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
351604837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
351704837f64SMarcel Holtmann 		break;
351804837f64SMarcel Holtmann 
3519a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3520a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
35211da177e4SLinus Torvalds 		break;
35221da177e4SLinus Torvalds 
35230493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
35240493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
35250493684eSMarcel Holtmann 		break;
35260493684eSMarcel Holtmann 
352703b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
352803b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
352903b555e1SJohan Hedberg 		break;
353003b555e1SJohan Hedberg 
3531a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3532a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3533a5c29683SJohan Hedberg 		break;
3534a5c29683SJohan Hedberg 
35351143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
35361143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
35371143d458SBrian Gix 		break;
35381143d458SBrian Gix 
35390493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
35400493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
35410493684eSMarcel Holtmann 		break;
35420493684eSMarcel Holtmann 
354341a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
354441a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
354541a96212SMarcel Holtmann 		break;
354641a96212SMarcel Holtmann 
3547fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3548fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3549fcd89c09SVille Tervo 		break;
3550fcd89c09SVille Tervo 
35512763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
35522763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
35532763eda6SSzymon Janc 		break;
35542763eda6SSzymon Janc 
355525e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
355625e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
355725e89e99SAndrei Emeltchenko 		break;
355825e89e99SAndrei Emeltchenko 
35591da177e4SLinus Torvalds 	default:
3560a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
35611da177e4SLinus Torvalds 		break;
35621da177e4SLinus Torvalds 	}
35631da177e4SLinus Torvalds 
35641da177e4SLinus Torvalds 	kfree_skb(skb);
35651da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
35661da177e4SLinus Torvalds }
3567