xref: /openbmc/linux/net/bluetooth/hci_event.c (revision e4666881)
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 
11015e0452c0SAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
11025e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
11035e0452c0SAndre Guedes 		} else {
1104c599008fSAndre Guedes 			hci_dev_lock(hdev);
1105c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1106c599008fSAndre Guedes 			hci_dev_unlock(hdev);
11075e0452c0SAndre Guedes 		}
1108c599008fSAndre Guedes 
110968a8aea4SAndrei Emeltchenko 		break;
111068a8aea4SAndrei Emeltchenko 
111168a8aea4SAndrei Emeltchenko 	default:
111268a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
111368a8aea4SAndrei Emeltchenko 		break;
111435815085SAndre Guedes 	}
1115eb9d91f5SAndre Guedes }
1116eb9d91f5SAndre Guedes 
1117a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1118a7a595f6SVinicius Costa Gomes {
1119a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1120a7a595f6SVinicius Costa Gomes 
1121a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1122a7a595f6SVinicius Costa Gomes 
1123a7a595f6SVinicius Costa Gomes 	if (rp->status)
1124a7a595f6SVinicius Costa Gomes 		return;
1125a7a595f6SVinicius Costa Gomes 
1126a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1127a7a595f6SVinicius Costa Gomes }
1128a7a595f6SVinicius Costa Gomes 
1129a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1130a7a595f6SVinicius Costa Gomes {
1131a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1132a7a595f6SVinicius Costa Gomes 
1133a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1134a7a595f6SVinicius Costa Gomes 
1135a7a595f6SVinicius Costa Gomes 	if (rp->status)
1136a7a595f6SVinicius Costa Gomes 		return;
1137a7a595f6SVinicius Costa Gomes 
1138a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1139a7a595f6SVinicius Costa Gomes }
1140a7a595f6SVinicius Costa Gomes 
1141f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1142f9b49306SAndre Guedes 							struct sk_buff *skb)
1143f9b49306SAndre Guedes {
114406199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1145f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1146f9b49306SAndre Guedes 
1147f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1148f9b49306SAndre Guedes 
114906199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
11508f984dfaSJohan Hedberg 	if (!sent)
1151f9b49306SAndre Guedes 		return;
1152f9b49306SAndre Guedes 
11538f984dfaSJohan Hedberg 	if (!status) {
11548f984dfaSJohan Hedberg 		if (sent->le)
11558f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
11568f984dfaSJohan Hedberg 		else
11578f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
11588f984dfaSJohan Hedberg 	}
11598f984dfaSJohan Hedberg 
11608f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
11618f984dfaSJohan Hedberg 					!test_bit(HCI_INIT, &hdev->flags))
11628f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
11638f984dfaSJohan Hedberg 
11648f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1165f9b49306SAndre Guedes }
1166f9b49306SAndre Guedes 
1167a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1168a9de9248SMarcel Holtmann {
1169a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1170a9de9248SMarcel Holtmann 
1171a9de9248SMarcel Holtmann 	if (status) {
117223bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1173a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
117456e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1175a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11767a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
117756e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1178314b2381SJohan Hedberg 		return;
1179314b2381SJohan Hedberg 	}
1180314b2381SJohan Hedberg 
118189352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
118289352e7dSAndre Guedes 
118356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1184343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
118556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1186a9de9248SMarcel Holtmann }
1187a9de9248SMarcel Holtmann 
11881da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11891da177e4SLinus Torvalds {
1190a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11911da177e4SLinus Torvalds 	struct hci_conn *conn;
11921da177e4SLinus Torvalds 
1193a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1194a9de9248SMarcel Holtmann 
1195a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11961da177e4SLinus Torvalds 	if (!cp)
11971da177e4SLinus Torvalds 		return;
11981da177e4SLinus Torvalds 
11991da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12001da177e4SLinus Torvalds 
12011da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
12021da177e4SLinus Torvalds 
1203a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
12041da177e4SLinus Torvalds 
12051da177e4SLinus Torvalds 	if (status) {
12061da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
12074c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
12081da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
12091da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
12101da177e4SLinus Torvalds 				hci_conn_del(conn);
12114c67bc74SMarcel Holtmann 			} else
12124c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
12131da177e4SLinus Torvalds 		}
12141da177e4SLinus Torvalds 	} else {
12151da177e4SLinus Torvalds 		if (!conn) {
12161da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
12171da177e4SLinus Torvalds 			if (conn) {
1218a0c808b3SJohan Hedberg 				conn->out = true;
12191da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
12201da177e4SLinus Torvalds 			} else
1221893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12221da177e4SLinus Torvalds 		}
12231da177e4SLinus Torvalds 	}
12241da177e4SLinus Torvalds 
12251da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12261da177e4SLinus Torvalds }
12271da177e4SLinus Torvalds 
1228a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12291da177e4SLinus Torvalds {
1230a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12311da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12321da177e4SLinus Torvalds 	__u16 handle;
12331da177e4SLinus Torvalds 
1234b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1235b6a0dc82SMarcel Holtmann 
1236a9de9248SMarcel Holtmann 	if (!status)
1237a9de9248SMarcel Holtmann 		return;
1238a9de9248SMarcel Holtmann 
1239a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12401da177e4SLinus Torvalds 	if (!cp)
1241a9de9248SMarcel Holtmann 		return;
12421da177e4SLinus Torvalds 
12431da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12441da177e4SLinus Torvalds 
1245a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
12461da177e4SLinus Torvalds 
12471da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12481da177e4SLinus Torvalds 
12491da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12505a08ecceSAndrei Emeltchenko 	if (acl) {
12515a08ecceSAndrei Emeltchenko 		sco = acl->link;
12525a08ecceSAndrei Emeltchenko 		if (sco) {
12531da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12541da177e4SLinus Torvalds 
12551da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12561da177e4SLinus Torvalds 			hci_conn_del(sco);
12571da177e4SLinus Torvalds 		}
12585a08ecceSAndrei Emeltchenko 	}
12591da177e4SLinus Torvalds 
12601da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12611da177e4SLinus Torvalds }
12621da177e4SLinus Torvalds 
1263f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1264f8558555SMarcel Holtmann {
1265f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1266f8558555SMarcel Holtmann 	struct hci_conn *conn;
1267f8558555SMarcel Holtmann 
1268f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1269f8558555SMarcel Holtmann 
1270f8558555SMarcel Holtmann 	if (!status)
1271f8558555SMarcel Holtmann 		return;
1272f8558555SMarcel Holtmann 
1273f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1274f8558555SMarcel Holtmann 	if (!cp)
1275f8558555SMarcel Holtmann 		return;
1276f8558555SMarcel Holtmann 
1277f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1278f8558555SMarcel Holtmann 
1279f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1280f8558555SMarcel Holtmann 	if (conn) {
1281f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1282f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1283f8558555SMarcel Holtmann 			hci_conn_put(conn);
1284f8558555SMarcel Holtmann 		}
1285f8558555SMarcel Holtmann 	}
1286f8558555SMarcel Holtmann 
1287f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1288f8558555SMarcel Holtmann }
1289f8558555SMarcel Holtmann 
1290f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1291f8558555SMarcel Holtmann {
1292f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1293f8558555SMarcel Holtmann 	struct hci_conn *conn;
1294f8558555SMarcel Holtmann 
1295f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1296f8558555SMarcel Holtmann 
1297f8558555SMarcel Holtmann 	if (!status)
1298f8558555SMarcel Holtmann 		return;
1299f8558555SMarcel Holtmann 
1300f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1301f8558555SMarcel Holtmann 	if (!cp)
1302f8558555SMarcel Holtmann 		return;
1303f8558555SMarcel Holtmann 
1304f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1305f8558555SMarcel Holtmann 
1306f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1307f8558555SMarcel Holtmann 	if (conn) {
1308f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1309f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1310f8558555SMarcel Holtmann 			hci_conn_put(conn);
1311f8558555SMarcel Holtmann 		}
1312f8558555SMarcel Holtmann 	}
1313f8558555SMarcel Holtmann 
1314f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1315f8558555SMarcel Holtmann }
1316f8558555SMarcel Holtmann 
1317127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1318392599b9SJohan Hedberg 							struct hci_conn *conn)
1319392599b9SJohan Hedberg {
1320392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1321392599b9SJohan Hedberg 		return 0;
1322392599b9SJohan Hedberg 
1323765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1324392599b9SJohan Hedberg 		return 0;
1325392599b9SJohan Hedberg 
1326392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1327e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1328aa64a8b5SJohan Hedberg 	if (!hci_conn_ssp_enabled(conn) &&
1329e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1330e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1331392599b9SJohan Hedberg 		return 0;
1332392599b9SJohan Hedberg 
1333392599b9SJohan Hedberg 	return 1;
1334392599b9SJohan Hedberg }
1335392599b9SJohan Hedberg 
133600abfe44SGustavo F. Padovan static inline int hci_resolve_name(struct hci_dev *hdev,
133700abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
133830dc78e1SJohan Hedberg {
133930dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
134030dc78e1SJohan Hedberg 
134130dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
134230dc78e1SJohan Hedberg 
134330dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
134430dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
134530dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
134630dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
134730dc78e1SJohan Hedberg 
134830dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
134930dc78e1SJohan Hedberg }
135030dc78e1SJohan Hedberg 
1351b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
135230dc78e1SJohan Hedberg {
135330dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
135430dc78e1SJohan Hedberg 	struct inquiry_entry *e;
135530dc78e1SJohan Hedberg 
1356b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1357b644ba33SJohan Hedberg 		return false;
1358b644ba33SJohan Hedberg 
1359b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1360b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1361b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1362b644ba33SJohan Hedberg 		return true;
1363b644ba33SJohan Hedberg 	}
1364b644ba33SJohan Hedberg 
1365b644ba33SJohan Hedberg 	return false;
1366b644ba33SJohan Hedberg }
1367b644ba33SJohan Hedberg 
1368b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1369b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1370b644ba33SJohan Hedberg {
1371b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1372b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1373b644ba33SJohan Hedberg 
1374b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
137504124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
137604124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1377b644ba33SJohan Hedberg 
1378b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1379b644ba33SJohan Hedberg 		return;
1380b644ba33SJohan Hedberg 
138130dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
138230dc78e1SJohan Hedberg 		goto discov_complete;
138330dc78e1SJohan Hedberg 
138430dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
138530dc78e1SJohan Hedberg 		return;
138630dc78e1SJohan Hedberg 
138730dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
138830dc78e1SJohan Hedberg 	if (e) {
138930dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
139030dc78e1SJohan Hedberg 		list_del(&e->list);
1391b644ba33SJohan Hedberg 		if (name)
1392b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1393b644ba33SJohan Hedberg 					 e->data.rssi, name, name_len);
139430dc78e1SJohan Hedberg 	}
139530dc78e1SJohan Hedberg 
1396b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
139730dc78e1SJohan Hedberg 		return;
139830dc78e1SJohan Hedberg 
139930dc78e1SJohan Hedberg discov_complete:
140030dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
140130dc78e1SJohan Hedberg }
140230dc78e1SJohan Hedberg 
1403a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
14041da177e4SLinus Torvalds {
1405127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1406127178d2SJohan Hedberg 	struct hci_conn *conn;
1407127178d2SJohan Hedberg 
1408a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1409127178d2SJohan Hedberg 
1410127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1411127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1412127178d2SJohan Hedberg 	if (!status)
1413127178d2SJohan Hedberg 		return;
1414127178d2SJohan Hedberg 
1415127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1416127178d2SJohan Hedberg 	if (!cp)
1417127178d2SJohan Hedberg 		return;
1418127178d2SJohan Hedberg 
1419127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1420127178d2SJohan Hedberg 
1421127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1422b644ba33SJohan Hedberg 
1423b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1424b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1425b644ba33SJohan Hedberg 
142679c6c70cSJohan Hedberg 	if (!conn)
142779c6c70cSJohan Hedberg 		goto unlock;
142879c6c70cSJohan Hedberg 
142979c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
143079c6c70cSJohan Hedberg 		goto unlock;
143179c6c70cSJohan Hedberg 
143251a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1433127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1434127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1435127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1436127178d2SJohan Hedberg 	}
1437127178d2SJohan Hedberg 
143879c6c70cSJohan Hedberg unlock:
1439127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1440a9de9248SMarcel Holtmann }
14411da177e4SLinus Torvalds 
1442769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1443769be974SMarcel Holtmann {
1444769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1445769be974SMarcel Holtmann 	struct hci_conn *conn;
1446769be974SMarcel Holtmann 
1447769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1448769be974SMarcel Holtmann 
1449769be974SMarcel Holtmann 	if (!status)
1450769be974SMarcel Holtmann 		return;
1451769be974SMarcel Holtmann 
1452769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1453769be974SMarcel Holtmann 	if (!cp)
1454769be974SMarcel Holtmann 		return;
1455769be974SMarcel Holtmann 
1456769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1457769be974SMarcel Holtmann 
1458769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1459769be974SMarcel Holtmann 	if (conn) {
1460769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1461769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1462769be974SMarcel Holtmann 			hci_conn_put(conn);
1463769be974SMarcel Holtmann 		}
1464769be974SMarcel Holtmann 	}
1465769be974SMarcel Holtmann 
1466769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1467769be974SMarcel Holtmann }
1468769be974SMarcel Holtmann 
1469769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1470769be974SMarcel Holtmann {
1471769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1472769be974SMarcel Holtmann 	struct hci_conn *conn;
1473769be974SMarcel Holtmann 
1474769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1475769be974SMarcel Holtmann 
1476769be974SMarcel Holtmann 	if (!status)
1477769be974SMarcel Holtmann 		return;
1478769be974SMarcel Holtmann 
1479769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1480769be974SMarcel Holtmann 	if (!cp)
1481769be974SMarcel Holtmann 		return;
1482769be974SMarcel Holtmann 
1483769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1484769be974SMarcel Holtmann 
1485769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1486769be974SMarcel Holtmann 	if (conn) {
1487769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1488769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1489769be974SMarcel Holtmann 			hci_conn_put(conn);
1490769be974SMarcel Holtmann 		}
1491769be974SMarcel Holtmann 	}
1492769be974SMarcel Holtmann 
1493769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1494769be974SMarcel Holtmann }
1495769be974SMarcel Holtmann 
1496a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1497a9de9248SMarcel Holtmann {
1498b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1499b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1500b6a0dc82SMarcel Holtmann 	__u16 handle;
1501b6a0dc82SMarcel Holtmann 
1502a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1503b6a0dc82SMarcel Holtmann 
1504b6a0dc82SMarcel Holtmann 	if (!status)
1505b6a0dc82SMarcel Holtmann 		return;
1506b6a0dc82SMarcel Holtmann 
1507b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1508b6a0dc82SMarcel Holtmann 	if (!cp)
1509b6a0dc82SMarcel Holtmann 		return;
1510b6a0dc82SMarcel Holtmann 
1511b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1512b6a0dc82SMarcel Holtmann 
1513b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1514b6a0dc82SMarcel Holtmann 
1515b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1516b6a0dc82SMarcel Holtmann 
1517b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15185a08ecceSAndrei Emeltchenko 	if (acl) {
15195a08ecceSAndrei Emeltchenko 		sco = acl->link;
15205a08ecceSAndrei Emeltchenko 		if (sco) {
1521b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1522b6a0dc82SMarcel Holtmann 
1523b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1524b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1525b6a0dc82SMarcel Holtmann 		}
15265a08ecceSAndrei Emeltchenko 	}
1527b6a0dc82SMarcel Holtmann 
1528b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1529a9de9248SMarcel Holtmann }
1530a9de9248SMarcel Holtmann 
1531a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1532a9de9248SMarcel Holtmann {
1533a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
153404837f64SMarcel Holtmann 	struct hci_conn *conn;
153504837f64SMarcel Holtmann 
1536a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1537a9de9248SMarcel Holtmann 
1538a9de9248SMarcel Holtmann 	if (!status)
1539a9de9248SMarcel Holtmann 		return;
1540a9de9248SMarcel Holtmann 
1541a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
154204837f64SMarcel Holtmann 	if (!cp)
1543a9de9248SMarcel Holtmann 		return;
154404837f64SMarcel Holtmann 
154504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
154604837f64SMarcel Holtmann 
154704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1548e73439d8SMarcel Holtmann 	if (conn) {
154951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
155004837f64SMarcel Holtmann 
155151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1552e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1553e73439d8SMarcel Holtmann 	}
1554e73439d8SMarcel Holtmann 
155504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
155604837f64SMarcel Holtmann }
155704837f64SMarcel Holtmann 
1558a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1559a9de9248SMarcel Holtmann {
1560a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
156104837f64SMarcel Holtmann 	struct hci_conn *conn;
156204837f64SMarcel Holtmann 
1563a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1564a9de9248SMarcel Holtmann 
1565a9de9248SMarcel Holtmann 	if (!status)
1566a9de9248SMarcel Holtmann 		return;
1567a9de9248SMarcel Holtmann 
1568a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
156904837f64SMarcel Holtmann 	if (!cp)
1570a9de9248SMarcel Holtmann 		return;
157104837f64SMarcel Holtmann 
157204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
157304837f64SMarcel Holtmann 
157404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1575e73439d8SMarcel Holtmann 	if (conn) {
157651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
157704837f64SMarcel Holtmann 
157851a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1579e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1580e73439d8SMarcel Holtmann 	}
1581e73439d8SMarcel Holtmann 
158204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
158304837f64SMarcel Holtmann }
158404837f64SMarcel Holtmann 
158588c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
158688c3df13SJohan Hedberg {
158788c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
158888c3df13SJohan Hedberg 	struct hci_conn *conn;
158988c3df13SJohan Hedberg 
159088c3df13SJohan Hedberg 	if (!status)
159188c3df13SJohan Hedberg 		return;
159288c3df13SJohan Hedberg 
159388c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
159488c3df13SJohan Hedberg 	if (!cp)
159588c3df13SJohan Hedberg 		return;
159688c3df13SJohan Hedberg 
159788c3df13SJohan Hedberg 	hci_dev_lock(hdev);
159888c3df13SJohan Hedberg 
159988c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
160088c3df13SJohan Hedberg 	if (conn)
160188c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
160288c3df13SJohan Hedberg 				       conn->dst_type, status);
160388c3df13SJohan Hedberg 
160488c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
160588c3df13SJohan Hedberg }
160688c3df13SJohan Hedberg 
1607fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1608fcd89c09SVille Tervo {
1609fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1610fcd89c09SVille Tervo 	struct hci_conn *conn;
1611fcd89c09SVille Tervo 
1612fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1613fcd89c09SVille Tervo 
1614fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1615fcd89c09SVille Tervo 	if (!cp)
1616fcd89c09SVille Tervo 		return;
1617fcd89c09SVille Tervo 
1618fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1619fcd89c09SVille Tervo 
1620fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1621fcd89c09SVille Tervo 
1622fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1623fcd89c09SVille Tervo 		conn);
1624fcd89c09SVille Tervo 
1625fcd89c09SVille Tervo 	if (status) {
1626fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1627fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1628fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1629fcd89c09SVille Tervo 			hci_conn_del(conn);
1630fcd89c09SVille Tervo 		}
1631fcd89c09SVille Tervo 	} else {
1632fcd89c09SVille Tervo 		if (!conn) {
1633fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
163429b7988aSAndre Guedes 			if (conn) {
163529b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1636a0c808b3SJohan Hedberg 				conn->out = true;
163729b7988aSAndre Guedes 			} else {
1638fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1639fcd89c09SVille Tervo 			}
1640fcd89c09SVille Tervo 		}
164129b7988aSAndre Guedes 	}
1642fcd89c09SVille Tervo 
1643fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1644fcd89c09SVille Tervo }
1645fcd89c09SVille Tervo 
1646a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1647a7a595f6SVinicius Costa Gomes {
1648a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1649a7a595f6SVinicius Costa Gomes }
1650a7a595f6SVinicius Costa Gomes 
16511da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16521da177e4SLinus Torvalds {
16531da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
165430dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
165530dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16561da177e4SLinus Torvalds 
16571da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
16581da177e4SLinus Torvalds 
165923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16606bd57416SMarcel Holtmann 
1661a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
166289352e7dSAndre Guedes 
166389352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
166489352e7dSAndre Guedes 		return;
166589352e7dSAndre Guedes 
1666a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
166730dc78e1SJohan Hedberg 		return;
166830dc78e1SJohan Hedberg 
166956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
167030dc78e1SJohan Hedberg 
1671343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
167230dc78e1SJohan Hedberg 		goto unlock;
167330dc78e1SJohan Hedberg 
167430dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1675ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
167630dc78e1SJohan Hedberg 		goto unlock;
167730dc78e1SJohan Hedberg 	}
167830dc78e1SJohan Hedberg 
167930dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
168030dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
168130dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
168230dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
168330dc78e1SJohan Hedberg 	} else {
168430dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
168530dc78e1SJohan Hedberg 	}
168630dc78e1SJohan Hedberg 
168730dc78e1SJohan Hedberg unlock:
168856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16891da177e4SLinus Torvalds }
16901da177e4SLinus Torvalds 
16911da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16921da177e4SLinus Torvalds {
169345bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1694a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16951da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16961da177e4SLinus Torvalds 
16971da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16981da177e4SLinus Torvalds 
169945bb4bf0SMarcel Holtmann 	if (!num_rsp)
170045bb4bf0SMarcel Holtmann 		return;
170145bb4bf0SMarcel Holtmann 
17021da177e4SLinus Torvalds 	hci_dev_lock(hdev);
170345bb4bf0SMarcel Holtmann 
1704e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1705388fc8faSJohan Hedberg 		bool name_known, ssp;
17063175405bSJohan Hedberg 
17071da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
17081da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
17091da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
17101da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
17111da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
17121da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17131da177e4SLinus Torvalds 		data.rssi		= 0x00;
171441a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17153175405bSJohan Hedberg 
1716388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
171748264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
171804124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
171904124681SGustavo F. Padovan 				  0);
17201da177e4SLinus Torvalds 	}
172145bb4bf0SMarcel Holtmann 
17221da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17231da177e4SLinus Torvalds }
17241da177e4SLinus Torvalds 
1725a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17261da177e4SLinus Torvalds {
1727a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1728a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17291da177e4SLinus Torvalds 
1730a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
173145bb4bf0SMarcel Holtmann 
17321da177e4SLinus Torvalds 	hci_dev_lock(hdev);
173345bb4bf0SMarcel Holtmann 
1734a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17359499237aSMarcel Holtmann 	if (!conn) {
17369499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17379499237aSMarcel Holtmann 			goto unlock;
17389499237aSMarcel Holtmann 
17399499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1740a9de9248SMarcel Holtmann 		if (!conn)
1741a9de9248SMarcel Holtmann 			goto unlock;
174245bb4bf0SMarcel Holtmann 
17439499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17449499237aSMarcel Holtmann 	}
17459499237aSMarcel Holtmann 
1746a9de9248SMarcel Holtmann 	if (!ev->status) {
1747a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1748769be974SMarcel Holtmann 
1749769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1750769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1751769be974SMarcel Holtmann 			hci_conn_hold(conn);
1752052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1753769be974SMarcel Holtmann 		} else
1754a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1755a9de9248SMarcel Holtmann 
17569eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
17577d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17587d0db0a3SMarcel Holtmann 
1759a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1760a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1761a9de9248SMarcel Holtmann 
1762a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1763a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1764a9de9248SMarcel Holtmann 
1765a9de9248SMarcel Holtmann 		/* Get remote features */
1766a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1767a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1768a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1769769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1770769be974SMarcel Holtmann 				     sizeof(cp), &cp);
177145bb4bf0SMarcel Holtmann 		}
1772a9de9248SMarcel Holtmann 
1773a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1774d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1775a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1776a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1777a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
177804124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
177904124681SGustavo F. Padovan 				     &cp);
1780a9de9248SMarcel Holtmann 		}
178117d5c04cSJohan Hedberg 	} else {
1782a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
178317d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1784744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
178548264f06SJohan Hedberg 					    conn->dst_type, ev->status);
178617d5c04cSJohan Hedberg 	}
178745bb4bf0SMarcel Holtmann 
1788e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1789e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
179045bb4bf0SMarcel Holtmann 
1791769be974SMarcel Holtmann 	if (ev->status) {
1792a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1793a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1794c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1795c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1796a9de9248SMarcel Holtmann 
1797a9de9248SMarcel Holtmann unlock:
17981da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1799a9de9248SMarcel Holtmann 
1800a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
18011da177e4SLinus Torvalds }
18021da177e4SLinus Torvalds 
18031da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18041da177e4SLinus Torvalds {
1805a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
18061da177e4SLinus Torvalds 	int mask = hdev->link_mode;
18071da177e4SLinus Torvalds 
1808a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
18091da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
18101da177e4SLinus Torvalds 
18111da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
18121da177e4SLinus Torvalds 
1813138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1814138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
18151da177e4SLinus Torvalds 		/* Connection accepted */
1816c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
18171da177e4SLinus Torvalds 		struct hci_conn *conn;
18181da177e4SLinus Torvalds 
18191da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1820b6a0dc82SMarcel Holtmann 
1821cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1822cc11b9c1SAndrei Emeltchenko 		if (ie)
1823c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1824c7bdd502SMarcel Holtmann 
18251da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
18261da177e4SLinus Torvalds 		if (!conn) {
1827cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1828cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1829893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
18301da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
18311da177e4SLinus Torvalds 				return;
18321da177e4SLinus Torvalds 			}
18331da177e4SLinus Torvalds 		}
1834b6a0dc82SMarcel Holtmann 
18351da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
18361da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1837b6a0dc82SMarcel Holtmann 
18381da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
18391da177e4SLinus Torvalds 
1840b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1841b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1842b6a0dc82SMarcel Holtmann 
18431da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
18441da177e4SLinus Torvalds 
18451da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
18461da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
18471da177e4SLinus Torvalds 			else
18481da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
18491da177e4SLinus Torvalds 
185004124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
185104124681SGustavo F. Padovan 				     &cp);
1852b6a0dc82SMarcel Holtmann 		} else {
1853b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1854b6a0dc82SMarcel Holtmann 
1855b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1856a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1857b6a0dc82SMarcel Holtmann 
1858b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1859b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1860b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1861b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1862b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1863b6a0dc82SMarcel Holtmann 
1864b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1865b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
1866b6a0dc82SMarcel Holtmann 		}
18671da177e4SLinus Torvalds 	} else {
18681da177e4SLinus Torvalds 		/* Connection rejected */
18691da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18701da177e4SLinus Torvalds 
18711da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18729f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1873a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18741da177e4SLinus Torvalds 	}
18751da177e4SLinus Torvalds }
18761da177e4SLinus Torvalds 
18771da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18781da177e4SLinus Torvalds {
1879a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
188004837f64SMarcel Holtmann 	struct hci_conn *conn;
18811da177e4SLinus Torvalds 
18821da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
18831da177e4SLinus Torvalds 
18841da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18851da177e4SLinus Torvalds 
188604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1887f7520543SJohan Hedberg 	if (!conn)
1888f7520543SJohan Hedberg 		goto unlock;
1889f7520543SJohan Hedberg 
189037d9ef76SJohan Hedberg 	if (ev->status == 0)
18911da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
18927d0db0a3SMarcel Holtmann 
1893b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1894b644ba33SJohan Hedberg 			(conn->type == ACL_LINK || conn->type == LE_LINK)) {
189537d9ef76SJohan Hedberg 		if (ev->status != 0)
189688c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
189788c3df13SJohan Hedberg 						conn->dst_type, ev->status);
189837d9ef76SJohan Hedberg 		else
1899afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
190048264f06SJohan Hedberg 						 conn->dst_type);
190137d9ef76SJohan Hedberg 	}
1902f7520543SJohan Hedberg 
190337d9ef76SJohan Hedberg 	if (ev->status == 0) {
19046ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
19056ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
19062950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
19071da177e4SLinus Torvalds 		hci_conn_del(conn);
190837d9ef76SJohan Hedberg 	}
19091da177e4SLinus Torvalds 
1910f7520543SJohan Hedberg unlock:
19111da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19121da177e4SLinus Torvalds }
19131da177e4SLinus Torvalds 
1914a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1915a9de9248SMarcel Holtmann {
1916a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1917a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1918a9de9248SMarcel Holtmann 
1919a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1920a9de9248SMarcel Holtmann 
1921a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1922a9de9248SMarcel Holtmann 
1923a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1924d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1925d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1926d7556e20SWaldemar Rymarkiewicz 
1927765c2a96SJohan Hedberg 	if (!ev->status) {
1928aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
192951a8efd7SJohan Hedberg 				test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1930d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
193119f8def0SWaldemar Rymarkiewicz 		} else {
1932a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1933765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
193419f8def0SWaldemar Rymarkiewicz 		}
19352a611692SJohan Hedberg 	} else {
1936bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1937bab73cb6SJohan Hedberg 				 ev->status);
19382a611692SJohan Hedberg 	}
1939a9de9248SMarcel Holtmann 
194051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
194151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1942a9de9248SMarcel Holtmann 
1943f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1944aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1945f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1946f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1947f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1948d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1949d7556e20SWaldemar Rymarkiewicz 									&cp);
1950f8558555SMarcel Holtmann 		} else {
1951f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1952f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1953f8558555SMarcel Holtmann 			hci_conn_put(conn);
1954f8558555SMarcel Holtmann 		}
1955052b30b0SMarcel Holtmann 	} else {
1956a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1957a9de9248SMarcel Holtmann 
1958052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1959052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1960052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1961052b30b0SMarcel Holtmann 	}
1962052b30b0SMarcel Holtmann 
196351a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1964a9de9248SMarcel Holtmann 		if (!ev->status) {
1965a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1966f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1967f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1968d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1969d7556e20SWaldemar Rymarkiewicz 									&cp);
1970a9de9248SMarcel Holtmann 		} else {
197151a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1972a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1973a9de9248SMarcel Holtmann 		}
1974a9de9248SMarcel Holtmann 	}
1975a9de9248SMarcel Holtmann 
1976d7556e20SWaldemar Rymarkiewicz unlock:
1977a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1978a9de9248SMarcel Holtmann }
1979a9de9248SMarcel Holtmann 
1980a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1981a9de9248SMarcel Holtmann {
1982127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1983127178d2SJohan Hedberg 	struct hci_conn *conn;
1984127178d2SJohan Hedberg 
1985a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1986a9de9248SMarcel Holtmann 
1987a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1988127178d2SJohan Hedberg 
1989127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1990127178d2SJohan Hedberg 
1991127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1992b644ba33SJohan Hedberg 
1993b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1994b644ba33SJohan Hedberg 		goto check_auth;
1995b644ba33SJohan Hedberg 
1996b644ba33SJohan Hedberg 	if (ev->status == 0)
1997b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1998b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1999b644ba33SJohan Hedberg 	else
2000b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2001b644ba33SJohan Hedberg 
2002b644ba33SJohan Hedberg check_auth:
200379c6c70cSJohan Hedberg 	if (!conn)
200479c6c70cSJohan Hedberg 		goto unlock;
200579c6c70cSJohan Hedberg 
200679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
200779c6c70cSJohan Hedberg 		goto unlock;
200879c6c70cSJohan Hedberg 
200951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2010127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2011127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2012127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2013127178d2SJohan Hedberg 	}
2014127178d2SJohan Hedberg 
201579c6c70cSJohan Hedberg unlock:
2016127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2017a9de9248SMarcel Holtmann }
2018a9de9248SMarcel Holtmann 
2019a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2020a9de9248SMarcel Holtmann {
2021a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2022a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2023a9de9248SMarcel Holtmann 
2024a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2025a9de9248SMarcel Holtmann 
2026a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2027a9de9248SMarcel Holtmann 
2028a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2029a9de9248SMarcel Holtmann 	if (conn) {
2030a9de9248SMarcel Holtmann 		if (!ev->status) {
2031ae293196SMarcel Holtmann 			if (ev->encrypt) {
2032ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2033ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2034a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2035da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2036ae293196SMarcel Holtmann 			} else
2037a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2038a9de9248SMarcel Holtmann 		}
2039a9de9248SMarcel Holtmann 
204051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2041a9de9248SMarcel Holtmann 
2042f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2043f8558555SMarcel Holtmann 			if (!ev->status)
2044f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2045f8558555SMarcel Holtmann 
2046f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2047f8558555SMarcel Holtmann 			hci_conn_put(conn);
2048f8558555SMarcel Holtmann 		} else
2049a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2050a9de9248SMarcel Holtmann 	}
2051a9de9248SMarcel Holtmann 
2052a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2053a9de9248SMarcel Holtmann }
2054a9de9248SMarcel Holtmann 
2055a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2056a9de9248SMarcel Holtmann {
2057a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2058a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2059a9de9248SMarcel Holtmann 
2060a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2061a9de9248SMarcel Holtmann 
2062a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2063a9de9248SMarcel Holtmann 
2064a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2065a9de9248SMarcel Holtmann 	if (conn) {
2066a9de9248SMarcel Holtmann 		if (!ev->status)
2067a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2068a9de9248SMarcel Holtmann 
206951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2070a9de9248SMarcel Holtmann 
2071a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2072a9de9248SMarcel Holtmann 	}
2073a9de9248SMarcel Holtmann 
2074a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2075a9de9248SMarcel Holtmann }
2076a9de9248SMarcel Holtmann 
2077a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2078a9de9248SMarcel Holtmann {
2079a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2080a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2081a9de9248SMarcel Holtmann 
2082a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2083a9de9248SMarcel Holtmann 
2084a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2085a9de9248SMarcel Holtmann 
2086a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2087ccd556feSJohan Hedberg 	if (!conn)
2088ccd556feSJohan Hedberg 		goto unlock;
2089ccd556feSJohan Hedberg 
2090769be974SMarcel Holtmann 	if (!ev->status)
2091a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2092a9de9248SMarcel Holtmann 
2093ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2094ccd556feSJohan Hedberg 		goto unlock;
2095ccd556feSJohan Hedberg 
2096ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2097769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2098769be974SMarcel Holtmann 		cp.handle = ev->handle;
2099769be974SMarcel Holtmann 		cp.page = 0x01;
2100ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2101769be974SMarcel Holtmann 							sizeof(cp), &cp);
2102392599b9SJohan Hedberg 		goto unlock;
2103392599b9SJohan Hedberg 	}
2104392599b9SJohan Hedberg 
2105127178d2SJohan Hedberg 	if (!ev->status) {
2106127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2107127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2108127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2109127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2110127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2111b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2112b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
211308c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2114b644ba33SJohan Hedberg 				      conn->dev_class);
2115392599b9SJohan Hedberg 
2116127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2117769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2118769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2119769be974SMarcel Holtmann 		hci_conn_put(conn);
2120769be974SMarcel Holtmann 	}
2121769be974SMarcel Holtmann 
2122ccd556feSJohan Hedberg unlock:
2123a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2124a9de9248SMarcel Holtmann }
2125a9de9248SMarcel Holtmann 
2126a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2127a9de9248SMarcel Holtmann {
2128a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2129a9de9248SMarcel Holtmann }
2130a9de9248SMarcel Holtmann 
2131a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2132a9de9248SMarcel Holtmann {
2133a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2134a9de9248SMarcel Holtmann }
2135a9de9248SMarcel Holtmann 
2136a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2137a9de9248SMarcel Holtmann {
2138a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2139a9de9248SMarcel Holtmann 	__u16 opcode;
2140a9de9248SMarcel Holtmann 
2141a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2142a9de9248SMarcel Holtmann 
2143a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2144a9de9248SMarcel Holtmann 
2145a9de9248SMarcel Holtmann 	switch (opcode) {
2146a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2147a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2148a9de9248SMarcel Holtmann 		break;
2149a9de9248SMarcel Holtmann 
2150a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2151a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2152a9de9248SMarcel Holtmann 		break;
2153a9de9248SMarcel Holtmann 
2154a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2155a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2156a9de9248SMarcel Holtmann 		break;
2157a9de9248SMarcel Holtmann 
2158a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2159a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2160a9de9248SMarcel Holtmann 		break;
2161a9de9248SMarcel Holtmann 
2162e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2163e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2164e4e8e37cSMarcel Holtmann 		break;
2165e4e8e37cSMarcel Holtmann 
2166a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2167a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2168a9de9248SMarcel Holtmann 		break;
2169a9de9248SMarcel Holtmann 
2170e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2171e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2172e4e8e37cSMarcel Holtmann 		break;
2173e4e8e37cSMarcel Holtmann 
2174e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2175e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2176e4e8e37cSMarcel Holtmann 		break;
2177e4e8e37cSMarcel Holtmann 
2178a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2179a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2180a9de9248SMarcel Holtmann 		break;
2181a9de9248SMarcel Holtmann 
2182a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2183a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2184a9de9248SMarcel Holtmann 		break;
2185a9de9248SMarcel Holtmann 
2186a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2187a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2188a9de9248SMarcel Holtmann 		break;
2189a9de9248SMarcel Holtmann 
2190a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2191a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2192a9de9248SMarcel Holtmann 		break;
2193a9de9248SMarcel Holtmann 
2194a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2195a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2196a9de9248SMarcel Holtmann 		break;
2197a9de9248SMarcel Holtmann 
2198a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2199a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2200a9de9248SMarcel Holtmann 		break;
2201a9de9248SMarcel Holtmann 
2202a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2203a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2204a9de9248SMarcel Holtmann 		break;
2205a9de9248SMarcel Holtmann 
2206a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2207a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2208a9de9248SMarcel Holtmann 		break;
2209a9de9248SMarcel Holtmann 
2210a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2211a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2212a9de9248SMarcel Holtmann 		break;
2213a9de9248SMarcel Holtmann 
2214a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2215a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2216a9de9248SMarcel Holtmann 		break;
2217a9de9248SMarcel Holtmann 
2218a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2219a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2220a9de9248SMarcel Holtmann 		break;
2221a9de9248SMarcel Holtmann 
2222333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2223333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2224333140b5SMarcel Holtmann 		break;
2225333140b5SMarcel Holtmann 
2226a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2227a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2228a9de9248SMarcel Holtmann 		break;
2229a9de9248SMarcel Holtmann 
2230a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2231a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2232a9de9248SMarcel Holtmann 		break;
2233a9de9248SMarcel Holtmann 
2234a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2235a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2236a9de9248SMarcel Holtmann 		break;
2237a9de9248SMarcel Holtmann 
2238971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2239971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2240971e3a4bSAndre Guedes 		break;
2241971e3a4bSAndre Guedes 
2242a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2243a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2244a9de9248SMarcel Holtmann 		break;
2245a9de9248SMarcel Holtmann 
2246a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2247a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2248a9de9248SMarcel Holtmann 		break;
2249a9de9248SMarcel Holtmann 
2250350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2251350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2252350ee4cfSAndrei Emeltchenko 		break;
2253350ee4cfSAndrei Emeltchenko 
225423bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
225523bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
225623bb5763SJohan Hedberg 		break;
225723bb5763SJohan Hedberg 
22581e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22591e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22601e89cffbSAndrei Emeltchenko 		break;
22611e89cffbSAndrei Emeltchenko 
2262928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2263928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2264928abaa7SAndrei Emeltchenko 		break;
2265928abaa7SAndrei Emeltchenko 
2266b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2267b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2268b0916ea0SJohan Hedberg 		break;
2269b0916ea0SJohan Hedberg 
2270d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2271d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2272d5859e22SJohan Hedberg 		break;
2273d5859e22SJohan Hedberg 
2274d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2275d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2276d5859e22SJohan Hedberg 		break;
2277d5859e22SJohan Hedberg 
2278d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2279d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2280d5859e22SJohan Hedberg 		break;
2281d5859e22SJohan Hedberg 
2282d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2283d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2284d5859e22SJohan Hedberg 		break;
2285d5859e22SJohan Hedberg 
2286980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2287980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2288980e1a53SJohan Hedberg 		break;
2289980e1a53SJohan Hedberg 
2290980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2291980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2292980e1a53SJohan Hedberg 		break;
2293980e1a53SJohan Hedberg 
2294c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2295c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2296c35938b2SSzymon Janc 		break;
2297c35938b2SSzymon Janc 
22986ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22996ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
23006ed58ec5SVille Tervo 		break;
23016ed58ec5SVille Tervo 
2302a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2303a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2304a5c29683SJohan Hedberg 		break;
2305a5c29683SJohan Hedberg 
2306a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2307a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2308a5c29683SJohan Hedberg 		break;
2309a5c29683SJohan Hedberg 
23101143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
23111143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
23121143d458SBrian Gix 		break;
23131143d458SBrian Gix 
23141143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23151143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
231616cde993SSzymon Janc 		break;
231707f7fa5dSAndre Guedes 
231807f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
231907f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
23201143d458SBrian Gix 		break;
23211143d458SBrian Gix 
2322eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2323eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2324eb9d91f5SAndre Guedes 		break;
2325eb9d91f5SAndre Guedes 
2326a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2327a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2328a7a595f6SVinicius Costa Gomes 		break;
2329a7a595f6SVinicius Costa Gomes 
2330a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2331a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2332a7a595f6SVinicius Costa Gomes 		break;
2333a7a595f6SVinicius Costa Gomes 
2334f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2335f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2336f9b49306SAndre Guedes 		break;
2337f9b49306SAndre Guedes 
2338a9de9248SMarcel Holtmann 	default:
2339a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2340a9de9248SMarcel Holtmann 		break;
2341a9de9248SMarcel Holtmann 	}
2342a9de9248SMarcel Holtmann 
23436bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23446bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23456bd32326SVille Tervo 
2346a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2347a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2348a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2349c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2350a9de9248SMarcel Holtmann 	}
2351a9de9248SMarcel Holtmann }
2352a9de9248SMarcel Holtmann 
2353a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2354a9de9248SMarcel Holtmann {
2355a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2356a9de9248SMarcel Holtmann 	__u16 opcode;
2357a9de9248SMarcel Holtmann 
2358a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2359a9de9248SMarcel Holtmann 
2360a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2361a9de9248SMarcel Holtmann 
2362a9de9248SMarcel Holtmann 	switch (opcode) {
2363a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2364a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2365a9de9248SMarcel Holtmann 		break;
2366a9de9248SMarcel Holtmann 
2367a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2368a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2369a9de9248SMarcel Holtmann 		break;
2370a9de9248SMarcel Holtmann 
2371a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2372a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2373a9de9248SMarcel Holtmann 		break;
2374a9de9248SMarcel Holtmann 
2375f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2376f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2377f8558555SMarcel Holtmann 		break;
2378f8558555SMarcel Holtmann 
2379f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2380f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2381f8558555SMarcel Holtmann 		break;
2382f8558555SMarcel Holtmann 
2383a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2384a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2385a9de9248SMarcel Holtmann 		break;
2386a9de9248SMarcel Holtmann 
2387769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2388769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2389769be974SMarcel Holtmann 		break;
2390769be974SMarcel Holtmann 
2391769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2392769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2393769be974SMarcel Holtmann 		break;
2394769be974SMarcel Holtmann 
2395a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2396a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2397a9de9248SMarcel Holtmann 		break;
2398a9de9248SMarcel Holtmann 
2399a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2400a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2401a9de9248SMarcel Holtmann 		break;
2402a9de9248SMarcel Holtmann 
2403a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2404a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2405a9de9248SMarcel Holtmann 		break;
2406a9de9248SMarcel Holtmann 
24078962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
240888c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
24098962ee74SJohan Hedberg 		break;
24108962ee74SJohan Hedberg 
2411fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2412fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2413fcd89c09SVille Tervo 		break;
2414fcd89c09SVille Tervo 
2415a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2416a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2417a7a595f6SVinicius Costa Gomes 		break;
2418a7a595f6SVinicius Costa Gomes 
2419a9de9248SMarcel Holtmann 	default:
2420a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2421a9de9248SMarcel Holtmann 		break;
2422a9de9248SMarcel Holtmann 	}
2423a9de9248SMarcel Holtmann 
24246bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
24256bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24266bd32326SVille Tervo 
242710572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2428a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2429a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2430c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2431a9de9248SMarcel Holtmann 	}
2432a9de9248SMarcel Holtmann }
2433a9de9248SMarcel Holtmann 
2434a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2435a9de9248SMarcel Holtmann {
2436a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2437a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2438a9de9248SMarcel Holtmann 
2439a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2440a9de9248SMarcel Holtmann 
2441a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2442a9de9248SMarcel Holtmann 
2443a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2444a9de9248SMarcel Holtmann 	if (conn) {
2445a9de9248SMarcel Holtmann 		if (!ev->status) {
2446a9de9248SMarcel Holtmann 			if (ev->role)
2447a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2448a9de9248SMarcel Holtmann 			else
2449a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2450a9de9248SMarcel Holtmann 		}
2451a9de9248SMarcel Holtmann 
245251a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2453a9de9248SMarcel Holtmann 
2454a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2455a9de9248SMarcel Holtmann 	}
2456a9de9248SMarcel Holtmann 
2457a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2458a9de9248SMarcel Holtmann }
2459a9de9248SMarcel Holtmann 
24601da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24611da177e4SLinus Torvalds {
2462a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24631da177e4SLinus Torvalds 	int i;
24641da177e4SLinus Torvalds 
246532ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
246632ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
246732ac5b9bSAndrei Emeltchenko 		return;
246832ac5b9bSAndrei Emeltchenko 	}
246932ac5b9bSAndrei Emeltchenko 
2470c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2471c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24721da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24731da177e4SLinus Torvalds 		return;
24741da177e4SLinus Torvalds 	}
24751da177e4SLinus Torvalds 
2476c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2477c5993de8SAndrei Emeltchenko 
2478613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2479613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24801da177e4SLinus Torvalds 		struct hci_conn *conn;
24811da177e4SLinus Torvalds 		__u16  handle, count;
24821da177e4SLinus Torvalds 
2483613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2484613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24851da177e4SLinus Torvalds 
24861da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2487f4280918SAndrei Emeltchenko 		if (!conn)
2488f4280918SAndrei Emeltchenko 			continue;
2489f4280918SAndrei Emeltchenko 
24901da177e4SLinus Torvalds 		conn->sent -= count;
24911da177e4SLinus Torvalds 
2492f4280918SAndrei Emeltchenko 		switch (conn->type) {
2493f4280918SAndrei Emeltchenko 		case ACL_LINK:
249470f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
249570f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24961da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2497f4280918SAndrei Emeltchenko 			break;
2498f4280918SAndrei Emeltchenko 
2499f4280918SAndrei Emeltchenko 		case LE_LINK:
25006ed58ec5SVille Tervo 			if (hdev->le_pkts) {
25016ed58ec5SVille Tervo 				hdev->le_cnt += count;
25026ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
25036ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
25046ed58ec5SVille Tervo 			} else {
25056ed58ec5SVille Tervo 				hdev->acl_cnt += count;
25066ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
25076ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
25086ed58ec5SVille Tervo 			}
2509f4280918SAndrei Emeltchenko 			break;
2510f4280918SAndrei Emeltchenko 
2511f4280918SAndrei Emeltchenko 		case SCO_LINK:
251270f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
251370f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
25145b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2515f4280918SAndrei Emeltchenko 			break;
2516f4280918SAndrei Emeltchenko 
2517f4280918SAndrei Emeltchenko 		default:
2518f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2519f4280918SAndrei Emeltchenko 			break;
25201da177e4SLinus Torvalds 		}
25211da177e4SLinus Torvalds 	}
2522a9de9248SMarcel Holtmann 
25233eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25241da177e4SLinus Torvalds }
25251da177e4SLinus Torvalds 
252625e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
252725e89e99SAndrei Emeltchenko 					   struct sk_buff *skb)
252825e89e99SAndrei Emeltchenko {
252925e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
253025e89e99SAndrei Emeltchenko 	int i;
253125e89e99SAndrei Emeltchenko 
253225e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
253325e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
253425e89e99SAndrei Emeltchenko 		return;
253525e89e99SAndrei Emeltchenko 	}
253625e89e99SAndrei Emeltchenko 
253725e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
253825e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
253925e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
254025e89e99SAndrei Emeltchenko 		return;
254125e89e99SAndrei Emeltchenko 	}
254225e89e99SAndrei Emeltchenko 
254325e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
254425e89e99SAndrei Emeltchenko 								ev->num_hndl);
254525e89e99SAndrei Emeltchenko 
254625e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
254725e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
254825e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
254925e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
255025e89e99SAndrei Emeltchenko 
255125e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
255225e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
255325e89e99SAndrei Emeltchenko 
255425e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
255525e89e99SAndrei Emeltchenko 		if (!conn)
255625e89e99SAndrei Emeltchenko 			continue;
255725e89e99SAndrei Emeltchenko 
255825e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
255925e89e99SAndrei Emeltchenko 
256025e89e99SAndrei Emeltchenko 		switch (conn->type) {
256125e89e99SAndrei Emeltchenko 		case ACL_LINK:
256225e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
256325e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
256425e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
256525e89e99SAndrei Emeltchenko 			break;
256625e89e99SAndrei Emeltchenko 
256725e89e99SAndrei Emeltchenko 		default:
256825e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
256925e89e99SAndrei Emeltchenko 			break;
257025e89e99SAndrei Emeltchenko 		}
257125e89e99SAndrei Emeltchenko 	}
257225e89e99SAndrei Emeltchenko 
257325e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
257425e89e99SAndrei Emeltchenko }
257525e89e99SAndrei Emeltchenko 
257604837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25771da177e4SLinus Torvalds {
2578a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
257904837f64SMarcel Holtmann 	struct hci_conn *conn;
25801da177e4SLinus Torvalds 
25811da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
25821da177e4SLinus Torvalds 
25831da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25841da177e4SLinus Torvalds 
258504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
258604837f64SMarcel Holtmann 	if (conn) {
258704837f64SMarcel Holtmann 		conn->mode = ev->mode;
258804837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
258904837f64SMarcel Holtmann 
259051a8efd7SJohan Hedberg 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
259104837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
259258a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
259304837f64SMarcel Holtmann 			else
259458a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
259504837f64SMarcel Holtmann 		}
2596e73439d8SMarcel Holtmann 
259751a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2598e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
259904837f64SMarcel Holtmann 	}
260004837f64SMarcel Holtmann 
260104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
260204837f64SMarcel Holtmann }
260304837f64SMarcel Holtmann 
26041da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26051da177e4SLinus Torvalds {
2606052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2607052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2608052b30b0SMarcel Holtmann 
2609a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2610052b30b0SMarcel Holtmann 
2611052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2612052b30b0SMarcel Holtmann 
2613052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2614b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2615b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2616b6f98044SWaldemar Rymarkiewicz 
2617b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2618052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2619052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2620052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2621052b30b0SMarcel Holtmann 	}
2622052b30b0SMarcel Holtmann 
2623a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
262403b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
262503b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2626a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2627a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2628a770bb5aSWaldemar Rymarkiewicz 
2629a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2630a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2631a770bb5aSWaldemar Rymarkiewicz 		else
2632a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2633a770bb5aSWaldemar Rymarkiewicz 
2634744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2635a770bb5aSWaldemar Rymarkiewicz 	}
2636980e1a53SJohan Hedberg 
2637b6f98044SWaldemar Rymarkiewicz unlock:
2638052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26391da177e4SLinus Torvalds }
26401da177e4SLinus Torvalds 
26411da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26421da177e4SLinus Torvalds {
264355ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
264455ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
264555ed8ca1SJohan Hedberg 	struct hci_conn *conn;
264655ed8ca1SJohan Hedberg 	struct link_key *key;
264755ed8ca1SJohan Hedberg 
2648a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
264955ed8ca1SJohan Hedberg 
2650a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
265155ed8ca1SJohan Hedberg 		return;
265255ed8ca1SJohan Hedberg 
265355ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
265455ed8ca1SJohan Hedberg 
265555ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
265655ed8ca1SJohan Hedberg 	if (!key) {
265755ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
265855ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
265955ed8ca1SJohan Hedberg 		goto not_found;
266055ed8ca1SJohan Hedberg 	}
266155ed8ca1SJohan Hedberg 
266255ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
266355ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
266455ed8ca1SJohan Hedberg 
2665a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2666b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
266755ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
266855ed8ca1SJohan Hedberg 		goto not_found;
266955ed8ca1SJohan Hedberg 	}
267055ed8ca1SJohan Hedberg 
267155ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
267260b83f57SWaldemar Rymarkiewicz 	if (conn) {
267360b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
267460b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
267560b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
267655ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
267755ed8ca1SJohan Hedberg 			goto not_found;
267855ed8ca1SJohan Hedberg 		}
267955ed8ca1SJohan Hedberg 
268060b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
268160b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
268260b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
268360b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
268460b83f57SWaldemar Rymarkiewicz 			goto not_found;
268560b83f57SWaldemar Rymarkiewicz 		}
268660b83f57SWaldemar Rymarkiewicz 
268760b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
268860b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
268960b83f57SWaldemar Rymarkiewicz 	}
269060b83f57SWaldemar Rymarkiewicz 
269155ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
269255ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
269355ed8ca1SJohan Hedberg 
269455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
269555ed8ca1SJohan Hedberg 
269655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
269755ed8ca1SJohan Hedberg 
269855ed8ca1SJohan Hedberg 	return;
269955ed8ca1SJohan Hedberg 
270055ed8ca1SJohan Hedberg not_found:
270155ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
270255ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
27031da177e4SLinus Torvalds }
27041da177e4SLinus Torvalds 
27051da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
27061da177e4SLinus Torvalds {
2707052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2708052b30b0SMarcel Holtmann 	struct hci_conn *conn;
270955ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2710052b30b0SMarcel Holtmann 
2711a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2712052b30b0SMarcel Holtmann 
2713052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2714052b30b0SMarcel Holtmann 
2715052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2716052b30b0SMarcel Holtmann 	if (conn) {
2717052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2718052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2719980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
272013d39315SWaldemar Rymarkiewicz 
272113d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
272213d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
272313d39315SWaldemar Rymarkiewicz 
2724052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2725052b30b0SMarcel Holtmann 	}
2726052b30b0SMarcel Holtmann 
2727a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2728d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
272955ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
273055ed8ca1SJohan Hedberg 
2731052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27321da177e4SLinus Torvalds }
27331da177e4SLinus Torvalds 
273404837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
273504837f64SMarcel Holtmann {
2736a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
273704837f64SMarcel Holtmann 	struct hci_conn *conn;
273804837f64SMarcel Holtmann 
273904837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
274004837f64SMarcel Holtmann 
274104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
274204837f64SMarcel Holtmann 
274304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27441da177e4SLinus Torvalds 	if (conn && !ev->status) {
27451da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27461da177e4SLinus Torvalds 
2747cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2748cc11b9c1SAndrei Emeltchenko 		if (ie) {
27491da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27501da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27511da177e4SLinus Torvalds 		}
27521da177e4SLinus Torvalds 	}
27531da177e4SLinus Torvalds 
27541da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27551da177e4SLinus Torvalds }
27561da177e4SLinus Torvalds 
2757a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2758a8746417SMarcel Holtmann {
2759a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2760a8746417SMarcel Holtmann 	struct hci_conn *conn;
2761a8746417SMarcel Holtmann 
2762a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2763a8746417SMarcel Holtmann 
2764a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2765a8746417SMarcel Holtmann 
2766a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2767a8746417SMarcel Holtmann 	if (conn && !ev->status)
2768a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2769a8746417SMarcel Holtmann 
2770a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2771a8746417SMarcel Holtmann }
2772a8746417SMarcel Holtmann 
277385a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
277485a1e930SMarcel Holtmann {
2775a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
277685a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
277785a1e930SMarcel Holtmann 
277885a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
277985a1e930SMarcel Holtmann 
278085a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
278185a1e930SMarcel Holtmann 
2782cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2783cc11b9c1SAndrei Emeltchenko 	if (ie) {
278485a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
278585a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
278685a1e930SMarcel Holtmann 	}
278785a1e930SMarcel Holtmann 
278885a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
278985a1e930SMarcel Holtmann }
279085a1e930SMarcel Holtmann 
2791a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2792a9de9248SMarcel Holtmann {
2793a9de9248SMarcel Holtmann 	struct inquiry_data data;
2794a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2795388fc8faSJohan Hedberg 	bool name_known, ssp;
2796a9de9248SMarcel Holtmann 
2797a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2798a9de9248SMarcel Holtmann 
2799a9de9248SMarcel Holtmann 	if (!num_rsp)
2800a9de9248SMarcel Holtmann 		return;
2801a9de9248SMarcel Holtmann 
2802a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2803a9de9248SMarcel Holtmann 
2804a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2805138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2806138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2807a9de9248SMarcel Holtmann 
2808e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2809a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2810a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2811a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2812a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2813a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2814a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2815a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
281641a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28173175405bSJohan Hedberg 
28183175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2819388fc8faSJohan Hedberg 							      false, &ssp);
282048264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2821e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2822388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2823a9de9248SMarcel Holtmann 		}
2824a9de9248SMarcel Holtmann 	} else {
2825a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2826a9de9248SMarcel Holtmann 
2827e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2828a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2829a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2830a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2831a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2832a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2833a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2834a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
283541a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28363175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2837388fc8faSJohan Hedberg 							      false, &ssp);
283848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2839e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2840388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2841a9de9248SMarcel Holtmann 		}
2842a9de9248SMarcel Holtmann 	}
2843a9de9248SMarcel Holtmann 
2844a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2845a9de9248SMarcel Holtmann }
2846a9de9248SMarcel Holtmann 
2847a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2848a9de9248SMarcel Holtmann {
284941a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
285041a96212SMarcel Holtmann 	struct hci_conn *conn;
285141a96212SMarcel Holtmann 
2852a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
285341a96212SMarcel Holtmann 
285441a96212SMarcel Holtmann 	hci_dev_lock(hdev);
285541a96212SMarcel Holtmann 
285641a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2857ccd556feSJohan Hedberg 	if (!conn)
2858ccd556feSJohan Hedberg 		goto unlock;
2859ccd556feSJohan Hedberg 
2860769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
286141a96212SMarcel Holtmann 		struct inquiry_entry *ie;
286241a96212SMarcel Holtmann 
2863cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2864cc11b9c1SAndrei Emeltchenko 		if (ie)
286502b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
286641a96212SMarcel Holtmann 
286702b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
286858a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
286941a96212SMarcel Holtmann 	}
287041a96212SMarcel Holtmann 
2871ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2872ccd556feSJohan Hedberg 		goto unlock;
2873ccd556feSJohan Hedberg 
2874127178d2SJohan Hedberg 	if (!ev->status) {
2875127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2876127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2877127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2878127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2879127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2880b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2881b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
288208c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2883b644ba33SJohan Hedberg 				      conn->dev_class);
2884392599b9SJohan Hedberg 
2885127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2886769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2887769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2888769be974SMarcel Holtmann 		hci_conn_put(conn);
2889769be974SMarcel Holtmann 	}
2890769be974SMarcel Holtmann 
2891ccd556feSJohan Hedberg unlock:
289241a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2893a9de9248SMarcel Holtmann }
2894a9de9248SMarcel Holtmann 
2895a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2896a9de9248SMarcel Holtmann {
2897b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2898b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2899b6a0dc82SMarcel Holtmann 
2900b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2901b6a0dc82SMarcel Holtmann 
2902b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2903b6a0dc82SMarcel Holtmann 
2904b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
29059dc0a3afSMarcel Holtmann 	if (!conn) {
29069dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
29079dc0a3afSMarcel Holtmann 			goto unlock;
29089dc0a3afSMarcel Holtmann 
29099dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2910b6a0dc82SMarcel Holtmann 		if (!conn)
2911b6a0dc82SMarcel Holtmann 			goto unlock;
2912b6a0dc82SMarcel Holtmann 
29139dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
29149dc0a3afSMarcel Holtmann 	}
29159dc0a3afSMarcel Holtmann 
2916732547f9SMarcel Holtmann 	switch (ev->status) {
2917732547f9SMarcel Holtmann 	case 0x00:
2918732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2919732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2920732547f9SMarcel Holtmann 
29219eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2922732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2923732547f9SMarcel Holtmann 		break;
2924732547f9SMarcel Holtmann 
2925705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2926732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29271038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2928732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2929732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2930efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2931efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2932efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2933efc7688bSMarcel Holtmann 			goto unlock;
2934efc7688bSMarcel Holtmann 		}
2935732547f9SMarcel Holtmann 		/* fall through */
2936efc7688bSMarcel Holtmann 
2937732547f9SMarcel Holtmann 	default:
2938b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2939732547f9SMarcel Holtmann 		break;
2940732547f9SMarcel Holtmann 	}
2941b6a0dc82SMarcel Holtmann 
2942b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2943b6a0dc82SMarcel Holtmann 	if (ev->status)
2944b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2945b6a0dc82SMarcel Holtmann 
2946b6a0dc82SMarcel Holtmann unlock:
2947b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2948a9de9248SMarcel Holtmann }
2949a9de9248SMarcel Holtmann 
2950a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2951a9de9248SMarcel Holtmann {
2952a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2953a9de9248SMarcel Holtmann }
2954a9de9248SMarcel Holtmann 
295504837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
295604837f64SMarcel Holtmann {
2957a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
295804837f64SMarcel Holtmann 
295904837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
296004837f64SMarcel Holtmann }
296104837f64SMarcel Holtmann 
2962a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
2963a9de9248SMarcel Holtmann {
2964a9de9248SMarcel Holtmann 	struct inquiry_data data;
2965a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2966a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2967a9de9248SMarcel Holtmann 
2968a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2969a9de9248SMarcel Holtmann 
2970a9de9248SMarcel Holtmann 	if (!num_rsp)
2971a9de9248SMarcel Holtmann 		return;
2972a9de9248SMarcel Holtmann 
2973a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2974a9de9248SMarcel Holtmann 
2975e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2976388fc8faSJohan Hedberg 		bool name_known, ssp;
2977561aafbcSJohan Hedberg 
2978a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2979a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2980a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2981a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2982a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2983a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2984a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
298541a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2986561aafbcSJohan Hedberg 
2987a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29884ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29894ddb1930SJohan Hedberg 						       sizeof(info->data),
29904ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
2991561aafbcSJohan Hedberg 		else
2992561aafbcSJohan Hedberg 			name_known = true;
2993561aafbcSJohan Hedberg 
2994388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
2995388fc8faSJohan Hedberg 						      &ssp);
299648264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
299704124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
299804124681SGustavo F. Padovan 				  ssp, info->data, sizeof(info->data));
2999a9de9248SMarcel Holtmann 	}
3000a9de9248SMarcel Holtmann 
3001a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3002a9de9248SMarcel Holtmann }
3003a9de9248SMarcel Holtmann 
300417fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
300517fa4b9dSJohan Hedberg {
300617fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
300717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
300817fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
300917fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
301017fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
301117fa4b9dSJohan Hedberg 			return 0x02;
301217fa4b9dSJohan Hedberg 		else
301317fa4b9dSJohan Hedberg 			return 0x03;
301417fa4b9dSJohan Hedberg 	}
301517fa4b9dSJohan Hedberg 
301617fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
301717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
301858797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
301917fa4b9dSJohan Hedberg 
302017fa4b9dSJohan Hedberg 	return conn->auth_type;
302117fa4b9dSJohan Hedberg }
302217fa4b9dSJohan Hedberg 
30230493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
30240493684eSMarcel Holtmann {
30250493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
30260493684eSMarcel Holtmann 	struct hci_conn *conn;
30270493684eSMarcel Holtmann 
30280493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30290493684eSMarcel Holtmann 
30300493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30310493684eSMarcel Holtmann 
30320493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
303303b555e1SJohan Hedberg 	if (!conn)
303403b555e1SJohan Hedberg 		goto unlock;
303503b555e1SJohan Hedberg 
30360493684eSMarcel Holtmann 	hci_conn_hold(conn);
30370493684eSMarcel Holtmann 
3038a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
303903b555e1SJohan Hedberg 		goto unlock;
304003b555e1SJohan Hedberg 
3041a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
304203b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
304317fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
304417fa4b9dSJohan Hedberg 
304517fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30467a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
30477a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
30487a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
30497a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
30507cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
30517cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
305217fa4b9dSJohan Hedberg 
305358a681efSJohan Hedberg 		if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
3054ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
3055ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3056ce85ee13SSzymon Janc 		else
3057ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3058ce85ee13SSzymon Janc 
305917fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
306017fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
306103b555e1SJohan Hedberg 	} else {
306203b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
306303b555e1SJohan Hedberg 
306403b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30659f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
306603b555e1SJohan Hedberg 
306703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
306803b555e1SJohan Hedberg 							sizeof(cp), &cp);
306903b555e1SJohan Hedberg 	}
307003b555e1SJohan Hedberg 
307103b555e1SJohan Hedberg unlock:
307203b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
307303b555e1SJohan Hedberg }
307403b555e1SJohan Hedberg 
307503b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
307603b555e1SJohan Hedberg {
307703b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
307803b555e1SJohan Hedberg 	struct hci_conn *conn;
307903b555e1SJohan Hedberg 
308003b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
308103b555e1SJohan Hedberg 
308203b555e1SJohan Hedberg 	hci_dev_lock(hdev);
308303b555e1SJohan Hedberg 
308403b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
308503b555e1SJohan Hedberg 	if (!conn)
308603b555e1SJohan Hedberg 		goto unlock;
308703b555e1SJohan Hedberg 
308803b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
308903b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
309058a681efSJohan Hedberg 	if (ev->oob_data)
309158a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
309203b555e1SJohan Hedberg 
309303b555e1SJohan Hedberg unlock:
30940493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
30950493684eSMarcel Holtmann }
30960493684eSMarcel Holtmann 
3097a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3098a5c29683SJohan Hedberg 							struct sk_buff *skb)
3099a5c29683SJohan Hedberg {
3100a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
310155bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
31027a828908SJohan Hedberg 	struct hci_conn *conn;
3103a5c29683SJohan Hedberg 
3104a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3105a5c29683SJohan Hedberg 
3106a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3107a5c29683SJohan Hedberg 
3108a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
31097a828908SJohan Hedberg 		goto unlock;
31107a828908SJohan Hedberg 
31117a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31127a828908SJohan Hedberg 	if (!conn)
31137a828908SJohan Hedberg 		goto unlock;
31147a828908SJohan Hedberg 
31157a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
31167a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
31177a828908SJohan Hedberg 
31187a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
31197a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
31207a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
31217a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
31227a828908SJohan Hedberg 	 * bit set. */
31237a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
31247a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
31257a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
31267a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
31277a828908SJohan Hedberg 		goto unlock;
31287a828908SJohan Hedberg 	}
31297a828908SJohan Hedberg 
31307a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
31317a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
31327a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
313355bc1a37SJohan Hedberg 
313455bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
313555bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
313655bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
313751a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
313855bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
313955bc1a37SJohan Hedberg 			confirm_hint = 1;
314055bc1a37SJohan Hedberg 			goto confirm;
314155bc1a37SJohan Hedberg 		}
314255bc1a37SJohan Hedberg 
31439f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
31449f61656aSJohan Hedberg 						hdev->auto_accept_delay);
31459f61656aSJohan Hedberg 
31469f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
31479f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
31489f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
31499f61656aSJohan Hedberg 			goto unlock;
31509f61656aSJohan Hedberg 		}
31519f61656aSJohan Hedberg 
31527a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
31537a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
31547a828908SJohan Hedberg 		goto unlock;
31557a828908SJohan Hedberg 	}
31567a828908SJohan Hedberg 
315755bc1a37SJohan Hedberg confirm:
3158272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
315955bc1a37SJohan Hedberg 				  confirm_hint);
3160a5c29683SJohan Hedberg 
31617a828908SJohan Hedberg unlock:
3162a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3163a5c29683SJohan Hedberg }
3164a5c29683SJohan Hedberg 
31651143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
31661143d458SBrian Gix 							struct sk_buff *skb)
31671143d458SBrian Gix {
31681143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
31691143d458SBrian Gix 
31701143d458SBrian Gix 	BT_DBG("%s", hdev->name);
31711143d458SBrian Gix 
31721143d458SBrian Gix 	hci_dev_lock(hdev);
31731143d458SBrian Gix 
3174a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3175272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
31761143d458SBrian Gix 
31771143d458SBrian Gix 	hci_dev_unlock(hdev);
31781143d458SBrian Gix }
31791143d458SBrian Gix 
31800493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
31810493684eSMarcel Holtmann {
31820493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
31830493684eSMarcel Holtmann 	struct hci_conn *conn;
31840493684eSMarcel Holtmann 
31850493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31860493684eSMarcel Holtmann 
31870493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31880493684eSMarcel Holtmann 
31890493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31902a611692SJohan Hedberg 	if (!conn)
31912a611692SJohan Hedberg 		goto unlock;
31922a611692SJohan Hedberg 
31932a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
31942a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
31952a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
31962a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
31972a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
319851a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3199bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3200bab73cb6SJohan Hedberg 				 ev->status);
32012a611692SJohan Hedberg 
32020493684eSMarcel Holtmann 	hci_conn_put(conn);
32030493684eSMarcel Holtmann 
32042a611692SJohan Hedberg unlock:
32050493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32060493684eSMarcel Holtmann }
32070493684eSMarcel Holtmann 
320841a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
320941a96212SMarcel Holtmann {
321041a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
321141a96212SMarcel Holtmann 	struct inquiry_entry *ie;
321241a96212SMarcel Holtmann 
321341a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
321441a96212SMarcel Holtmann 
321541a96212SMarcel Holtmann 	hci_dev_lock(hdev);
321641a96212SMarcel Holtmann 
3217cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3218cc11b9c1SAndrei Emeltchenko 	if (ie)
321902b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
322041a96212SMarcel Holtmann 
322141a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
322241a96212SMarcel Holtmann }
322341a96212SMarcel Holtmann 
32242763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
32252763eda6SSzymon Janc 						   struct sk_buff *skb)
32262763eda6SSzymon Janc {
32272763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
32282763eda6SSzymon Janc 	struct oob_data *data;
32292763eda6SSzymon Janc 
32302763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
32312763eda6SSzymon Janc 
32322763eda6SSzymon Janc 	hci_dev_lock(hdev);
32332763eda6SSzymon Janc 
3234a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3235e1ba1f15SSzymon Janc 		goto unlock;
3236e1ba1f15SSzymon Janc 
32372763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
32382763eda6SSzymon Janc 	if (data) {
32392763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
32402763eda6SSzymon Janc 
32412763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32422763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
32432763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
32442763eda6SSzymon Janc 
32452763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
32462763eda6SSzymon Janc 									&cp);
32472763eda6SSzymon Janc 	} else {
32482763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
32492763eda6SSzymon Janc 
32502763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32512763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
32522763eda6SSzymon Janc 									&cp);
32532763eda6SSzymon Janc 	}
32542763eda6SSzymon Janc 
3255e1ba1f15SSzymon Janc unlock:
32562763eda6SSzymon Janc 	hci_dev_unlock(hdev);
32572763eda6SSzymon Janc }
32582763eda6SSzymon Janc 
3259fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3260fcd89c09SVille Tervo {
3261fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3262fcd89c09SVille Tervo 	struct hci_conn *conn;
3263fcd89c09SVille Tervo 
3264fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3265fcd89c09SVille Tervo 
3266fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3267fcd89c09SVille Tervo 
3268fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3269b62f328bSVille Tervo 	if (!conn) {
3270b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3271b62f328bSVille Tervo 		if (!conn) {
3272b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3273b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3274b62f328bSVille Tervo 			return;
3275b62f328bSVille Tervo 		}
327629b7988aSAndre Guedes 
327729b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3278b62f328bSVille Tervo 	}
3279fcd89c09SVille Tervo 
3280fcd89c09SVille Tervo 	if (ev->status) {
328148264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
328248264f06SJohan Hedberg 						conn->dst_type, ev->status);
3283fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3284fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3285fcd89c09SVille Tervo 		hci_conn_del(conn);
3286fcd89c09SVille Tervo 		goto unlock;
3287fcd89c09SVille Tervo 	}
3288fcd89c09SVille Tervo 
3289b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3290b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
329195b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
329283bc71b4SVinicius Costa Gomes 
32937b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3294fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3295fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3296fcd89c09SVille Tervo 
3297fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3298fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3299fcd89c09SVille Tervo 
3300fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3301fcd89c09SVille Tervo 
3302fcd89c09SVille Tervo unlock:
3303fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3304fcd89c09SVille Tervo }
3305fcd89c09SVille Tervo 
33069aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
33079aa04c91SAndre Guedes 						struct sk_buff *skb)
33089aa04c91SAndre Guedes {
3309e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3310e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
33113c9e9195SAndre Guedes 	s8 rssi;
33129aa04c91SAndre Guedes 
33139aa04c91SAndre Guedes 	hci_dev_lock(hdev);
33149aa04c91SAndre Guedes 
3315e95beb41SAndre Guedes 	while (num_reports--) {
3316e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3317e95beb41SAndre Guedes 
33189aa04c91SAndre Guedes 		hci_add_adv_entry(hdev, ev);
33199aa04c91SAndre Guedes 
33203c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
33213c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
332204124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
33233c9e9195SAndre Guedes 
3324e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
33259aa04c91SAndre Guedes 	}
33269aa04c91SAndre Guedes 
33279aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
33289aa04c91SAndre Guedes }
33299aa04c91SAndre Guedes 
3330a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3331a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3332a7a595f6SVinicius Costa Gomes {
3333a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3334a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3335bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3336a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3337c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3338a7a595f6SVinicius Costa Gomes 
3339*e4666881SAndrei Emeltchenko 	BT_DBG("%s handle %d", hdev->name, __le16_to_cpu(ev->handle));
3340a7a595f6SVinicius Costa Gomes 
3341a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3342a7a595f6SVinicius Costa Gomes 
3343a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3344bea710feSVinicius Costa Gomes 	if (conn == NULL)
3345bea710feSVinicius Costa Gomes 		goto not_found;
3346a7a595f6SVinicius Costa Gomes 
3347bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3348bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3349bea710feSVinicius Costa Gomes 		goto not_found;
3350bea710feSVinicius Costa Gomes 
3351bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3352a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3353c9839a11SVinicius Costa Gomes 
3354c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3355c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3356a7a595f6SVinicius Costa Gomes 
3357a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3358a7a595f6SVinicius Costa Gomes 
3359c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3360c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3361c9839a11SVinicius Costa Gomes 		kfree(ltk);
3362c9839a11SVinicius Costa Gomes 	}
3363c9839a11SVinicius Costa Gomes 
3364a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3365bea710feSVinicius Costa Gomes 
3366bea710feSVinicius Costa Gomes 	return;
3367bea710feSVinicius Costa Gomes 
3368bea710feSVinicius Costa Gomes not_found:
3369bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3370bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3371bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3372a7a595f6SVinicius Costa Gomes }
3373a7a595f6SVinicius Costa Gomes 
3374fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3375fcd89c09SVille Tervo {
3376fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3377fcd89c09SVille Tervo 
3378fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3379fcd89c09SVille Tervo 
3380fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3381fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3382fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3383fcd89c09SVille Tervo 		break;
3384fcd89c09SVille Tervo 
33859aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
33869aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
33879aa04c91SAndre Guedes 		break;
33889aa04c91SAndre Guedes 
3389a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3390a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3391a7a595f6SVinicius Costa Gomes 		break;
3392a7a595f6SVinicius Costa Gomes 
3393fcd89c09SVille Tervo 	default:
3394fcd89c09SVille Tervo 		break;
3395fcd89c09SVille Tervo 	}
3396fcd89c09SVille Tervo }
3397fcd89c09SVille Tervo 
33981da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
33991da177e4SLinus Torvalds {
3400a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3401a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
34021da177e4SLinus Torvalds 
34031da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
34041da177e4SLinus Torvalds 
3405a9de9248SMarcel Holtmann 	switch (event) {
34061da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
34071da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
34081da177e4SLinus Torvalds 		break;
34091da177e4SLinus Torvalds 
34101da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
34111da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
34121da177e4SLinus Torvalds 		break;
34131da177e4SLinus Torvalds 
3414a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3415a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
341621d9e30eSMarcel Holtmann 		break;
341721d9e30eSMarcel Holtmann 
34181da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
34191da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
34201da177e4SLinus Torvalds 		break;
34211da177e4SLinus Torvalds 
34221da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
34231da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
34241da177e4SLinus Torvalds 		break;
34251da177e4SLinus Torvalds 
34261da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
34271da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
34281da177e4SLinus Torvalds 		break;
34291da177e4SLinus Torvalds 
3430a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3431a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3432a9de9248SMarcel Holtmann 		break;
3433a9de9248SMarcel Holtmann 
34341da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
34351da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
34361da177e4SLinus Torvalds 		break;
34371da177e4SLinus Torvalds 
3438a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3439a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3440a9de9248SMarcel Holtmann 		break;
3441a9de9248SMarcel Holtmann 
3442a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3443a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3444a9de9248SMarcel Holtmann 		break;
3445a9de9248SMarcel Holtmann 
3446a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3447a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3448a9de9248SMarcel Holtmann 		break;
3449a9de9248SMarcel Holtmann 
3450a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3451a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3452a9de9248SMarcel Holtmann 		break;
3453a9de9248SMarcel Holtmann 
3454a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3455a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3456a9de9248SMarcel Holtmann 		break;
3457a9de9248SMarcel Holtmann 
3458a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3459a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3460a9de9248SMarcel Holtmann 		break;
3461a9de9248SMarcel Holtmann 
3462a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3463a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3464a9de9248SMarcel Holtmann 		break;
3465a9de9248SMarcel Holtmann 
3466a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3467a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3468a9de9248SMarcel Holtmann 		break;
3469a9de9248SMarcel Holtmann 
3470a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3471a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
34721da177e4SLinus Torvalds 		break;
34731da177e4SLinus Torvalds 
34741da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
34751da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
34761da177e4SLinus Torvalds 		break;
34771da177e4SLinus Torvalds 
34781da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
34791da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
34801da177e4SLinus Torvalds 		break;
34811da177e4SLinus Torvalds 
34821da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
34831da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
34841da177e4SLinus Torvalds 		break;
34851da177e4SLinus Torvalds 
34861da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
34871da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
34881da177e4SLinus Torvalds 		break;
34891da177e4SLinus Torvalds 
3490a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3491a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3492a8746417SMarcel Holtmann 		break;
3493a8746417SMarcel Holtmann 
349485a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
349585a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
349685a1e930SMarcel Holtmann 		break;
349785a1e930SMarcel Holtmann 
3498a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3499a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3500a9de9248SMarcel Holtmann 		break;
3501a9de9248SMarcel Holtmann 
3502a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3503a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3504a9de9248SMarcel Holtmann 		break;
3505a9de9248SMarcel Holtmann 
3506a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3507a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3508a9de9248SMarcel Holtmann 		break;
3509a9de9248SMarcel Holtmann 
3510a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3511a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3512a9de9248SMarcel Holtmann 		break;
3513a9de9248SMarcel Holtmann 
351404837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
351504837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
351604837f64SMarcel Holtmann 		break;
351704837f64SMarcel Holtmann 
3518a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3519a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
35201da177e4SLinus Torvalds 		break;
35211da177e4SLinus Torvalds 
35220493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
35230493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
35240493684eSMarcel Holtmann 		break;
35250493684eSMarcel Holtmann 
352603b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
352703b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
352803b555e1SJohan Hedberg 		break;
352903b555e1SJohan Hedberg 
3530a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3531a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3532a5c29683SJohan Hedberg 		break;
3533a5c29683SJohan Hedberg 
35341143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
35351143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
35361143d458SBrian Gix 		break;
35371143d458SBrian Gix 
35380493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
35390493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
35400493684eSMarcel Holtmann 		break;
35410493684eSMarcel Holtmann 
354241a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
354341a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
354441a96212SMarcel Holtmann 		break;
354541a96212SMarcel Holtmann 
3546fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3547fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3548fcd89c09SVille Tervo 		break;
3549fcd89c09SVille Tervo 
35502763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
35512763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
35522763eda6SSzymon Janc 		break;
35532763eda6SSzymon Janc 
355425e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
355525e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
355625e89e99SAndrei Emeltchenko 		break;
355725e89e99SAndrei Emeltchenko 
35581da177e4SLinus Torvalds 	default:
3559a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
35601da177e4SLinus Torvalds 		break;
35611da177e4SLinus Torvalds 	}
35621da177e4SLinus Torvalds 
35631da177e4SLinus Torvalds 	kfree_skb(skb);
35641da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
35651da177e4SLinus Torvalds }
3566