xref: /openbmc/linux/net/bluetooth/hci_event.c (revision d839c813)
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 
724d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
734d93483bSAndre Guedes {
744d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
754d93483bSAndre Guedes 
764d93483bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
77ae854a70SAndre Guedes 
78ae854a70SAndre Guedes 	if (status)
79ae854a70SAndre Guedes 		return;
80ae854a70SAndre Guedes 
81ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
824d93483bSAndre Guedes }
834d93483bSAndre Guedes 
84a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
851da177e4SLinus Torvalds {
86a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
87a9de9248SMarcel Holtmann 
88a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
89a9de9248SMarcel Holtmann 
90a9de9248SMarcel Holtmann 	if (status)
91a9de9248SMarcel Holtmann 		return;
92a9de9248SMarcel Holtmann 
93ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
94ae854a70SAndre Guedes 
95a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
96a9de9248SMarcel Holtmann }
97a9de9248SMarcel Holtmann 
98a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
99a9de9248SMarcel Holtmann {
100a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
101a9de9248SMarcel Holtmann }
102a9de9248SMarcel Holtmann 
103a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
104a9de9248SMarcel Holtmann {
105a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
1061da177e4SLinus Torvalds 	struct hci_conn *conn;
1071da177e4SLinus Torvalds 
108a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1091da177e4SLinus Torvalds 
110a9de9248SMarcel Holtmann 	if (rp->status)
111a9de9248SMarcel Holtmann 		return;
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1141da177e4SLinus Torvalds 
115a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1161da177e4SLinus Torvalds 	if (conn) {
117a9de9248SMarcel Holtmann 		if (rp->role)
1181da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1191da177e4SLinus Torvalds 		else
1201da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1211da177e4SLinus Torvalds 	}
1221da177e4SLinus Torvalds 
1231da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
124a9de9248SMarcel Holtmann }
1251da177e4SLinus Torvalds 
126e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
127e4e8e37cSMarcel Holtmann {
128e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
129e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
130e4e8e37cSMarcel Holtmann 
131e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
132e4e8e37cSMarcel Holtmann 
133e4e8e37cSMarcel Holtmann 	if (rp->status)
134e4e8e37cSMarcel Holtmann 		return;
135e4e8e37cSMarcel Holtmann 
136e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
137e4e8e37cSMarcel Holtmann 
138e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
139e4e8e37cSMarcel Holtmann 	if (conn)
140e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
141e4e8e37cSMarcel Holtmann 
142e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
143e4e8e37cSMarcel Holtmann }
144e4e8e37cSMarcel Holtmann 
145a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
146a9de9248SMarcel Holtmann {
147a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
148a9de9248SMarcel Holtmann 	struct hci_conn *conn;
149a9de9248SMarcel Holtmann 	void *sent;
150a9de9248SMarcel Holtmann 
151a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
152a9de9248SMarcel Holtmann 
153a9de9248SMarcel Holtmann 	if (rp->status)
154a9de9248SMarcel Holtmann 		return;
155a9de9248SMarcel Holtmann 
156a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
15704837f64SMarcel Holtmann 	if (!sent)
158a9de9248SMarcel Holtmann 		return;
15904837f64SMarcel Holtmann 
16004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
16104837f64SMarcel Holtmann 
162a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
163e4e8e37cSMarcel Holtmann 	if (conn)
16483985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
16504837f64SMarcel Holtmann 
16604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1671da177e4SLinus Torvalds }
1681da177e4SLinus Torvalds 
169e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
170e4e8e37cSMarcel Holtmann {
171e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
172e4e8e37cSMarcel Holtmann 
173e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
174e4e8e37cSMarcel Holtmann 
175e4e8e37cSMarcel Holtmann 	if (rp->status)
176e4e8e37cSMarcel Holtmann 		return;
177e4e8e37cSMarcel Holtmann 
178e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
179e4e8e37cSMarcel Holtmann }
180e4e8e37cSMarcel Holtmann 
181e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
182e4e8e37cSMarcel Holtmann {
183e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
184e4e8e37cSMarcel Holtmann 	void *sent;
185e4e8e37cSMarcel Holtmann 
186e4e8e37cSMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
187e4e8e37cSMarcel Holtmann 
188e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
189e4e8e37cSMarcel Holtmann 	if (!sent)
190e4e8e37cSMarcel Holtmann 		return;
191e4e8e37cSMarcel Holtmann 
192e4e8e37cSMarcel Holtmann 	if (!status)
193e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
194e4e8e37cSMarcel Holtmann 
19523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
196e4e8e37cSMarcel Holtmann }
197e4e8e37cSMarcel Holtmann 
198a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1991da177e4SLinus Torvalds {
200a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
201a9de9248SMarcel Holtmann 
202a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
203a9de9248SMarcel Holtmann 
20410572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
20510572132SGustavo F. Padovan 
20623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
207d23264a8SAndre Guedes 
208a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
209ae854a70SAndre Guedes 	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
210ae854a70SAndre Guedes 			     BIT(HCI_PERIODIC_INQ));
21169775ff6SAndre Guedes 
21269775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
213a9de9248SMarcel Holtmann }
214a9de9248SMarcel Holtmann 
215a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
216a9de9248SMarcel Holtmann {
217a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2181da177e4SLinus Torvalds 	void *sent;
2191da177e4SLinus Torvalds 
220a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
2211da177e4SLinus Torvalds 
222a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2231da177e4SLinus Torvalds 	if (!sent)
224a9de9248SMarcel Holtmann 		return;
2251da177e4SLinus Torvalds 
22656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
22756e5cb86SJohan Hedberg 
228f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
229f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
23028cc7bdeSJohan Hedberg 	else if (!status)
23128cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
232f51d5b24SJohan Hedberg 
23356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
2343159d384SJohan Hedberg 
2353159d384SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
236a9de9248SMarcel Holtmann }
237a9de9248SMarcel Holtmann 
238a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
239a9de9248SMarcel Holtmann {
240a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
241a9de9248SMarcel Holtmann 
242a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
243a9de9248SMarcel Holtmann 
244a9de9248SMarcel Holtmann 	if (rp->status)
245a9de9248SMarcel Holtmann 		return;
246a9de9248SMarcel Holtmann 
247db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2481f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
249a9de9248SMarcel Holtmann }
250a9de9248SMarcel Holtmann 
251a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
252a9de9248SMarcel Holtmann {
253a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
254a9de9248SMarcel Holtmann 	void *sent;
255a9de9248SMarcel Holtmann 
256a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
257a9de9248SMarcel Holtmann 
258a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
259a9de9248SMarcel Holtmann 	if (!sent)
260a9de9248SMarcel Holtmann 		return;
2611da177e4SLinus Torvalds 
2621da177e4SLinus Torvalds 	if (!status) {
263a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
264a9de9248SMarcel Holtmann 
2651da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2661da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2671da177e4SLinus Torvalds 		else
2681da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2691da177e4SLinus Torvalds 	}
270a9de9248SMarcel Holtmann 
27133ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
27233ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
27333ef95edSJohan Hedberg 
27423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
275a9de9248SMarcel Holtmann }
2761da177e4SLinus Torvalds 
277a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
278a9de9248SMarcel Holtmann {
279a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
280a9de9248SMarcel Holtmann 	void *sent;
281a9de9248SMarcel Holtmann 
282a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
283a9de9248SMarcel Holtmann 
284a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2851da177e4SLinus Torvalds 	if (!sent)
286a9de9248SMarcel Holtmann 		return;
2871da177e4SLinus Torvalds 
2881da177e4SLinus Torvalds 	if (!status) {
289a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
290a9de9248SMarcel Holtmann 
2911da177e4SLinus Torvalds 		if (param)
2921da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2931da177e4SLinus Torvalds 		else
2941da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2951da177e4SLinus Torvalds 	}
296a9de9248SMarcel Holtmann 
29723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2981da177e4SLinus Torvalds }
2991da177e4SLinus Torvalds 
300a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
301a9de9248SMarcel Holtmann {
30236f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
30336f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
304a9de9248SMarcel Holtmann 	void *sent;
3051da177e4SLinus Torvalds 
306a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
307a9de9248SMarcel Holtmann 
308a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3091da177e4SLinus Torvalds 	if (!sent)
310a9de9248SMarcel Holtmann 		return;
3111da177e4SLinus Torvalds 
31236f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
313a9de9248SMarcel Holtmann 
31456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
31556e5cb86SJohan Hedberg 
3162d7cee58SJohan Hedberg 	if (status != 0) {
317744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3182d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3192d7cee58SJohan Hedberg 		goto done;
3202d7cee58SJohan Hedberg 	}
3212d7cee58SJohan Hedberg 
3229fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3239fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
324a9de9248SMarcel Holtmann 
32573f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3261da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3279fbcbb45SJohan Hedberg 		if (!old_iscan)
328744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
32916ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
33016ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
33116ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
33216ab91abSJohan Hedberg 									to);
33316ab91abSJohan Hedberg 		}
3349fbcbb45SJohan Hedberg 	} else if (old_iscan)
335744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3361da177e4SLinus Torvalds 
3379fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3381da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3399fbcbb45SJohan Hedberg 		if (!old_pscan)
340744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3419fbcbb45SJohan Hedberg 	} else if (old_pscan)
342744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
343a9de9248SMarcel Holtmann 
34436f7fc7eSJohan Hedberg done:
34556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
34623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3471da177e4SLinus Torvalds }
3481da177e4SLinus Torvalds 
349a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
350a9de9248SMarcel Holtmann {
351a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
352a9de9248SMarcel Holtmann 
353a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
354a9de9248SMarcel Holtmann 
355a9de9248SMarcel Holtmann 	if (rp->status)
356a9de9248SMarcel Holtmann 		return;
357a9de9248SMarcel Holtmann 
358a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
359a9de9248SMarcel Holtmann 
360a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
361a9de9248SMarcel Holtmann 		hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
362a9de9248SMarcel Holtmann }
363a9de9248SMarcel Holtmann 
364a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
365a9de9248SMarcel Holtmann {
366a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
367a9de9248SMarcel Holtmann 	void *sent;
368a9de9248SMarcel Holtmann 
369a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
370a9de9248SMarcel Holtmann 
371a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
372a9de9248SMarcel Holtmann 	if (!sent)
373a9de9248SMarcel Holtmann 		return;
374a9de9248SMarcel Holtmann 
3757f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3767f9a903cSMarcel Holtmann 
3777f9a903cSMarcel Holtmann 	if (status == 0)
378a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3797f9a903cSMarcel Holtmann 
3807f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3817f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3827f9a903cSMarcel Holtmann 
3837f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
384a9de9248SMarcel Holtmann }
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
387a9de9248SMarcel Holtmann {
388a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
389a9de9248SMarcel Holtmann 	__u16 setting;
390a9de9248SMarcel Holtmann 
391a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
392a9de9248SMarcel Holtmann 
393a9de9248SMarcel Holtmann 	if (rp->status)
394a9de9248SMarcel Holtmann 		return;
395a9de9248SMarcel Holtmann 
396a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
397a9de9248SMarcel Holtmann 
398a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
399a9de9248SMarcel Holtmann 		return;
400a9de9248SMarcel Holtmann 
401a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
402a9de9248SMarcel Holtmann 
403a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
404a9de9248SMarcel Holtmann 
4053c54711cSGustavo F. Padovan 	if (hdev->notify)
406a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
407a9de9248SMarcel Holtmann }
408a9de9248SMarcel Holtmann 
409a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
410a9de9248SMarcel Holtmann {
411a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
412f383f275SMarcel Holtmann 	__u16 setting;
413a9de9248SMarcel Holtmann 	void *sent;
414a9de9248SMarcel Holtmann 
415a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
416a9de9248SMarcel Holtmann 
417f383f275SMarcel Holtmann 	if (status)
418f383f275SMarcel Holtmann 		return;
419f383f275SMarcel Holtmann 
420a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
421a9de9248SMarcel Holtmann 	if (!sent)
422a9de9248SMarcel Holtmann 		return;
423a9de9248SMarcel Holtmann 
424f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4251da177e4SLinus Torvalds 
426f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
427f383f275SMarcel Holtmann 		return;
428f383f275SMarcel Holtmann 
4291da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4301da177e4SLinus Torvalds 
431a9de9248SMarcel Holtmann 	BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
4321da177e4SLinus Torvalds 
4333c54711cSGustavo F. Padovan 	if (hdev->notify)
4341da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4351da177e4SLinus Torvalds }
4361da177e4SLinus Torvalds 
437a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4381da177e4SLinus Torvalds {
439a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4401da177e4SLinus Torvalds 
441a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
4421da177e4SLinus Torvalds 
44323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4441143e5a6SMarcel Holtmann }
4451143e5a6SMarcel Holtmann 
446333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
447333140b5SMarcel Holtmann {
448333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
449333140b5SMarcel Holtmann 	void *sent;
450333140b5SMarcel Holtmann 
451333140b5SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
452333140b5SMarcel Holtmann 
453333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
454333140b5SMarcel Holtmann 	if (!sent)
455333140b5SMarcel Holtmann 		return;
456333140b5SMarcel Holtmann 
457c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
458c0ecddc2SJohan Hedberg 		mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
459c0ecddc2SJohan Hedberg 	else if (!status) {
46084bde9d6SJohan Hedberg 		if (*((u8 *) sent))
46184bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
46284bde9d6SJohan Hedberg 		else
46384bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
464c0ecddc2SJohan Hedberg 	}
465333140b5SMarcel Holtmann }
466333140b5SMarcel Holtmann 
467d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
468d5859e22SJohan Hedberg {
469d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
470d5859e22SJohan Hedberg 		return 2;
471d5859e22SJohan Hedberg 
472d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
473d5859e22SJohan Hedberg 		return 1;
474d5859e22SJohan Hedberg 
475d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
476d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x0757)
477d5859e22SJohan Hedberg 		return 1;
478d5859e22SJohan Hedberg 
479d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
480d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
481d5859e22SJohan Hedberg 			return 1;
482d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
483d5859e22SJohan Hedberg 			return 1;
484d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
485d5859e22SJohan Hedberg 			return 1;
486d5859e22SJohan Hedberg 	}
487d5859e22SJohan Hedberg 
488d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
489d5859e22SJohan Hedberg 						hdev->lmp_subver == 0x1805)
490d5859e22SJohan Hedberg 		return 1;
491d5859e22SJohan Hedberg 
492d5859e22SJohan Hedberg 	return 0;
493d5859e22SJohan Hedberg }
494d5859e22SJohan Hedberg 
495d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
496d5859e22SJohan Hedberg {
497d5859e22SJohan Hedberg 	u8 mode;
498d5859e22SJohan Hedberg 
499d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
500d5859e22SJohan Hedberg 
501d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
502d5859e22SJohan Hedberg }
503d5859e22SJohan Hedberg 
504d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
505d5859e22SJohan Hedberg {
506d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
507d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
508d5859e22SJohan Hedberg 	 * command otherwise */
509d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
510d5859e22SJohan Hedberg 
5116de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5126de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5135a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
5146de6c18dSVille Tervo 		return;
5156de6c18dSVille Tervo 
516d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
517d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
518d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
519d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
520d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
521d5859e22SJohan Hedberg 
522d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
523a24299e6SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
524d5859e22SJohan Hedberg 
525d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_SNIFF_SUBR)
526d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
527d5859e22SJohan Hedberg 
528d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
529d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
530d5859e22SJohan Hedberg 
531d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
532d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
533d5859e22SJohan Hedberg 
534d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_NO_FLUSH)
535d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
536d5859e22SJohan Hedberg 
537d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
538d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
539d5859e22SJohan Hedberg 
540d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
541d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
542d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
543d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
544d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
545d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
546d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
547d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
548d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
549d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
550d5859e22SJohan Hedberg 					 * Features Notification */
551d5859e22SJohan Hedberg 	}
552d5859e22SJohan Hedberg 
553d5859e22SJohan Hedberg 	if (hdev->features[4] & LMP_LE)
554d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
555d5859e22SJohan Hedberg 
556d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
557d5859e22SJohan Hedberg }
558d5859e22SJohan Hedberg 
559d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
560d5859e22SJohan Hedberg {
561e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
562e61ef499SAndrei Emeltchenko 		return;
563e61ef499SAndrei Emeltchenko 
564d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
565d5859e22SJohan Hedberg 
566d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
567d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
568d5859e22SJohan Hedberg 
56954d04dbbSJohan Hedberg 	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
57054d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
571d5859e22SJohan Hedberg 			u8 mode = 0x01;
57254d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
57354d04dbbSJohan Hedberg 				     sizeof(mode), &mode);
57454d04dbbSJohan Hedberg 		} else {
57554d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
57654d04dbbSJohan Hedberg 
57754d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
57854d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
57954d04dbbSJohan Hedberg 
58054d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
58154d04dbbSJohan Hedberg 		}
582d5859e22SJohan Hedberg 	}
583d5859e22SJohan Hedberg 
584d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
585d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
586d5859e22SJohan Hedberg 
587d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
588d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
589971e3a4bSAndre Guedes 
590971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
591971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
592971e3a4bSAndre Guedes 
593971e3a4bSAndre Guedes 		cp.page = 0x01;
59404124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
59504124681SGustavo F. Padovan 			     &cp);
596971e3a4bSAndre Guedes 	}
597e6100a25SAndre Guedes 
59847990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
59947990ea0SJohan Hedberg 		u8 enable = 1;
60004124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
60104124681SGustavo F. Padovan 			     &enable);
60247990ea0SJohan Hedberg 	}
603d5859e22SJohan Hedberg }
604d5859e22SJohan Hedberg 
605a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
606a9de9248SMarcel Holtmann {
607a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6081143e5a6SMarcel Holtmann 
609a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
6101143e5a6SMarcel Holtmann 
611a9de9248SMarcel Holtmann 	if (rp->status)
61228b8df77SAndrei Emeltchenko 		goto done;
6131143e5a6SMarcel Holtmann 
614a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
615e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
616d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
617e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
618d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6191da177e4SLinus Torvalds 
620a9de9248SMarcel Holtmann 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
621a9de9248SMarcel Holtmann 					hdev->manufacturer,
622a9de9248SMarcel Holtmann 					hdev->hci_ver, hdev->hci_rev);
623d5859e22SJohan Hedberg 
624d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
625d5859e22SJohan Hedberg 		hci_setup(hdev);
62628b8df77SAndrei Emeltchenko 
62728b8df77SAndrei Emeltchenko done:
62828b8df77SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
629d5859e22SJohan Hedberg }
630d5859e22SJohan Hedberg 
631d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
632d5859e22SJohan Hedberg {
633035100c8SAndrei Emeltchenko 	struct hci_cp_write_def_link_policy cp;
634d5859e22SJohan Hedberg 	u16 link_policy = 0;
635d5859e22SJohan Hedberg 
636d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_RSWITCH)
637d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
638d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
639d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
640d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_SNIFF)
641d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
642d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
643d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
644d5859e22SJohan Hedberg 
645035100c8SAndrei Emeltchenko 	cp.policy = cpu_to_le16(link_policy);
646035100c8SAndrei Emeltchenko 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
6471da177e4SLinus Torvalds }
6481da177e4SLinus Torvalds 
649a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
650a9de9248SMarcel Holtmann {
651a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
652a9de9248SMarcel Holtmann 
653a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
654a9de9248SMarcel Holtmann 
655a9de9248SMarcel Holtmann 	if (rp->status)
656d5859e22SJohan Hedberg 		goto done;
657a9de9248SMarcel Holtmann 
658a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
659d5859e22SJohan Hedberg 
660d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
661d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
662d5859e22SJohan Hedberg 
663d5859e22SJohan Hedberg done:
664d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
665a9de9248SMarcel Holtmann }
666a9de9248SMarcel Holtmann 
667a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
668a9de9248SMarcel Holtmann {
669a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
670a9de9248SMarcel Holtmann 
671a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
672a9de9248SMarcel Holtmann 
673a9de9248SMarcel Holtmann 	if (rp->status)
674a9de9248SMarcel Holtmann 		return;
675a9de9248SMarcel Holtmann 
676a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6771da177e4SLinus Torvalds 
6781da177e4SLinus Torvalds 	/* Adjust default settings according to features
6791da177e4SLinus Torvalds 	 * supported by device. */
680a9de9248SMarcel Holtmann 
6811da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6821da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6831da177e4SLinus Torvalds 
6841da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6851da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6861da177e4SLinus Torvalds 
6875b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6881da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6895b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6905b7f9909SMarcel Holtmann 	}
6911da177e4SLinus Torvalds 
6925b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6931da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6945b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6955b7f9909SMarcel Holtmann 	}
6965b7f9909SMarcel Holtmann 
6975b7f9909SMarcel Holtmann 	if (hdev->features[3] & LMP_ESCO)
6985b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6995b7f9909SMarcel Holtmann 
7005b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
7015b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
7025b7f9909SMarcel Holtmann 
7035b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
7045b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
7051da177e4SLinus Torvalds 
706efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
707efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
708efc7688bSMarcel Holtmann 
709efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
710efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
711efc7688bSMarcel Holtmann 
712efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
713efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
714efc7688bSMarcel Holtmann 
715a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
716a9de9248SMarcel Holtmann 					hdev->features[0], hdev->features[1],
717a9de9248SMarcel Holtmann 					hdev->features[2], hdev->features[3],
718a9de9248SMarcel Holtmann 					hdev->features[4], hdev->features[5],
719a9de9248SMarcel Holtmann 					hdev->features[6], hdev->features[7]);
7201da177e4SLinus Torvalds }
7211da177e4SLinus Torvalds 
7228f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev)
7238f984dfaSJohan Hedberg {
7248f984dfaSJohan Hedberg 	struct hci_cp_write_le_host_supported cp;
7258f984dfaSJohan Hedberg 
7268f984dfaSJohan Hedberg 	memset(&cp, 0, sizeof(cp));
7278f984dfaSJohan Hedberg 
7289d42820fSMarcel Holtmann 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
7298f984dfaSJohan Hedberg 		cp.le = 1;
7308f984dfaSJohan Hedberg 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
7318f984dfaSJohan Hedberg 	}
7328f984dfaSJohan Hedberg 
7338f984dfaSJohan Hedberg 	if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
73404124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
73504124681SGustavo F. Padovan 			     &cp);
7368f984dfaSJohan Hedberg }
7378f984dfaSJohan Hedberg 
738971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
739971e3a4bSAndre Guedes 							struct sk_buff *skb)
740971e3a4bSAndre Guedes {
741971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
742971e3a4bSAndre Guedes 
743971e3a4bSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
744971e3a4bSAndre Guedes 
745971e3a4bSAndre Guedes 	if (rp->status)
7468f984dfaSJohan Hedberg 		goto done;
747971e3a4bSAndre Guedes 
748b5b32b65SAndre Guedes 	switch (rp->page) {
749b5b32b65SAndre Guedes 	case 0:
750b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
751b5b32b65SAndre Guedes 		break;
752b5b32b65SAndre Guedes 	case 1:
75359e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
754b5b32b65SAndre Guedes 		break;
755b5b32b65SAndre Guedes 	}
756971e3a4bSAndre Guedes 
7578f984dfaSJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE)
7588f984dfaSJohan Hedberg 		hci_set_le_support(hdev);
7598f984dfaSJohan Hedberg 
7608f984dfaSJohan Hedberg done:
761971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
762971e3a4bSAndre Guedes }
763971e3a4bSAndre Guedes 
7641e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7651e89cffbSAndrei Emeltchenko 						struct sk_buff *skb)
7661e89cffbSAndrei Emeltchenko {
7671e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7681e89cffbSAndrei Emeltchenko 
7691e89cffbSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
7701e89cffbSAndrei Emeltchenko 
7711e89cffbSAndrei Emeltchenko 	if (rp->status)
7721e89cffbSAndrei Emeltchenko 		return;
7731e89cffbSAndrei Emeltchenko 
7741e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7751e89cffbSAndrei Emeltchenko 
7761e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7771e89cffbSAndrei Emeltchenko }
7781e89cffbSAndrei Emeltchenko 
779a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
780a9de9248SMarcel Holtmann {
781a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
782a9de9248SMarcel Holtmann 
783a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
784a9de9248SMarcel Holtmann 
785a9de9248SMarcel Holtmann 	if (rp->status)
786a9de9248SMarcel Holtmann 		return;
787a9de9248SMarcel Holtmann 
788a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
789a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
790a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
791a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
792da1f5198SMarcel Holtmann 
793da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
794da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
795da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
796da1f5198SMarcel Holtmann 	}
797da1f5198SMarcel Holtmann 
798da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
799da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
8001da177e4SLinus Torvalds 
801a9de9248SMarcel Holtmann 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
802a9de9248SMarcel Holtmann 					hdev->acl_mtu, hdev->acl_pkts,
803a9de9248SMarcel Holtmann 					hdev->sco_mtu, hdev->sco_pkts);
8041da177e4SLinus Torvalds }
8051da177e4SLinus Torvalds 
806a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
807a9de9248SMarcel Holtmann {
808a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
8091da177e4SLinus Torvalds 
810a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
811a9de9248SMarcel Holtmann 
812a9de9248SMarcel Holtmann 	if (!rp->status)
813a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
814a9de9248SMarcel Holtmann 
81523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
81623bb5763SJohan Hedberg }
81723bb5763SJohan Hedberg 
818350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
819350ee4cfSAndrei Emeltchenko 							struct sk_buff *skb)
820350ee4cfSAndrei Emeltchenko {
821350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
822350ee4cfSAndrei Emeltchenko 
823350ee4cfSAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
824350ee4cfSAndrei Emeltchenko 
825350ee4cfSAndrei Emeltchenko 	if (rp->status)
826350ee4cfSAndrei Emeltchenko 		return;
827350ee4cfSAndrei Emeltchenko 
828350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
829350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
830350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
831350ee4cfSAndrei Emeltchenko 
832350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
833350ee4cfSAndrei Emeltchenko 
834350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
835350ee4cfSAndrei Emeltchenko 					hdev->block_cnt, hdev->block_len);
836350ee4cfSAndrei Emeltchenko 
837350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
838350ee4cfSAndrei Emeltchenko }
839350ee4cfSAndrei Emeltchenko 
84023bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
84123bb5763SJohan Hedberg {
84223bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
84323bb5763SJohan Hedberg 
84423bb5763SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
84523bb5763SJohan Hedberg 
84623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8471da177e4SLinus Torvalds }
8481da177e4SLinus Torvalds 
849928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
850928abaa7SAndrei Emeltchenko 		struct sk_buff *skb)
851928abaa7SAndrei Emeltchenko {
852928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
853928abaa7SAndrei Emeltchenko 
854928abaa7SAndrei Emeltchenko 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
855928abaa7SAndrei Emeltchenko 
856928abaa7SAndrei Emeltchenko 	if (rp->status)
857928abaa7SAndrei Emeltchenko 		return;
858928abaa7SAndrei Emeltchenko 
859928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
860928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
861928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
862928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
863928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
864928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
865928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
866928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
867928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
868928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
869928abaa7SAndrei Emeltchenko 
870928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
871928abaa7SAndrei Emeltchenko }
872928abaa7SAndrei Emeltchenko 
873b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
874b0916ea0SJohan Hedberg 							struct sk_buff *skb)
875b0916ea0SJohan Hedberg {
876b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
877b0916ea0SJohan Hedberg 
878b0916ea0SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
879b0916ea0SJohan Hedberg 
880b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
881b0916ea0SJohan Hedberg }
882b0916ea0SJohan Hedberg 
883d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
884d5859e22SJohan Hedberg {
885d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
886d5859e22SJohan Hedberg 
887d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
888d5859e22SJohan Hedberg 
889d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
890d5859e22SJohan Hedberg }
891d5859e22SJohan Hedberg 
892d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
893d5859e22SJohan Hedberg 							struct sk_buff *skb)
894d5859e22SJohan Hedberg {
895d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
896d5859e22SJohan Hedberg 
897d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
898d5859e22SJohan Hedberg 
899d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
900d5859e22SJohan Hedberg }
901d5859e22SJohan Hedberg 
902d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
903d5859e22SJohan Hedberg 							struct sk_buff *skb)
904d5859e22SJohan Hedberg {
90591c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
906d5859e22SJohan Hedberg 
90791c4e9b1SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
908d5859e22SJohan Hedberg 
90991c4e9b1SMarcel Holtmann 	if (!rp->status)
91091c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
91191c4e9b1SMarcel Holtmann 
91291c4e9b1SMarcel Holtmann 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
913d5859e22SJohan Hedberg }
914d5859e22SJohan Hedberg 
915d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
916d5859e22SJohan Hedberg {
917d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
918d5859e22SJohan Hedberg 
919d5859e22SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, status);
920d5859e22SJohan Hedberg 
921d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
922d5859e22SJohan Hedberg }
923d5859e22SJohan Hedberg 
924980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
925980e1a53SJohan Hedberg {
926980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
927980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
928980e1a53SJohan Hedberg 	struct hci_conn *conn;
929980e1a53SJohan Hedberg 
930980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
931980e1a53SJohan Hedberg 
93256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
93356e5cb86SJohan Hedberg 
934a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
935744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
936980e1a53SJohan Hedberg 
937980e1a53SJohan Hedberg 	if (rp->status != 0)
93856e5cb86SJohan Hedberg 		goto unlock;
939980e1a53SJohan Hedberg 
940980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
941980e1a53SJohan Hedberg 	if (!cp)
94256e5cb86SJohan Hedberg 		goto unlock;
943980e1a53SJohan Hedberg 
944980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
945980e1a53SJohan Hedberg 	if (conn)
946980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
94756e5cb86SJohan Hedberg 
94856e5cb86SJohan Hedberg unlock:
94956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
950980e1a53SJohan Hedberg }
951980e1a53SJohan Hedberg 
952980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
953980e1a53SJohan Hedberg {
954980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
955980e1a53SJohan Hedberg 
956980e1a53SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
957980e1a53SJohan Hedberg 
95856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
95956e5cb86SJohan Hedberg 
960a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
961744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
962980e1a53SJohan Hedberg 								rp->status);
96356e5cb86SJohan Hedberg 
96456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
965980e1a53SJohan Hedberg }
96656e5cb86SJohan Hedberg 
9676ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9686ed58ec5SVille Tervo 				       struct sk_buff *skb)
9696ed58ec5SVille Tervo {
9706ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9716ed58ec5SVille Tervo 
9726ed58ec5SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
9736ed58ec5SVille Tervo 
9746ed58ec5SVille Tervo 	if (rp->status)
9756ed58ec5SVille Tervo 		return;
9766ed58ec5SVille Tervo 
9776ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9786ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9796ed58ec5SVille Tervo 
9806ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9816ed58ec5SVille Tervo 
9826ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9836ed58ec5SVille Tervo 
9846ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9856ed58ec5SVille Tervo }
986980e1a53SJohan Hedberg 
987a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
988a5c29683SJohan Hedberg {
989a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
990a5c29683SJohan Hedberg 
991a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
992a5c29683SJohan Hedberg 
99356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
99456e5cb86SJohan Hedberg 
995a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
99604124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
99704124681SGustavo F. Padovan 						 rp->status);
99856e5cb86SJohan Hedberg 
99956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1000a5c29683SJohan Hedberg }
1001a5c29683SJohan Hedberg 
1002a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
1003a5c29683SJohan Hedberg 							struct sk_buff *skb)
1004a5c29683SJohan Hedberg {
1005a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1006a5c29683SJohan Hedberg 
1007a5c29683SJohan Hedberg 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1008a5c29683SJohan Hedberg 
100956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
101056e5cb86SJohan Hedberg 
1011a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1012744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
101304124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
101456e5cb86SJohan Hedberg 
101556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1016a5c29683SJohan Hedberg }
1017a5c29683SJohan Hedberg 
10181143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
10191143d458SBrian Gix {
10201143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10211143d458SBrian Gix 
10221143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10231143d458SBrian Gix 
10241143d458SBrian Gix 	hci_dev_lock(hdev);
10251143d458SBrian Gix 
1026a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1027272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1028272d90dfSJohan Hedberg 						 0, rp->status);
10291143d458SBrian Gix 
10301143d458SBrian Gix 	hci_dev_unlock(hdev);
10311143d458SBrian Gix }
10321143d458SBrian Gix 
10331143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10341143d458SBrian Gix 							struct sk_buff *skb)
10351143d458SBrian Gix {
10361143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10371143d458SBrian Gix 
10381143d458SBrian Gix 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
10391143d458SBrian Gix 
10401143d458SBrian Gix 	hci_dev_lock(hdev);
10411143d458SBrian Gix 
1042a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10431143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
104404124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
10451143d458SBrian Gix 
10461143d458SBrian Gix 	hci_dev_unlock(hdev);
10471143d458SBrian Gix }
10481143d458SBrian Gix 
1049c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1050c35938b2SSzymon Janc 							struct sk_buff *skb)
1051c35938b2SSzymon Janc {
1052c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1053c35938b2SSzymon Janc 
1054c35938b2SSzymon Janc 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1055c35938b2SSzymon Janc 
105656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1057744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1058c35938b2SSzymon Janc 						rp->randomizer, rp->status);
105956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1060c35938b2SSzymon Janc }
1061c35938b2SSzymon Janc 
106207f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
106307f7fa5dSAndre Guedes {
106407f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
106507f7fa5dSAndre Guedes 
106607f7fa5dSAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
10677ba8b4beSAndre Guedes 
10687ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
10693fd24153SAndre Guedes 
10703fd24153SAndre Guedes 	if (status) {
10713fd24153SAndre Guedes 		hci_dev_lock(hdev);
10723fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
10733fd24153SAndre Guedes 		hci_dev_unlock(hdev);
10743fd24153SAndre Guedes 		return;
10753fd24153SAndre Guedes 	}
107607f7fa5dSAndre Guedes }
107707f7fa5dSAndre Guedes 
1078eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1079eb9d91f5SAndre Guedes 					struct sk_buff *skb)
1080eb9d91f5SAndre Guedes {
1081eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1082eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1083eb9d91f5SAndre Guedes 
1084eb9d91f5SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1085eb9d91f5SAndre Guedes 
1086eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1087eb9d91f5SAndre Guedes 	if (!cp)
1088eb9d91f5SAndre Guedes 		return;
1089eb9d91f5SAndre Guedes 
109068a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
109168a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
10927ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
10937ba8b4beSAndre Guedes 
10943fd24153SAndre Guedes 		if (status) {
10953fd24153SAndre Guedes 			hci_dev_lock(hdev);
10963fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
10973fd24153SAndre Guedes 			hci_dev_unlock(hdev);
10987ba8b4beSAndre Guedes 			return;
10993fd24153SAndre Guedes 		}
11007ba8b4beSAndre Guedes 
1101d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1102d23264a8SAndre Guedes 
1103a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1104343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1105a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
110668a8aea4SAndrei Emeltchenko 		break;
110768a8aea4SAndrei Emeltchenko 
110868a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1109c9ecc48eSAndre Guedes 		if (status) {
1110c9ecc48eSAndre Guedes 			hci_dev_lock(hdev);
1111c9ecc48eSAndre Guedes 			mgmt_stop_discovery_failed(hdev, status);
1112c9ecc48eSAndre Guedes 			hci_dev_unlock(hdev);
11137ba8b4beSAndre Guedes 			return;
1114c9ecc48eSAndre Guedes 		}
11157ba8b4beSAndre Guedes 
1116d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1117d23264a8SAndre Guedes 
1118bc3dd33cSAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1119bc3dd33cSAndre Guedes 		    hdev->discovery.state == DISCOVERY_FINDING) {
11205e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
11215e0452c0SAndre Guedes 		} else {
1122c599008fSAndre Guedes 			hci_dev_lock(hdev);
1123c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1124c599008fSAndre Guedes 			hci_dev_unlock(hdev);
11255e0452c0SAndre Guedes 		}
1126c599008fSAndre Guedes 
112768a8aea4SAndrei Emeltchenko 		break;
112868a8aea4SAndrei Emeltchenko 
112968a8aea4SAndrei Emeltchenko 	default:
113068a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
113168a8aea4SAndrei Emeltchenko 		break;
113235815085SAndre Guedes 	}
1133eb9d91f5SAndre Guedes }
1134eb9d91f5SAndre Guedes 
1135a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1136a7a595f6SVinicius Costa Gomes {
1137a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1138a7a595f6SVinicius Costa Gomes 
1139a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1140a7a595f6SVinicius Costa Gomes 
1141a7a595f6SVinicius Costa Gomes 	if (rp->status)
1142a7a595f6SVinicius Costa Gomes 		return;
1143a7a595f6SVinicius Costa Gomes 
1144a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1145a7a595f6SVinicius Costa Gomes }
1146a7a595f6SVinicius Costa Gomes 
1147a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1148a7a595f6SVinicius Costa Gomes {
1149a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1150a7a595f6SVinicius Costa Gomes 
1151a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
1152a7a595f6SVinicius Costa Gomes 
1153a7a595f6SVinicius Costa Gomes 	if (rp->status)
1154a7a595f6SVinicius Costa Gomes 		return;
1155a7a595f6SVinicius Costa Gomes 
1156a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1157a7a595f6SVinicius Costa Gomes }
1158a7a595f6SVinicius Costa Gomes 
1159f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1160f9b49306SAndre Guedes 							struct sk_buff *skb)
1161f9b49306SAndre Guedes {
116206199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1163f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1164f9b49306SAndre Guedes 
1165f9b49306SAndre Guedes 	BT_DBG("%s status 0x%x", hdev->name, status);
1166f9b49306SAndre Guedes 
116706199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
11688f984dfaSJohan Hedberg 	if (!sent)
1169f9b49306SAndre Guedes 		return;
1170f9b49306SAndre Guedes 
11718f984dfaSJohan Hedberg 	if (!status) {
11728f984dfaSJohan Hedberg 		if (sent->le)
11738f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
11748f984dfaSJohan Hedberg 		else
11758f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
11768f984dfaSJohan Hedberg 	}
11778f984dfaSJohan Hedberg 
11788f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
11798f984dfaSJohan Hedberg 					!test_bit(HCI_INIT, &hdev->flags))
11808f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
11818f984dfaSJohan Hedberg 
11828f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1183f9b49306SAndre Guedes }
1184f9b49306SAndre Guedes 
1185a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1186a9de9248SMarcel Holtmann {
1187a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1188a9de9248SMarcel Holtmann 
1189a9de9248SMarcel Holtmann 	if (status) {
119023bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1191a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
119256e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1193a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11947a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
119556e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1196314b2381SJohan Hedberg 		return;
1197314b2381SJohan Hedberg 	}
1198314b2381SJohan Hedberg 
119989352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
120089352e7dSAndre Guedes 
120156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1202343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
120356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1204a9de9248SMarcel Holtmann }
1205a9de9248SMarcel Holtmann 
12061da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
12071da177e4SLinus Torvalds {
1208a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
12091da177e4SLinus Torvalds 	struct hci_conn *conn;
12101da177e4SLinus Torvalds 
1211a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1212a9de9248SMarcel Holtmann 
1213a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
12141da177e4SLinus Torvalds 	if (!cp)
12151da177e4SLinus Torvalds 		return;
12161da177e4SLinus Torvalds 
12171da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12181da177e4SLinus Torvalds 
12191da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
12201da177e4SLinus Torvalds 
1221a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
12221da177e4SLinus Torvalds 
12231da177e4SLinus Torvalds 	if (status) {
12241da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
12254c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
12261da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
12271da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
12281da177e4SLinus Torvalds 				hci_conn_del(conn);
12294c67bc74SMarcel Holtmann 			} else
12304c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
12311da177e4SLinus Torvalds 		}
12321da177e4SLinus Torvalds 	} else {
12331da177e4SLinus Torvalds 		if (!conn) {
12341da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
12351da177e4SLinus Torvalds 			if (conn) {
1236a0c808b3SJohan Hedberg 				conn->out = true;
12371da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
12381da177e4SLinus Torvalds 			} else
1239893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12401da177e4SLinus Torvalds 		}
12411da177e4SLinus Torvalds 	}
12421da177e4SLinus Torvalds 
12431da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12441da177e4SLinus Torvalds }
12451da177e4SLinus Torvalds 
1246a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12471da177e4SLinus Torvalds {
1248a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12491da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12501da177e4SLinus Torvalds 	__u16 handle;
12511da177e4SLinus Torvalds 
1252b6a0dc82SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1253b6a0dc82SMarcel Holtmann 
1254a9de9248SMarcel Holtmann 	if (!status)
1255a9de9248SMarcel Holtmann 		return;
1256a9de9248SMarcel Holtmann 
1257a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12581da177e4SLinus Torvalds 	if (!cp)
1259a9de9248SMarcel Holtmann 		return;
12601da177e4SLinus Torvalds 
12611da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12621da177e4SLinus Torvalds 
1263a9de9248SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
12641da177e4SLinus Torvalds 
12651da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12661da177e4SLinus Torvalds 
12671da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12685a08ecceSAndrei Emeltchenko 	if (acl) {
12695a08ecceSAndrei Emeltchenko 		sco = acl->link;
12705a08ecceSAndrei Emeltchenko 		if (sco) {
12711da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12741da177e4SLinus Torvalds 			hci_conn_del(sco);
12751da177e4SLinus Torvalds 		}
12765a08ecceSAndrei Emeltchenko 	}
12771da177e4SLinus Torvalds 
12781da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12791da177e4SLinus Torvalds }
12801da177e4SLinus Torvalds 
1281f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1282f8558555SMarcel Holtmann {
1283f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1284f8558555SMarcel Holtmann 	struct hci_conn *conn;
1285f8558555SMarcel Holtmann 
1286f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1287f8558555SMarcel Holtmann 
1288f8558555SMarcel Holtmann 	if (!status)
1289f8558555SMarcel Holtmann 		return;
1290f8558555SMarcel Holtmann 
1291f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1292f8558555SMarcel Holtmann 	if (!cp)
1293f8558555SMarcel Holtmann 		return;
1294f8558555SMarcel Holtmann 
1295f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1296f8558555SMarcel Holtmann 
1297f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1298f8558555SMarcel Holtmann 	if (conn) {
1299f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1300f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1301f8558555SMarcel Holtmann 			hci_conn_put(conn);
1302f8558555SMarcel Holtmann 		}
1303f8558555SMarcel Holtmann 	}
1304f8558555SMarcel Holtmann 
1305f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1306f8558555SMarcel Holtmann }
1307f8558555SMarcel Holtmann 
1308f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1309f8558555SMarcel Holtmann {
1310f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1311f8558555SMarcel Holtmann 	struct hci_conn *conn;
1312f8558555SMarcel Holtmann 
1313f8558555SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1314f8558555SMarcel Holtmann 
1315f8558555SMarcel Holtmann 	if (!status)
1316f8558555SMarcel Holtmann 		return;
1317f8558555SMarcel Holtmann 
1318f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1319f8558555SMarcel Holtmann 	if (!cp)
1320f8558555SMarcel Holtmann 		return;
1321f8558555SMarcel Holtmann 
1322f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1323f8558555SMarcel Holtmann 
1324f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1325f8558555SMarcel Holtmann 	if (conn) {
1326f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1327f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1328f8558555SMarcel Holtmann 			hci_conn_put(conn);
1329f8558555SMarcel Holtmann 		}
1330f8558555SMarcel Holtmann 	}
1331f8558555SMarcel Holtmann 
1332f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1333f8558555SMarcel Holtmann }
1334f8558555SMarcel Holtmann 
1335127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1336392599b9SJohan Hedberg 							struct hci_conn *conn)
1337392599b9SJohan Hedberg {
1338392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1339392599b9SJohan Hedberg 		return 0;
1340392599b9SJohan Hedberg 
1341765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1342392599b9SJohan Hedberg 		return 0;
1343392599b9SJohan Hedberg 
1344392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1345e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1346aa64a8b5SJohan Hedberg 	if (!hci_conn_ssp_enabled(conn) &&
1347e9bf2bf0SVinicius Costa Gomes 				conn->pending_sec_level != BT_SECURITY_HIGH &&
1348e9bf2bf0SVinicius Costa Gomes 				!(conn->auth_type & 0x01))
1349392599b9SJohan Hedberg 		return 0;
1350392599b9SJohan Hedberg 
1351392599b9SJohan Hedberg 	return 1;
1352392599b9SJohan Hedberg }
1353392599b9SJohan Hedberg 
135400abfe44SGustavo F. Padovan static inline int hci_resolve_name(struct hci_dev *hdev,
135500abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
135630dc78e1SJohan Hedberg {
135730dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
135830dc78e1SJohan Hedberg 
135930dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
136030dc78e1SJohan Hedberg 
136130dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
136230dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
136330dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
136430dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
136530dc78e1SJohan Hedberg 
136630dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
136730dc78e1SJohan Hedberg }
136830dc78e1SJohan Hedberg 
1369b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
137030dc78e1SJohan Hedberg {
137130dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
137230dc78e1SJohan Hedberg 	struct inquiry_entry *e;
137330dc78e1SJohan Hedberg 
1374b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1375b644ba33SJohan Hedberg 		return false;
1376b644ba33SJohan Hedberg 
1377b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1378b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1379b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1380b644ba33SJohan Hedberg 		return true;
1381b644ba33SJohan Hedberg 	}
1382b644ba33SJohan Hedberg 
1383b644ba33SJohan Hedberg 	return false;
1384b644ba33SJohan Hedberg }
1385b644ba33SJohan Hedberg 
1386b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1387b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1388b644ba33SJohan Hedberg {
1389b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1390b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1391b644ba33SJohan Hedberg 
1392b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
139304124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
139404124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1395b644ba33SJohan Hedberg 
1396b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1397b644ba33SJohan Hedberg 		return;
1398b644ba33SJohan Hedberg 
139930dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
140030dc78e1SJohan Hedberg 		goto discov_complete;
140130dc78e1SJohan Hedberg 
140230dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
140330dc78e1SJohan Hedberg 		return;
140430dc78e1SJohan Hedberg 
140530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
140630dc78e1SJohan Hedberg 	if (e) {
140730dc78e1SJohan Hedberg 		e->name_state = NAME_KNOWN;
140830dc78e1SJohan Hedberg 		list_del(&e->list);
1409b644ba33SJohan Hedberg 		if (name)
1410b644ba33SJohan Hedberg 			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1411b644ba33SJohan Hedberg 					 e->data.rssi, name, name_len);
141230dc78e1SJohan Hedberg 	}
141330dc78e1SJohan Hedberg 
1414b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
141530dc78e1SJohan Hedberg 		return;
141630dc78e1SJohan Hedberg 
141730dc78e1SJohan Hedberg discov_complete:
141830dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
141930dc78e1SJohan Hedberg }
142030dc78e1SJohan Hedberg 
1421a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
14221da177e4SLinus Torvalds {
1423127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1424127178d2SJohan Hedberg 	struct hci_conn *conn;
1425127178d2SJohan Hedberg 
1426a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1427127178d2SJohan Hedberg 
1428127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1429127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1430127178d2SJohan Hedberg 	if (!status)
1431127178d2SJohan Hedberg 		return;
1432127178d2SJohan Hedberg 
1433127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1434127178d2SJohan Hedberg 	if (!cp)
1435127178d2SJohan Hedberg 		return;
1436127178d2SJohan Hedberg 
1437127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1438127178d2SJohan Hedberg 
1439127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1440b644ba33SJohan Hedberg 
1441b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1442b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1443b644ba33SJohan Hedberg 
144479c6c70cSJohan Hedberg 	if (!conn)
144579c6c70cSJohan Hedberg 		goto unlock;
144679c6c70cSJohan Hedberg 
144779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
144879c6c70cSJohan Hedberg 		goto unlock;
144979c6c70cSJohan Hedberg 
145051a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1451127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1452127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1453127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1454127178d2SJohan Hedberg 	}
1455127178d2SJohan Hedberg 
145679c6c70cSJohan Hedberg unlock:
1457127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1458a9de9248SMarcel Holtmann }
14591da177e4SLinus Torvalds 
1460769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1461769be974SMarcel Holtmann {
1462769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1463769be974SMarcel Holtmann 	struct hci_conn *conn;
1464769be974SMarcel Holtmann 
1465769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1466769be974SMarcel Holtmann 
1467769be974SMarcel Holtmann 	if (!status)
1468769be974SMarcel Holtmann 		return;
1469769be974SMarcel Holtmann 
1470769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1471769be974SMarcel Holtmann 	if (!cp)
1472769be974SMarcel Holtmann 		return;
1473769be974SMarcel Holtmann 
1474769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1475769be974SMarcel Holtmann 
1476769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1477769be974SMarcel Holtmann 	if (conn) {
1478769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1479769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1480769be974SMarcel Holtmann 			hci_conn_put(conn);
1481769be974SMarcel Holtmann 		}
1482769be974SMarcel Holtmann 	}
1483769be974SMarcel Holtmann 
1484769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1485769be974SMarcel Holtmann }
1486769be974SMarcel Holtmann 
1487769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1488769be974SMarcel Holtmann {
1489769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1490769be974SMarcel Holtmann 	struct hci_conn *conn;
1491769be974SMarcel Holtmann 
1492769be974SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1493769be974SMarcel Holtmann 
1494769be974SMarcel Holtmann 	if (!status)
1495769be974SMarcel Holtmann 		return;
1496769be974SMarcel Holtmann 
1497769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1498769be974SMarcel Holtmann 	if (!cp)
1499769be974SMarcel Holtmann 		return;
1500769be974SMarcel Holtmann 
1501769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1502769be974SMarcel Holtmann 
1503769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1504769be974SMarcel Holtmann 	if (conn) {
1505769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1506769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1507769be974SMarcel Holtmann 			hci_conn_put(conn);
1508769be974SMarcel Holtmann 		}
1509769be974SMarcel Holtmann 	}
1510769be974SMarcel Holtmann 
1511769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1512769be974SMarcel Holtmann }
1513769be974SMarcel Holtmann 
1514a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1515a9de9248SMarcel Holtmann {
1516b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1517b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1518b6a0dc82SMarcel Holtmann 	__u16 handle;
1519b6a0dc82SMarcel Holtmann 
1520a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1521b6a0dc82SMarcel Holtmann 
1522b6a0dc82SMarcel Holtmann 	if (!status)
1523b6a0dc82SMarcel Holtmann 		return;
1524b6a0dc82SMarcel Holtmann 
1525b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1526b6a0dc82SMarcel Holtmann 	if (!cp)
1527b6a0dc82SMarcel Holtmann 		return;
1528b6a0dc82SMarcel Holtmann 
1529b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1530b6a0dc82SMarcel Holtmann 
1531b6a0dc82SMarcel Holtmann 	BT_DBG("%s handle %d", hdev->name, handle);
1532b6a0dc82SMarcel Holtmann 
1533b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1534b6a0dc82SMarcel Holtmann 
1535b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15365a08ecceSAndrei Emeltchenko 	if (acl) {
15375a08ecceSAndrei Emeltchenko 		sco = acl->link;
15385a08ecceSAndrei Emeltchenko 		if (sco) {
1539b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1540b6a0dc82SMarcel Holtmann 
1541b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1542b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1543b6a0dc82SMarcel Holtmann 		}
15445a08ecceSAndrei Emeltchenko 	}
1545b6a0dc82SMarcel Holtmann 
1546b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1547a9de9248SMarcel Holtmann }
1548a9de9248SMarcel Holtmann 
1549a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1550a9de9248SMarcel Holtmann {
1551a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
155204837f64SMarcel Holtmann 	struct hci_conn *conn;
155304837f64SMarcel Holtmann 
1554a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1555a9de9248SMarcel Holtmann 
1556a9de9248SMarcel Holtmann 	if (!status)
1557a9de9248SMarcel Holtmann 		return;
1558a9de9248SMarcel Holtmann 
1559a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
156004837f64SMarcel Holtmann 	if (!cp)
1561a9de9248SMarcel Holtmann 		return;
156204837f64SMarcel Holtmann 
156304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
156404837f64SMarcel Holtmann 
156504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1566e73439d8SMarcel Holtmann 	if (conn) {
156751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
156804837f64SMarcel Holtmann 
156951a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1570e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1571e73439d8SMarcel Holtmann 	}
1572e73439d8SMarcel Holtmann 
157304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
157404837f64SMarcel Holtmann }
157504837f64SMarcel Holtmann 
1576a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1577a9de9248SMarcel Holtmann {
1578a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
157904837f64SMarcel Holtmann 	struct hci_conn *conn;
158004837f64SMarcel Holtmann 
1581a9de9248SMarcel Holtmann 	BT_DBG("%s status 0x%x", hdev->name, status);
1582a9de9248SMarcel Holtmann 
1583a9de9248SMarcel Holtmann 	if (!status)
1584a9de9248SMarcel Holtmann 		return;
1585a9de9248SMarcel Holtmann 
1586a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
158704837f64SMarcel Holtmann 	if (!cp)
1588a9de9248SMarcel Holtmann 		return;
158904837f64SMarcel Holtmann 
159004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
159104837f64SMarcel Holtmann 
159204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1593e73439d8SMarcel Holtmann 	if (conn) {
159451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
159504837f64SMarcel Holtmann 
159651a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1597e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1598e73439d8SMarcel Holtmann 	}
1599e73439d8SMarcel Holtmann 
160004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
160104837f64SMarcel Holtmann }
160204837f64SMarcel Holtmann 
160388c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
160488c3df13SJohan Hedberg {
160588c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
160688c3df13SJohan Hedberg 	struct hci_conn *conn;
160788c3df13SJohan Hedberg 
160888c3df13SJohan Hedberg 	if (!status)
160988c3df13SJohan Hedberg 		return;
161088c3df13SJohan Hedberg 
161188c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
161288c3df13SJohan Hedberg 	if (!cp)
161388c3df13SJohan Hedberg 		return;
161488c3df13SJohan Hedberg 
161588c3df13SJohan Hedberg 	hci_dev_lock(hdev);
161688c3df13SJohan Hedberg 
161788c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
161888c3df13SJohan Hedberg 	if (conn)
161988c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
162088c3df13SJohan Hedberg 				       conn->dst_type, status);
162188c3df13SJohan Hedberg 
162288c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
162388c3df13SJohan Hedberg }
162488c3df13SJohan Hedberg 
1625fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1626fcd89c09SVille Tervo {
1627fcd89c09SVille Tervo 	struct hci_cp_le_create_conn *cp;
1628fcd89c09SVille Tervo 	struct hci_conn *conn;
1629fcd89c09SVille Tervo 
1630fcd89c09SVille Tervo 	BT_DBG("%s status 0x%x", hdev->name, status);
1631fcd89c09SVille Tervo 
1632fcd89c09SVille Tervo 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1633fcd89c09SVille Tervo 	if (!cp)
1634fcd89c09SVille Tervo 		return;
1635fcd89c09SVille Tervo 
1636fcd89c09SVille Tervo 	hci_dev_lock(hdev);
1637fcd89c09SVille Tervo 
1638fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1639fcd89c09SVille Tervo 
1640fcd89c09SVille Tervo 	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1641fcd89c09SVille Tervo 		conn);
1642fcd89c09SVille Tervo 
1643fcd89c09SVille Tervo 	if (status) {
1644fcd89c09SVille Tervo 		if (conn && conn->state == BT_CONNECT) {
1645fcd89c09SVille Tervo 			conn->state = BT_CLOSED;
1646328c9248SHemant Gupta 			mgmt_connect_failed(hdev, &cp->peer_addr, conn->type,
1647328c9248SHemant Gupta 					    conn->dst_type, status);
1648fcd89c09SVille Tervo 			hci_proto_connect_cfm(conn, status);
1649fcd89c09SVille Tervo 			hci_conn_del(conn);
1650fcd89c09SVille Tervo 		}
1651fcd89c09SVille Tervo 	} else {
1652fcd89c09SVille Tervo 		if (!conn) {
1653fcd89c09SVille Tervo 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
165429b7988aSAndre Guedes 			if (conn) {
165529b7988aSAndre Guedes 				conn->dst_type = cp->peer_addr_type;
1656a0c808b3SJohan Hedberg 				conn->out = true;
165729b7988aSAndre Guedes 			} else {
1658fcd89c09SVille Tervo 				BT_ERR("No memory for new connection");
1659fcd89c09SVille Tervo 			}
1660fcd89c09SVille Tervo 		}
166129b7988aSAndre Guedes 	}
1662fcd89c09SVille Tervo 
1663fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
1664fcd89c09SVille Tervo }
1665fcd89c09SVille Tervo 
1666a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1667a7a595f6SVinicius Costa Gomes {
1668a7a595f6SVinicius Costa Gomes 	BT_DBG("%s status 0x%x", hdev->name, status);
1669a7a595f6SVinicius Costa Gomes }
1670a7a595f6SVinicius Costa Gomes 
16711da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16721da177e4SLinus Torvalds {
16731da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
167430dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
167530dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16761da177e4SLinus Torvalds 
16771da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, status);
16781da177e4SLinus Torvalds 
167923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16806bd57416SMarcel Holtmann 
1681a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
168289352e7dSAndre Guedes 
168389352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
168489352e7dSAndre Guedes 		return;
168589352e7dSAndre Guedes 
1686a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
168730dc78e1SJohan Hedberg 		return;
168830dc78e1SJohan Hedberg 
168956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
169030dc78e1SJohan Hedberg 
1691343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
169230dc78e1SJohan Hedberg 		goto unlock;
169330dc78e1SJohan Hedberg 
169430dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1695ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
169630dc78e1SJohan Hedberg 		goto unlock;
169730dc78e1SJohan Hedberg 	}
169830dc78e1SJohan Hedberg 
169930dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
170030dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
170130dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
170230dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
170330dc78e1SJohan Hedberg 	} else {
170430dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
170530dc78e1SJohan Hedberg 	}
170630dc78e1SJohan Hedberg 
170730dc78e1SJohan Hedberg unlock:
170856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
17091da177e4SLinus Torvalds }
17101da177e4SLinus Torvalds 
17111da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
17121da177e4SLinus Torvalds {
171345bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1714a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
17151da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
17161da177e4SLinus Torvalds 
17171da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
17181da177e4SLinus Torvalds 
171945bb4bf0SMarcel Holtmann 	if (!num_rsp)
172045bb4bf0SMarcel Holtmann 		return;
172145bb4bf0SMarcel Holtmann 
17221519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
17231519cc17SAndre Guedes 		return;
17241519cc17SAndre Guedes 
17251da177e4SLinus Torvalds 	hci_dev_lock(hdev);
172645bb4bf0SMarcel Holtmann 
1727e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1728388fc8faSJohan Hedberg 		bool name_known, ssp;
17293175405bSJohan Hedberg 
17301da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
17311da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
17321da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
17331da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
17341da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
17351da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17361da177e4SLinus Torvalds 		data.rssi		= 0x00;
173741a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17383175405bSJohan Hedberg 
1739388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
174048264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
174104124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
174204124681SGustavo F. Padovan 				  0);
17431da177e4SLinus Torvalds 	}
174445bb4bf0SMarcel Holtmann 
17451da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17461da177e4SLinus Torvalds }
17471da177e4SLinus Torvalds 
1748a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17491da177e4SLinus Torvalds {
1750a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1751a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17521da177e4SLinus Torvalds 
1753a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
175445bb4bf0SMarcel Holtmann 
17551da177e4SLinus Torvalds 	hci_dev_lock(hdev);
175645bb4bf0SMarcel Holtmann 
1757a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17589499237aSMarcel Holtmann 	if (!conn) {
17599499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17609499237aSMarcel Holtmann 			goto unlock;
17619499237aSMarcel Holtmann 
17629499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1763a9de9248SMarcel Holtmann 		if (!conn)
1764a9de9248SMarcel Holtmann 			goto unlock;
176545bb4bf0SMarcel Holtmann 
17669499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17679499237aSMarcel Holtmann 	}
17689499237aSMarcel Holtmann 
1769a9de9248SMarcel Holtmann 	if (!ev->status) {
1770a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1771769be974SMarcel Holtmann 
1772769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1773769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1774769be974SMarcel Holtmann 			hci_conn_hold(conn);
1775052b30b0SMarcel Holtmann 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1776769be974SMarcel Holtmann 		} else
1777a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1778a9de9248SMarcel Holtmann 
17799eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
17807d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17817d0db0a3SMarcel Holtmann 
1782a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1783a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1784a9de9248SMarcel Holtmann 
1785a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1786a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1787a9de9248SMarcel Holtmann 
1788a9de9248SMarcel Holtmann 		/* Get remote features */
1789a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1790a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1791a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1792769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1793769be974SMarcel Holtmann 				     sizeof(cp), &cp);
179445bb4bf0SMarcel Holtmann 		}
1795a9de9248SMarcel Holtmann 
1796a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1797d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1798a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1799a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1800a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
180104124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
180204124681SGustavo F. Padovan 				     &cp);
1803a9de9248SMarcel Holtmann 		}
180417d5c04cSJohan Hedberg 	} else {
1805a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
180617d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1807744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
180848264f06SJohan Hedberg 					    conn->dst_type, ev->status);
180917d5c04cSJohan Hedberg 	}
181045bb4bf0SMarcel Holtmann 
1811e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1812e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
181345bb4bf0SMarcel Holtmann 
1814769be974SMarcel Holtmann 	if (ev->status) {
1815a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1816a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1817c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1818c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1819a9de9248SMarcel Holtmann 
1820a9de9248SMarcel Holtmann unlock:
18211da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1822a9de9248SMarcel Holtmann 
1823a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
18241da177e4SLinus Torvalds }
18251da177e4SLinus Torvalds 
18261da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18271da177e4SLinus Torvalds {
1828a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
18291da177e4SLinus Torvalds 	int mask = hdev->link_mode;
18301da177e4SLinus Torvalds 
1831a9de9248SMarcel Holtmann 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
18321da177e4SLinus Torvalds 					batostr(&ev->bdaddr), ev->link_type);
18331da177e4SLinus Torvalds 
18341da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
18351da177e4SLinus Torvalds 
1836138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1837138d22efSSzymon Janc 			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
18381da177e4SLinus Torvalds 		/* Connection accepted */
1839c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
18401da177e4SLinus Torvalds 		struct hci_conn *conn;
18411da177e4SLinus Torvalds 
18421da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1843b6a0dc82SMarcel Holtmann 
1844cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1845cc11b9c1SAndrei Emeltchenko 		if (ie)
1846c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1847c7bdd502SMarcel Holtmann 
18481da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
18491da177e4SLinus Torvalds 		if (!conn) {
1850cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1851cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1852893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
18531da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
18541da177e4SLinus Torvalds 				return;
18551da177e4SLinus Torvalds 			}
18561da177e4SLinus Torvalds 		}
1857b6a0dc82SMarcel Holtmann 
18581da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
18591da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1860b6a0dc82SMarcel Holtmann 
18611da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
18621da177e4SLinus Torvalds 
1863b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1864b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1865b6a0dc82SMarcel Holtmann 
18661da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
18671da177e4SLinus Torvalds 
18681da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
18691da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
18701da177e4SLinus Torvalds 			else
18711da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
18721da177e4SLinus Torvalds 
187304124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
187404124681SGustavo F. Padovan 				     &cp);
1875b6a0dc82SMarcel Holtmann 		} else {
1876b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1877b6a0dc82SMarcel Holtmann 
1878b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1879a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1880b6a0dc82SMarcel Holtmann 
1881b6a0dc82SMarcel Holtmann 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
1882b6a0dc82SMarcel Holtmann 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
1883b6a0dc82SMarcel Holtmann 			cp.max_latency    = cpu_to_le16(0xffff);
1884b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1885b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1886b6a0dc82SMarcel Holtmann 
1887b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1888b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
1889b6a0dc82SMarcel Holtmann 		}
18901da177e4SLinus Torvalds 	} else {
18911da177e4SLinus Torvalds 		/* Connection rejected */
18921da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18931da177e4SLinus Torvalds 
18941da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18959f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1896a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18971da177e4SLinus Torvalds 	}
18981da177e4SLinus Torvalds }
18991da177e4SLinus Torvalds 
19001da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19011da177e4SLinus Torvalds {
1902a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
190304837f64SMarcel Holtmann 	struct hci_conn *conn;
19041da177e4SLinus Torvalds 
19051da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
19061da177e4SLinus Torvalds 
19071da177e4SLinus Torvalds 	hci_dev_lock(hdev);
19081da177e4SLinus Torvalds 
190904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1910f7520543SJohan Hedberg 	if (!conn)
1911f7520543SJohan Hedberg 		goto unlock;
1912f7520543SJohan Hedberg 
191337d9ef76SJohan Hedberg 	if (ev->status == 0)
19141da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
19157d0db0a3SMarcel Holtmann 
1916b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1917b644ba33SJohan Hedberg 			(conn->type == ACL_LINK || conn->type == LE_LINK)) {
191837d9ef76SJohan Hedberg 		if (ev->status != 0)
191988c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
192088c3df13SJohan Hedberg 						conn->dst_type, ev->status);
192137d9ef76SJohan Hedberg 		else
1922afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
192348264f06SJohan Hedberg 						 conn->dst_type);
192437d9ef76SJohan Hedberg 	}
1925f7520543SJohan Hedberg 
192637d9ef76SJohan Hedberg 	if (ev->status == 0) {
19276ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
19286ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
19292950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
19301da177e4SLinus Torvalds 		hci_conn_del(conn);
193137d9ef76SJohan Hedberg 	}
19321da177e4SLinus Torvalds 
1933f7520543SJohan Hedberg unlock:
19341da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19351da177e4SLinus Torvalds }
19361da177e4SLinus Torvalds 
1937a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1938a9de9248SMarcel Holtmann {
1939a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1940a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1941a9de9248SMarcel Holtmann 
1942a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
1943a9de9248SMarcel Holtmann 
1944a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1945a9de9248SMarcel Holtmann 
1946a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1947d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1948d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1949d7556e20SWaldemar Rymarkiewicz 
1950765c2a96SJohan Hedberg 	if (!ev->status) {
1951aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
195251a8efd7SJohan Hedberg 				test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1953d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
195419f8def0SWaldemar Rymarkiewicz 		} else {
1955a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1956765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
195719f8def0SWaldemar Rymarkiewicz 		}
19582a611692SJohan Hedberg 	} else {
1959bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1960bab73cb6SJohan Hedberg 				 ev->status);
19612a611692SJohan Hedberg 	}
1962a9de9248SMarcel Holtmann 
196351a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
196451a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1965a9de9248SMarcel Holtmann 
1966f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1967aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1968f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1969f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1970f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1971d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1972d7556e20SWaldemar Rymarkiewicz 									&cp);
1973f8558555SMarcel Holtmann 		} else {
1974f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1975f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1976f8558555SMarcel Holtmann 			hci_conn_put(conn);
1977f8558555SMarcel Holtmann 		}
1978052b30b0SMarcel Holtmann 	} else {
1979a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1980a9de9248SMarcel Holtmann 
1981052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1982052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1983052b30b0SMarcel Holtmann 		hci_conn_put(conn);
1984052b30b0SMarcel Holtmann 	}
1985052b30b0SMarcel Holtmann 
198651a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1987a9de9248SMarcel Holtmann 		if (!ev->status) {
1988a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1989f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1990f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1991d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1992d7556e20SWaldemar Rymarkiewicz 									&cp);
1993a9de9248SMarcel Holtmann 		} else {
199451a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1995a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1996a9de9248SMarcel Holtmann 		}
1997a9de9248SMarcel Holtmann 	}
1998a9de9248SMarcel Holtmann 
1999d7556e20SWaldemar Rymarkiewicz unlock:
2000a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2001a9de9248SMarcel Holtmann }
2002a9de9248SMarcel Holtmann 
2003a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2004a9de9248SMarcel Holtmann {
2005127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2006127178d2SJohan Hedberg 	struct hci_conn *conn;
2007127178d2SJohan Hedberg 
2008a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2009a9de9248SMarcel Holtmann 
2010a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2011127178d2SJohan Hedberg 
2012127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2013127178d2SJohan Hedberg 
2014127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2015b644ba33SJohan Hedberg 
2016b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2017b644ba33SJohan Hedberg 		goto check_auth;
2018b644ba33SJohan Hedberg 
2019b644ba33SJohan Hedberg 	if (ev->status == 0)
2020b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2021b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2022b644ba33SJohan Hedberg 	else
2023b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2024b644ba33SJohan Hedberg 
2025b644ba33SJohan Hedberg check_auth:
202679c6c70cSJohan Hedberg 	if (!conn)
202779c6c70cSJohan Hedberg 		goto unlock;
202879c6c70cSJohan Hedberg 
202979c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
203079c6c70cSJohan Hedberg 		goto unlock;
203179c6c70cSJohan Hedberg 
203251a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2033127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2034127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2035127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2036127178d2SJohan Hedberg 	}
2037127178d2SJohan Hedberg 
203879c6c70cSJohan Hedberg unlock:
2039127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2040a9de9248SMarcel Holtmann }
2041a9de9248SMarcel Holtmann 
2042a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2043a9de9248SMarcel Holtmann {
2044a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2045a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2046a9de9248SMarcel Holtmann 
2047a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2048a9de9248SMarcel Holtmann 
2049a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2050a9de9248SMarcel Holtmann 
2051a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2052a9de9248SMarcel Holtmann 	if (conn) {
2053a9de9248SMarcel Holtmann 		if (!ev->status) {
2054ae293196SMarcel Holtmann 			if (ev->encrypt) {
2055ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2056ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2057a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2058da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2059ae293196SMarcel Holtmann 			} else
2060a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2061a9de9248SMarcel Holtmann 		}
2062a9de9248SMarcel Holtmann 
206351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2064a9de9248SMarcel Holtmann 
2065a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2066d839c813SGustavo Padovan 			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
2067a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2068a7d7723aSGustavo Padovan 			goto unlock;
2069a7d7723aSGustavo Padovan 		}
2070a7d7723aSGustavo Padovan 
2071f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2072f8558555SMarcel Holtmann 			if (!ev->status)
2073f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2074f8558555SMarcel Holtmann 
2075f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2076f8558555SMarcel Holtmann 			hci_conn_put(conn);
2077f8558555SMarcel Holtmann 		} else
2078a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2079a9de9248SMarcel Holtmann 	}
2080a9de9248SMarcel Holtmann 
2081a7d7723aSGustavo Padovan unlock:
2082a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2083a9de9248SMarcel Holtmann }
2084a9de9248SMarcel Holtmann 
2085a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2086a9de9248SMarcel Holtmann {
2087a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2088a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2089a9de9248SMarcel Holtmann 
2090a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2091a9de9248SMarcel Holtmann 
2092a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2093a9de9248SMarcel Holtmann 
2094a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2095a9de9248SMarcel Holtmann 	if (conn) {
2096a9de9248SMarcel Holtmann 		if (!ev->status)
2097a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2098a9de9248SMarcel Holtmann 
209951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2100a9de9248SMarcel Holtmann 
2101a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2102a9de9248SMarcel Holtmann 	}
2103a9de9248SMarcel Holtmann 
2104a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2105a9de9248SMarcel Holtmann }
2106a9de9248SMarcel Holtmann 
2107a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2108a9de9248SMarcel Holtmann {
2109a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2110a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2111a9de9248SMarcel Holtmann 
2112a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2113a9de9248SMarcel Holtmann 
2114a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2115a9de9248SMarcel Holtmann 
2116a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2117ccd556feSJohan Hedberg 	if (!conn)
2118ccd556feSJohan Hedberg 		goto unlock;
2119ccd556feSJohan Hedberg 
2120769be974SMarcel Holtmann 	if (!ev->status)
2121a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2122a9de9248SMarcel Holtmann 
2123ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2124ccd556feSJohan Hedberg 		goto unlock;
2125ccd556feSJohan Hedberg 
2126ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2127769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2128769be974SMarcel Holtmann 		cp.handle = ev->handle;
2129769be974SMarcel Holtmann 		cp.page = 0x01;
2130ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2131769be974SMarcel Holtmann 							sizeof(cp), &cp);
2132392599b9SJohan Hedberg 		goto unlock;
2133392599b9SJohan Hedberg 	}
2134392599b9SJohan Hedberg 
2135671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2136127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2137127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2138127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2139127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2140127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2141b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2142b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
214308c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2144b644ba33SJohan Hedberg 				      conn->dev_class);
2145392599b9SJohan Hedberg 
2146127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2147769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2148769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2149769be974SMarcel Holtmann 		hci_conn_put(conn);
2150769be974SMarcel Holtmann 	}
2151769be974SMarcel Holtmann 
2152ccd556feSJohan Hedberg unlock:
2153a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2154a9de9248SMarcel Holtmann }
2155a9de9248SMarcel Holtmann 
2156a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
2157a9de9248SMarcel Holtmann {
2158a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2159a9de9248SMarcel Holtmann }
2160a9de9248SMarcel Holtmann 
2161a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2162a9de9248SMarcel Holtmann {
2163a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2164a9de9248SMarcel Holtmann }
2165a9de9248SMarcel Holtmann 
2166a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2167a9de9248SMarcel Holtmann {
2168a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2169a9de9248SMarcel Holtmann 	__u16 opcode;
2170a9de9248SMarcel Holtmann 
2171a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2172a9de9248SMarcel Holtmann 
2173a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2174a9de9248SMarcel Holtmann 
2175a9de9248SMarcel Holtmann 	switch (opcode) {
2176a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2177a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2178a9de9248SMarcel Holtmann 		break;
2179a9de9248SMarcel Holtmann 
21804d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
21814d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
21824d93483bSAndre Guedes 		break;
21834d93483bSAndre Guedes 
2184a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2185a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2186a9de9248SMarcel Holtmann 		break;
2187a9de9248SMarcel Holtmann 
2188a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2189a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2190a9de9248SMarcel Holtmann 		break;
2191a9de9248SMarcel Holtmann 
2192a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2193a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2194a9de9248SMarcel Holtmann 		break;
2195a9de9248SMarcel Holtmann 
2196e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2197e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2198e4e8e37cSMarcel Holtmann 		break;
2199e4e8e37cSMarcel Holtmann 
2200a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2201a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2202a9de9248SMarcel Holtmann 		break;
2203a9de9248SMarcel Holtmann 
2204e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2205e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2206e4e8e37cSMarcel Holtmann 		break;
2207e4e8e37cSMarcel Holtmann 
2208e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2209e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2210e4e8e37cSMarcel Holtmann 		break;
2211e4e8e37cSMarcel Holtmann 
2212a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2213a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2214a9de9248SMarcel Holtmann 		break;
2215a9de9248SMarcel Holtmann 
2216a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2217a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2218a9de9248SMarcel Holtmann 		break;
2219a9de9248SMarcel Holtmann 
2220a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2221a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2222a9de9248SMarcel Holtmann 		break;
2223a9de9248SMarcel Holtmann 
2224a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2225a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2226a9de9248SMarcel Holtmann 		break;
2227a9de9248SMarcel Holtmann 
2228a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2229a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2230a9de9248SMarcel Holtmann 		break;
2231a9de9248SMarcel Holtmann 
2232a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2233a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2234a9de9248SMarcel Holtmann 		break;
2235a9de9248SMarcel Holtmann 
2236a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2237a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2238a9de9248SMarcel Holtmann 		break;
2239a9de9248SMarcel Holtmann 
2240a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2241a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2242a9de9248SMarcel Holtmann 		break;
2243a9de9248SMarcel Holtmann 
2244a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2245a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2246a9de9248SMarcel Holtmann 		break;
2247a9de9248SMarcel Holtmann 
2248a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2249a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2250a9de9248SMarcel Holtmann 		break;
2251a9de9248SMarcel Holtmann 
2252a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2253a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2254a9de9248SMarcel Holtmann 		break;
2255a9de9248SMarcel Holtmann 
2256333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2257333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2258333140b5SMarcel Holtmann 		break;
2259333140b5SMarcel Holtmann 
2260a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2261a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2262a9de9248SMarcel Holtmann 		break;
2263a9de9248SMarcel Holtmann 
2264a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2265a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2266a9de9248SMarcel Holtmann 		break;
2267a9de9248SMarcel Holtmann 
2268a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2269a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2270a9de9248SMarcel Holtmann 		break;
2271a9de9248SMarcel Holtmann 
2272971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2273971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2274971e3a4bSAndre Guedes 		break;
2275971e3a4bSAndre Guedes 
2276a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2277a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2278a9de9248SMarcel Holtmann 		break;
2279a9de9248SMarcel Holtmann 
2280a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2281a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2282a9de9248SMarcel Holtmann 		break;
2283a9de9248SMarcel Holtmann 
2284350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2285350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2286350ee4cfSAndrei Emeltchenko 		break;
2287350ee4cfSAndrei Emeltchenko 
228823bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
228923bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
229023bb5763SJohan Hedberg 		break;
229123bb5763SJohan Hedberg 
22921e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22931e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22941e89cffbSAndrei Emeltchenko 		break;
22951e89cffbSAndrei Emeltchenko 
2296928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2297928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2298928abaa7SAndrei Emeltchenko 		break;
2299928abaa7SAndrei Emeltchenko 
2300b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2301b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2302b0916ea0SJohan Hedberg 		break;
2303b0916ea0SJohan Hedberg 
2304d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2305d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2306d5859e22SJohan Hedberg 		break;
2307d5859e22SJohan Hedberg 
2308d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2309d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2310d5859e22SJohan Hedberg 		break;
2311d5859e22SJohan Hedberg 
2312d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2313d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2314d5859e22SJohan Hedberg 		break;
2315d5859e22SJohan Hedberg 
2316d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2317d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2318d5859e22SJohan Hedberg 		break;
2319d5859e22SJohan Hedberg 
2320980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2321980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2322980e1a53SJohan Hedberg 		break;
2323980e1a53SJohan Hedberg 
2324980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2325980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2326980e1a53SJohan Hedberg 		break;
2327980e1a53SJohan Hedberg 
2328c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2329c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2330c35938b2SSzymon Janc 		break;
2331c35938b2SSzymon Janc 
23326ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
23336ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
23346ed58ec5SVille Tervo 		break;
23356ed58ec5SVille Tervo 
2336a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2337a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2338a5c29683SJohan Hedberg 		break;
2339a5c29683SJohan Hedberg 
2340a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2341a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2342a5c29683SJohan Hedberg 		break;
2343a5c29683SJohan Hedberg 
23441143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
23451143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
23461143d458SBrian Gix 		break;
23471143d458SBrian Gix 
23481143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23491143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
235016cde993SSzymon Janc 		break;
235107f7fa5dSAndre Guedes 
235207f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
235307f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
23541143d458SBrian Gix 		break;
23551143d458SBrian Gix 
2356eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2357eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2358eb9d91f5SAndre Guedes 		break;
2359eb9d91f5SAndre Guedes 
2360a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2361a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2362a7a595f6SVinicius Costa Gomes 		break;
2363a7a595f6SVinicius Costa Gomes 
2364a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2365a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2366a7a595f6SVinicius Costa Gomes 		break;
2367a7a595f6SVinicius Costa Gomes 
2368f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2369f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2370f9b49306SAndre Guedes 		break;
2371f9b49306SAndre Guedes 
2372a9de9248SMarcel Holtmann 	default:
2373a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2374a9de9248SMarcel Holtmann 		break;
2375a9de9248SMarcel Holtmann 	}
2376a9de9248SMarcel Holtmann 
23776bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23786bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23796bd32326SVille Tervo 
2380a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2381a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2382a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2383c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2384a9de9248SMarcel Holtmann 	}
2385a9de9248SMarcel Holtmann }
2386a9de9248SMarcel Holtmann 
2387a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2388a9de9248SMarcel Holtmann {
2389a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2390a9de9248SMarcel Holtmann 	__u16 opcode;
2391a9de9248SMarcel Holtmann 
2392a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2393a9de9248SMarcel Holtmann 
2394a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2395a9de9248SMarcel Holtmann 
2396a9de9248SMarcel Holtmann 	switch (opcode) {
2397a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2398a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2399a9de9248SMarcel Holtmann 		break;
2400a9de9248SMarcel Holtmann 
2401a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2402a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2403a9de9248SMarcel Holtmann 		break;
2404a9de9248SMarcel Holtmann 
2405a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2406a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2407a9de9248SMarcel Holtmann 		break;
2408a9de9248SMarcel Holtmann 
2409f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2410f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2411f8558555SMarcel Holtmann 		break;
2412f8558555SMarcel Holtmann 
2413f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2414f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2415f8558555SMarcel Holtmann 		break;
2416f8558555SMarcel Holtmann 
2417a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2418a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2419a9de9248SMarcel Holtmann 		break;
2420a9de9248SMarcel Holtmann 
2421769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2422769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2423769be974SMarcel Holtmann 		break;
2424769be974SMarcel Holtmann 
2425769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2426769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2427769be974SMarcel Holtmann 		break;
2428769be974SMarcel Holtmann 
2429a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2430a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2431a9de9248SMarcel Holtmann 		break;
2432a9de9248SMarcel Holtmann 
2433a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2434a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2435a9de9248SMarcel Holtmann 		break;
2436a9de9248SMarcel Holtmann 
2437a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2438a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2439a9de9248SMarcel Holtmann 		break;
2440a9de9248SMarcel Holtmann 
24418962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
244288c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
24438962ee74SJohan Hedberg 		break;
24448962ee74SJohan Hedberg 
2445fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2446fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2447fcd89c09SVille Tervo 		break;
2448fcd89c09SVille Tervo 
2449a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2450a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2451a7a595f6SVinicius Costa Gomes 		break;
2452a7a595f6SVinicius Costa Gomes 
2453a9de9248SMarcel Holtmann 	default:
2454a9de9248SMarcel Holtmann 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
2455a9de9248SMarcel Holtmann 		break;
2456a9de9248SMarcel Holtmann 	}
2457a9de9248SMarcel Holtmann 
24586bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
24596bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24606bd32326SVille Tervo 
246110572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2462a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2463a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2464c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2465a9de9248SMarcel Holtmann 	}
2466a9de9248SMarcel Holtmann }
2467a9de9248SMarcel Holtmann 
2468a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2469a9de9248SMarcel Holtmann {
2470a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2471a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2472a9de9248SMarcel Holtmann 
2473a9de9248SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2474a9de9248SMarcel Holtmann 
2475a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2476a9de9248SMarcel Holtmann 
2477a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2478a9de9248SMarcel Holtmann 	if (conn) {
2479a9de9248SMarcel Holtmann 		if (!ev->status) {
2480a9de9248SMarcel Holtmann 			if (ev->role)
2481a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2482a9de9248SMarcel Holtmann 			else
2483a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2484a9de9248SMarcel Holtmann 		}
2485a9de9248SMarcel Holtmann 
248651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2487a9de9248SMarcel Holtmann 
2488a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2489a9de9248SMarcel Holtmann 	}
2490a9de9248SMarcel Holtmann 
2491a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2492a9de9248SMarcel Holtmann }
2493a9de9248SMarcel Holtmann 
24941da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24951da177e4SLinus Torvalds {
2496a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24971da177e4SLinus Torvalds 	int i;
24981da177e4SLinus Torvalds 
249932ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
250032ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
250132ac5b9bSAndrei Emeltchenko 		return;
250232ac5b9bSAndrei Emeltchenko 	}
250332ac5b9bSAndrei Emeltchenko 
2504c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2505c5993de8SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
25061da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
25071da177e4SLinus Torvalds 		return;
25081da177e4SLinus Torvalds 	}
25091da177e4SLinus Torvalds 
2510c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2511c5993de8SAndrei Emeltchenko 
2512613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2513613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
25141da177e4SLinus Torvalds 		struct hci_conn *conn;
25151da177e4SLinus Torvalds 		__u16  handle, count;
25161da177e4SLinus Torvalds 
2517613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2518613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
25191da177e4SLinus Torvalds 
25201da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2521f4280918SAndrei Emeltchenko 		if (!conn)
2522f4280918SAndrei Emeltchenko 			continue;
2523f4280918SAndrei Emeltchenko 
25241da177e4SLinus Torvalds 		conn->sent -= count;
25251da177e4SLinus Torvalds 
2526f4280918SAndrei Emeltchenko 		switch (conn->type) {
2527f4280918SAndrei Emeltchenko 		case ACL_LINK:
252870f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
252970f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
25301da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2531f4280918SAndrei Emeltchenko 			break;
2532f4280918SAndrei Emeltchenko 
2533f4280918SAndrei Emeltchenko 		case LE_LINK:
25346ed58ec5SVille Tervo 			if (hdev->le_pkts) {
25356ed58ec5SVille Tervo 				hdev->le_cnt += count;
25366ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
25376ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
25386ed58ec5SVille Tervo 			} else {
25396ed58ec5SVille Tervo 				hdev->acl_cnt += count;
25406ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
25416ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
25426ed58ec5SVille Tervo 			}
2543f4280918SAndrei Emeltchenko 			break;
2544f4280918SAndrei Emeltchenko 
2545f4280918SAndrei Emeltchenko 		case SCO_LINK:
254670f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
254770f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
25485b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2549f4280918SAndrei Emeltchenko 			break;
2550f4280918SAndrei Emeltchenko 
2551f4280918SAndrei Emeltchenko 		default:
2552f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2553f4280918SAndrei Emeltchenko 			break;
25541da177e4SLinus Torvalds 		}
25551da177e4SLinus Torvalds 	}
2556a9de9248SMarcel Holtmann 
25573eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25581da177e4SLinus Torvalds }
25591da177e4SLinus Torvalds 
256025e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
256125e89e99SAndrei Emeltchenko 					   struct sk_buff *skb)
256225e89e99SAndrei Emeltchenko {
256325e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
256425e89e99SAndrei Emeltchenko 	int i;
256525e89e99SAndrei Emeltchenko 
256625e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
256725e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
256825e89e99SAndrei Emeltchenko 		return;
256925e89e99SAndrei Emeltchenko 	}
257025e89e99SAndrei Emeltchenko 
257125e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
257225e89e99SAndrei Emeltchenko 			ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
257325e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
257425e89e99SAndrei Emeltchenko 		return;
257525e89e99SAndrei Emeltchenko 	}
257625e89e99SAndrei Emeltchenko 
257725e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
257825e89e99SAndrei Emeltchenko 								ev->num_hndl);
257925e89e99SAndrei Emeltchenko 
258025e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
258125e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
258225e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
258325e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
258425e89e99SAndrei Emeltchenko 
258525e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
258625e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
258725e89e99SAndrei Emeltchenko 
258825e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
258925e89e99SAndrei Emeltchenko 		if (!conn)
259025e89e99SAndrei Emeltchenko 			continue;
259125e89e99SAndrei Emeltchenko 
259225e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
259325e89e99SAndrei Emeltchenko 
259425e89e99SAndrei Emeltchenko 		switch (conn->type) {
259525e89e99SAndrei Emeltchenko 		case ACL_LINK:
259625e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
259725e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
259825e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
259925e89e99SAndrei Emeltchenko 			break;
260025e89e99SAndrei Emeltchenko 
260125e89e99SAndrei Emeltchenko 		default:
260225e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
260325e89e99SAndrei Emeltchenko 			break;
260425e89e99SAndrei Emeltchenko 		}
260525e89e99SAndrei Emeltchenko 	}
260625e89e99SAndrei Emeltchenko 
260725e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
260825e89e99SAndrei Emeltchenko }
260925e89e99SAndrei Emeltchenko 
261004837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
26111da177e4SLinus Torvalds {
2612a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
261304837f64SMarcel Holtmann 	struct hci_conn *conn;
26141da177e4SLinus Torvalds 
26151da177e4SLinus Torvalds 	BT_DBG("%s status %d", hdev->name, ev->status);
26161da177e4SLinus Torvalds 
26171da177e4SLinus Torvalds 	hci_dev_lock(hdev);
26181da177e4SLinus Torvalds 
261904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
262004837f64SMarcel Holtmann 	if (conn) {
262104837f64SMarcel Holtmann 		conn->mode = ev->mode;
262204837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
262304837f64SMarcel Holtmann 
262451a8efd7SJohan Hedberg 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
262504837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
262658a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
262704837f64SMarcel Holtmann 			else
262858a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
262904837f64SMarcel Holtmann 		}
2630e73439d8SMarcel Holtmann 
263151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2632e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
263304837f64SMarcel Holtmann 	}
263404837f64SMarcel Holtmann 
263504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
263604837f64SMarcel Holtmann }
263704837f64SMarcel Holtmann 
26381da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26391da177e4SLinus Torvalds {
2640052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2641052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2642052b30b0SMarcel Holtmann 
2643a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2644052b30b0SMarcel Holtmann 
2645052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2646052b30b0SMarcel Holtmann 
2647052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2648b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2649b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2650b6f98044SWaldemar Rymarkiewicz 
2651b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2652052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2653052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2654052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2655052b30b0SMarcel Holtmann 	}
2656052b30b0SMarcel Holtmann 
2657a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
265803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
265903b555e1SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
2660a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2661a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2662a770bb5aSWaldemar Rymarkiewicz 
2663a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2664a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2665a770bb5aSWaldemar Rymarkiewicz 		else
2666a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2667a770bb5aSWaldemar Rymarkiewicz 
2668744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2669a770bb5aSWaldemar Rymarkiewicz 	}
2670980e1a53SJohan Hedberg 
2671b6f98044SWaldemar Rymarkiewicz unlock:
2672052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26731da177e4SLinus Torvalds }
26741da177e4SLinus Torvalds 
26751da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26761da177e4SLinus Torvalds {
267755ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
267855ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
267955ed8ca1SJohan Hedberg 	struct hci_conn *conn;
268055ed8ca1SJohan Hedberg 	struct link_key *key;
268155ed8ca1SJohan Hedberg 
2682a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
268355ed8ca1SJohan Hedberg 
2684a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
268555ed8ca1SJohan Hedberg 		return;
268655ed8ca1SJohan Hedberg 
268755ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
268855ed8ca1SJohan Hedberg 
268955ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
269055ed8ca1SJohan Hedberg 	if (!key) {
269155ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
269255ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
269355ed8ca1SJohan Hedberg 		goto not_found;
269455ed8ca1SJohan Hedberg 	}
269555ed8ca1SJohan Hedberg 
269655ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
269755ed8ca1SJohan Hedberg 							batostr(&ev->bdaddr));
269855ed8ca1SJohan Hedberg 
2699a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2700b6020ba0SWaldemar Rymarkiewicz 				key->type == HCI_LK_DEBUG_COMBINATION) {
270155ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
270255ed8ca1SJohan Hedberg 		goto not_found;
270355ed8ca1SJohan Hedberg 	}
270455ed8ca1SJohan Hedberg 
270555ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
270660b83f57SWaldemar Rymarkiewicz 	if (conn) {
270760b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
270860b83f57SWaldemar Rymarkiewicz 				conn->auth_type != 0xff &&
270960b83f57SWaldemar Rymarkiewicz 				(conn->auth_type & 0x01)) {
271055ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
271155ed8ca1SJohan Hedberg 			goto not_found;
271255ed8ca1SJohan Hedberg 		}
271355ed8ca1SJohan Hedberg 
271460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
271560b83f57SWaldemar Rymarkiewicz 				conn->pending_sec_level == BT_SECURITY_HIGH) {
271660b83f57SWaldemar Rymarkiewicz 			BT_DBG("%s ignoring key unauthenticated for high \
271760b83f57SWaldemar Rymarkiewicz 							security", hdev->name);
271860b83f57SWaldemar Rymarkiewicz 			goto not_found;
271960b83f57SWaldemar Rymarkiewicz 		}
272060b83f57SWaldemar Rymarkiewicz 
272160b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
272260b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
272360b83f57SWaldemar Rymarkiewicz 	}
272460b83f57SWaldemar Rymarkiewicz 
272555ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
272655ed8ca1SJohan Hedberg 	memcpy(cp.link_key, key->val, 16);
272755ed8ca1SJohan Hedberg 
272855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
272955ed8ca1SJohan Hedberg 
273055ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
273155ed8ca1SJohan Hedberg 
273255ed8ca1SJohan Hedberg 	return;
273355ed8ca1SJohan Hedberg 
273455ed8ca1SJohan Hedberg not_found:
273555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
273655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
27371da177e4SLinus Torvalds }
27381da177e4SLinus Torvalds 
27391da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
27401da177e4SLinus Torvalds {
2741052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2742052b30b0SMarcel Holtmann 	struct hci_conn *conn;
274355ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2744052b30b0SMarcel Holtmann 
2745a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2746052b30b0SMarcel Holtmann 
2747052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2748052b30b0SMarcel Holtmann 
2749052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2750052b30b0SMarcel Holtmann 	if (conn) {
2751052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2752052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2753980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
275413d39315SWaldemar Rymarkiewicz 
275513d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
275613d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
275713d39315SWaldemar Rymarkiewicz 
2758052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2759052b30b0SMarcel Holtmann 	}
2760052b30b0SMarcel Holtmann 
2761a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2762d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
276355ed8ca1SJohan Hedberg 							ev->key_type, pin_len);
276455ed8ca1SJohan Hedberg 
2765052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27661da177e4SLinus Torvalds }
27671da177e4SLinus Torvalds 
276804837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
276904837f64SMarcel Holtmann {
2770a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
277104837f64SMarcel Holtmann 	struct hci_conn *conn;
277204837f64SMarcel Holtmann 
277304837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
277404837f64SMarcel Holtmann 
277504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
277604837f64SMarcel Holtmann 
277704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27781da177e4SLinus Torvalds 	if (conn && !ev->status) {
27791da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27801da177e4SLinus Torvalds 
2781cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2782cc11b9c1SAndrei Emeltchenko 		if (ie) {
27831da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27841da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27851da177e4SLinus Torvalds 		}
27861da177e4SLinus Torvalds 	}
27871da177e4SLinus Torvalds 
27881da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27891da177e4SLinus Torvalds }
27901da177e4SLinus Torvalds 
2791a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2792a8746417SMarcel Holtmann {
2793a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2794a8746417SMarcel Holtmann 	struct hci_conn *conn;
2795a8746417SMarcel Holtmann 
2796a8746417SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2797a8746417SMarcel Holtmann 
2798a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2799a8746417SMarcel Holtmann 
2800a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2801a8746417SMarcel Holtmann 	if (conn && !ev->status)
2802a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2803a8746417SMarcel Holtmann 
2804a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2805a8746417SMarcel Holtmann }
2806a8746417SMarcel Holtmann 
280785a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
280885a1e930SMarcel Holtmann {
2809a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
281085a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
281185a1e930SMarcel Holtmann 
281285a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
281385a1e930SMarcel Holtmann 
281485a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
281585a1e930SMarcel Holtmann 
2816cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2817cc11b9c1SAndrei Emeltchenko 	if (ie) {
281885a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
281985a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
282085a1e930SMarcel Holtmann 	}
282185a1e930SMarcel Holtmann 
282285a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
282385a1e930SMarcel Holtmann }
282485a1e930SMarcel Holtmann 
2825a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
2826a9de9248SMarcel Holtmann {
2827a9de9248SMarcel Holtmann 	struct inquiry_data data;
2828a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2829388fc8faSJohan Hedberg 	bool name_known, ssp;
2830a9de9248SMarcel Holtmann 
2831a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2832a9de9248SMarcel Holtmann 
2833a9de9248SMarcel Holtmann 	if (!num_rsp)
2834a9de9248SMarcel Holtmann 		return;
2835a9de9248SMarcel Holtmann 
28361519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
28371519cc17SAndre Guedes 		return;
28381519cc17SAndre Guedes 
2839a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2840a9de9248SMarcel Holtmann 
2841a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2842138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2843138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2844a9de9248SMarcel Holtmann 
2845e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2846a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2847a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2848a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2849a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2850a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2851a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2852a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
285341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28543175405bSJohan Hedberg 
28553175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2856388fc8faSJohan Hedberg 							      false, &ssp);
285748264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2858e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2859388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2860a9de9248SMarcel Holtmann 		}
2861a9de9248SMarcel Holtmann 	} else {
2862a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2863a9de9248SMarcel Holtmann 
2864e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2865a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2866a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2867a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2868a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2869a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2870a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2871a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
287241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28733175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2874388fc8faSJohan Hedberg 							      false, &ssp);
287548264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2876e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2877388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2878a9de9248SMarcel Holtmann 		}
2879a9de9248SMarcel Holtmann 	}
2880a9de9248SMarcel Holtmann 
2881a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2882a9de9248SMarcel Holtmann }
2883a9de9248SMarcel Holtmann 
2884a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
2885a9de9248SMarcel Holtmann {
288641a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
288741a96212SMarcel Holtmann 	struct hci_conn *conn;
288841a96212SMarcel Holtmann 
2889a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
289041a96212SMarcel Holtmann 
289141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
289241a96212SMarcel Holtmann 
289341a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2894ccd556feSJohan Hedberg 	if (!conn)
2895ccd556feSJohan Hedberg 		goto unlock;
2896ccd556feSJohan Hedberg 
2897769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
289841a96212SMarcel Holtmann 		struct inquiry_entry *ie;
289941a96212SMarcel Holtmann 
2900cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2901cc11b9c1SAndrei Emeltchenko 		if (ie)
290202b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
290341a96212SMarcel Holtmann 
290402b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
290558a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
290641a96212SMarcel Holtmann 	}
290741a96212SMarcel Holtmann 
2908ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2909ccd556feSJohan Hedberg 		goto unlock;
2910ccd556feSJohan Hedberg 
2911671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2912127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2913127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2914127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2915127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2916127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2917b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2918b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
291908c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2920b644ba33SJohan Hedberg 				      conn->dev_class);
2921392599b9SJohan Hedberg 
2922127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2923769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2924769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2925769be974SMarcel Holtmann 		hci_conn_put(conn);
2926769be974SMarcel Holtmann 	}
2927769be974SMarcel Holtmann 
2928ccd556feSJohan Hedberg unlock:
292941a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2930a9de9248SMarcel Holtmann }
2931a9de9248SMarcel Holtmann 
2932a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2933a9de9248SMarcel Holtmann {
2934b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2935b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2936b6a0dc82SMarcel Holtmann 
2937b6a0dc82SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
2938b6a0dc82SMarcel Holtmann 
2939b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2940b6a0dc82SMarcel Holtmann 
2941b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
29429dc0a3afSMarcel Holtmann 	if (!conn) {
29439dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
29449dc0a3afSMarcel Holtmann 			goto unlock;
29459dc0a3afSMarcel Holtmann 
29469dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2947b6a0dc82SMarcel Holtmann 		if (!conn)
2948b6a0dc82SMarcel Holtmann 			goto unlock;
2949b6a0dc82SMarcel Holtmann 
29509dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
29519dc0a3afSMarcel Holtmann 	}
29529dc0a3afSMarcel Holtmann 
2953732547f9SMarcel Holtmann 	switch (ev->status) {
2954732547f9SMarcel Holtmann 	case 0x00:
2955732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2956732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2957732547f9SMarcel Holtmann 
29589eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2959732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2960732547f9SMarcel Holtmann 		break;
2961732547f9SMarcel Holtmann 
2962705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2963732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29641038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2965732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2966732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2967efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2968efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2969efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2970efc7688bSMarcel Holtmann 			goto unlock;
2971efc7688bSMarcel Holtmann 		}
2972732547f9SMarcel Holtmann 		/* fall through */
2973efc7688bSMarcel Holtmann 
2974732547f9SMarcel Holtmann 	default:
2975b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2976732547f9SMarcel Holtmann 		break;
2977732547f9SMarcel Holtmann 	}
2978b6a0dc82SMarcel Holtmann 
2979b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2980b6a0dc82SMarcel Holtmann 	if (ev->status)
2981b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2982b6a0dc82SMarcel Holtmann 
2983b6a0dc82SMarcel Holtmann unlock:
2984b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2985a9de9248SMarcel Holtmann }
2986a9de9248SMarcel Holtmann 
2987a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
2988a9de9248SMarcel Holtmann {
2989a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2990a9de9248SMarcel Holtmann }
2991a9de9248SMarcel Holtmann 
299204837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
299304837f64SMarcel Holtmann {
2994a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
299504837f64SMarcel Holtmann 
299604837f64SMarcel Holtmann 	BT_DBG("%s status %d", hdev->name, ev->status);
299704837f64SMarcel Holtmann }
299804837f64SMarcel Holtmann 
2999a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
3000a9de9248SMarcel Holtmann {
3001a9de9248SMarcel Holtmann 	struct inquiry_data data;
3002a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3003a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
30049d939d94SVishal Agarwal 	size_t eir_len;
3005a9de9248SMarcel Holtmann 
3006a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3007a9de9248SMarcel Holtmann 
3008a9de9248SMarcel Holtmann 	if (!num_rsp)
3009a9de9248SMarcel Holtmann 		return;
3010a9de9248SMarcel Holtmann 
30111519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30121519cc17SAndre Guedes 		return;
30131519cc17SAndre Guedes 
3014a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3015a9de9248SMarcel Holtmann 
3016e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3017388fc8faSJohan Hedberg 		bool name_known, ssp;
3018561aafbcSJohan Hedberg 
3019a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3020a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3021a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3022a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3023a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3024a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3025a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
302641a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3027561aafbcSJohan Hedberg 
3028a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
30294ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
30304ddb1930SJohan Hedberg 						       sizeof(info->data),
30314ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3032561aafbcSJohan Hedberg 		else
3033561aafbcSJohan Hedberg 			name_known = true;
3034561aafbcSJohan Hedberg 
3035388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3036388fc8faSJohan Hedberg 						      &ssp);
30379d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
303848264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
303904124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
30409d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3041a9de9248SMarcel Holtmann 	}
3042a9de9248SMarcel Holtmann 
3043a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3044a9de9248SMarcel Holtmann }
3045a9de9248SMarcel Holtmann 
304617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn)
304717fa4b9dSJohan Hedberg {
304817fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
304917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
305017fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
305117fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
305217fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
305317fa4b9dSJohan Hedberg 			return 0x02;
305417fa4b9dSJohan Hedberg 		else
305517fa4b9dSJohan Hedberg 			return 0x03;
305617fa4b9dSJohan Hedberg 	}
305717fa4b9dSJohan Hedberg 
305817fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
305917fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
306058797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
306117fa4b9dSJohan Hedberg 
306217fa4b9dSJohan Hedberg 	return conn->auth_type;
306317fa4b9dSJohan Hedberg }
306417fa4b9dSJohan Hedberg 
30650493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
30660493684eSMarcel Holtmann {
30670493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
30680493684eSMarcel Holtmann 	struct hci_conn *conn;
30690493684eSMarcel Holtmann 
30700493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30710493684eSMarcel Holtmann 
30720493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30730493684eSMarcel Holtmann 
30740493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
307503b555e1SJohan Hedberg 	if (!conn)
307603b555e1SJohan Hedberg 		goto unlock;
307703b555e1SJohan Hedberg 
30780493684eSMarcel Holtmann 	hci_conn_hold(conn);
30790493684eSMarcel Holtmann 
3080a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
308103b555e1SJohan Hedberg 		goto unlock;
308203b555e1SJohan Hedberg 
3083a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
308403b555e1SJohan Hedberg 			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
308517fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
308617fa4b9dSJohan Hedberg 
308717fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30887a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
30897a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
30907a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
30917a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
30927cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
30937cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
309417fa4b9dSJohan Hedberg 
309558a681efSJohan Hedberg 		if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
3096ce85ee13SSzymon Janc 				hci_find_remote_oob_data(hdev, &conn->dst))
3097ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3098ce85ee13SSzymon Janc 		else
3099ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3100ce85ee13SSzymon Janc 
310117fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
310217fa4b9dSJohan Hedberg 							sizeof(cp), &cp);
310303b555e1SJohan Hedberg 	} else {
310403b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
310503b555e1SJohan Hedberg 
310603b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31079f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
310803b555e1SJohan Hedberg 
310903b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
311003b555e1SJohan Hedberg 							sizeof(cp), &cp);
311103b555e1SJohan Hedberg 	}
311203b555e1SJohan Hedberg 
311303b555e1SJohan Hedberg unlock:
311403b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
311503b555e1SJohan Hedberg }
311603b555e1SJohan Hedberg 
311703b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
311803b555e1SJohan Hedberg {
311903b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
312003b555e1SJohan Hedberg 	struct hci_conn *conn;
312103b555e1SJohan Hedberg 
312203b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
312303b555e1SJohan Hedberg 
312403b555e1SJohan Hedberg 	hci_dev_lock(hdev);
312503b555e1SJohan Hedberg 
312603b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
312703b555e1SJohan Hedberg 	if (!conn)
312803b555e1SJohan Hedberg 		goto unlock;
312903b555e1SJohan Hedberg 
313003b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
313103b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
313258a681efSJohan Hedberg 	if (ev->oob_data)
313358a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
313403b555e1SJohan Hedberg 
313503b555e1SJohan Hedberg unlock:
31360493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31370493684eSMarcel Holtmann }
31380493684eSMarcel Holtmann 
3139a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
3140a5c29683SJohan Hedberg 							struct sk_buff *skb)
3141a5c29683SJohan Hedberg {
3142a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
314355bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
31447a828908SJohan Hedberg 	struct hci_conn *conn;
3145a5c29683SJohan Hedberg 
3146a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3147a5c29683SJohan Hedberg 
3148a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3149a5c29683SJohan Hedberg 
3150a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
31517a828908SJohan Hedberg 		goto unlock;
31527a828908SJohan Hedberg 
31537a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31547a828908SJohan Hedberg 	if (!conn)
31557a828908SJohan Hedberg 		goto unlock;
31567a828908SJohan Hedberg 
31577a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
31587a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
31597a828908SJohan Hedberg 
31607a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
31617a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
31627a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
31637a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
31647a828908SJohan Hedberg 	 * bit set. */
31657a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
31667a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
31677a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
31687a828908SJohan Hedberg 					sizeof(ev->bdaddr), &ev->bdaddr);
31697a828908SJohan Hedberg 		goto unlock;
31707a828908SJohan Hedberg 	}
31717a828908SJohan Hedberg 
31727a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
31737a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
31747a828908SJohan Hedberg 				(!rem_mitm || conn->io_capability == 0x03)) {
317555bc1a37SJohan Hedberg 
317655bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
317755bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
317855bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
317951a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
318055bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
318155bc1a37SJohan Hedberg 			confirm_hint = 1;
318255bc1a37SJohan Hedberg 			goto confirm;
318355bc1a37SJohan Hedberg 		}
318455bc1a37SJohan Hedberg 
31859f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
31869f61656aSJohan Hedberg 						hdev->auto_accept_delay);
31879f61656aSJohan Hedberg 
31889f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
31899f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
31909f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
31919f61656aSJohan Hedberg 			goto unlock;
31929f61656aSJohan Hedberg 		}
31939f61656aSJohan Hedberg 
31947a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
31957a828908SJohan Hedberg 						sizeof(ev->bdaddr), &ev->bdaddr);
31967a828908SJohan Hedberg 		goto unlock;
31977a828908SJohan Hedberg 	}
31987a828908SJohan Hedberg 
319955bc1a37SJohan Hedberg confirm:
3200272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
320155bc1a37SJohan Hedberg 				  confirm_hint);
3202a5c29683SJohan Hedberg 
32037a828908SJohan Hedberg unlock:
3204a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3205a5c29683SJohan Hedberg }
3206a5c29683SJohan Hedberg 
32071143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
32081143d458SBrian Gix 							struct sk_buff *skb)
32091143d458SBrian Gix {
32101143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
32111143d458SBrian Gix 
32121143d458SBrian Gix 	BT_DBG("%s", hdev->name);
32131143d458SBrian Gix 
32141143d458SBrian Gix 	hci_dev_lock(hdev);
32151143d458SBrian Gix 
3216a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3217272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
32181143d458SBrian Gix 
32191143d458SBrian Gix 	hci_dev_unlock(hdev);
32201143d458SBrian Gix }
32211143d458SBrian Gix 
32220493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
32230493684eSMarcel Holtmann {
32240493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
32250493684eSMarcel Holtmann 	struct hci_conn *conn;
32260493684eSMarcel Holtmann 
32270493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
32280493684eSMarcel Holtmann 
32290493684eSMarcel Holtmann 	hci_dev_lock(hdev);
32300493684eSMarcel Holtmann 
32310493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32322a611692SJohan Hedberg 	if (!conn)
32332a611692SJohan Hedberg 		goto unlock;
32342a611692SJohan Hedberg 
32352a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
32362a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
32372a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
32382a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
32392a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
324051a8efd7SJohan Hedberg 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
3241bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3242bab73cb6SJohan Hedberg 				 ev->status);
32432a611692SJohan Hedberg 
32440493684eSMarcel Holtmann 	hci_conn_put(conn);
32450493684eSMarcel Holtmann 
32462a611692SJohan Hedberg unlock:
32470493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32480493684eSMarcel Holtmann }
32490493684eSMarcel Holtmann 
325041a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
325141a96212SMarcel Holtmann {
325241a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
325341a96212SMarcel Holtmann 	struct inquiry_entry *ie;
325441a96212SMarcel Holtmann 
325541a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
325641a96212SMarcel Holtmann 
325741a96212SMarcel Holtmann 	hci_dev_lock(hdev);
325841a96212SMarcel Holtmann 
3259cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3260cc11b9c1SAndrei Emeltchenko 	if (ie)
326102b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
326241a96212SMarcel Holtmann 
326341a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
326441a96212SMarcel Holtmann }
326541a96212SMarcel Holtmann 
32662763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
32672763eda6SSzymon Janc 						   struct sk_buff *skb)
32682763eda6SSzymon Janc {
32692763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
32702763eda6SSzymon Janc 	struct oob_data *data;
32712763eda6SSzymon Janc 
32722763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
32732763eda6SSzymon Janc 
32742763eda6SSzymon Janc 	hci_dev_lock(hdev);
32752763eda6SSzymon Janc 
3276a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3277e1ba1f15SSzymon Janc 		goto unlock;
3278e1ba1f15SSzymon Janc 
32792763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
32802763eda6SSzymon Janc 	if (data) {
32812763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
32822763eda6SSzymon Janc 
32832763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32842763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
32852763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
32862763eda6SSzymon Janc 
32872763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
32882763eda6SSzymon Janc 									&cp);
32892763eda6SSzymon Janc 	} else {
32902763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
32912763eda6SSzymon Janc 
32922763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
32932763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
32942763eda6SSzymon Janc 									&cp);
32952763eda6SSzymon Janc 	}
32962763eda6SSzymon Janc 
3297e1ba1f15SSzymon Janc unlock:
32982763eda6SSzymon Janc 	hci_dev_unlock(hdev);
32992763eda6SSzymon Janc }
33002763eda6SSzymon Janc 
3301fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3302fcd89c09SVille Tervo {
3303fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3304fcd89c09SVille Tervo 	struct hci_conn *conn;
3305fcd89c09SVille Tervo 
3306fcd89c09SVille Tervo 	BT_DBG("%s status %d", hdev->name, ev->status);
3307fcd89c09SVille Tervo 
3308fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3309fcd89c09SVille Tervo 
3310fcd89c09SVille Tervo 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
3311b62f328bSVille Tervo 	if (!conn) {
3312b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3313b62f328bSVille Tervo 		if (!conn) {
3314b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3315b62f328bSVille Tervo 			hci_dev_unlock(hdev);
3316b62f328bSVille Tervo 			return;
3317b62f328bSVille Tervo 		}
331829b7988aSAndre Guedes 
331929b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3320b62f328bSVille Tervo 	}
3321fcd89c09SVille Tervo 
3322fcd89c09SVille Tervo 	if (ev->status) {
332348264f06SJohan Hedberg 		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
332448264f06SJohan Hedberg 						conn->dst_type, ev->status);
3325fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, ev->status);
3326fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
3327fcd89c09SVille Tervo 		hci_conn_del(conn);
3328fcd89c09SVille Tervo 		goto unlock;
3329fcd89c09SVille Tervo 	}
3330fcd89c09SVille Tervo 
3331b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3332b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
333395b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
333483bc71b4SVinicius Costa Gomes 
33357b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3336fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3337fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3338fcd89c09SVille Tervo 
3339fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3340fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3341fcd89c09SVille Tervo 
3342fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3343fcd89c09SVille Tervo 
3344fcd89c09SVille Tervo unlock:
3345fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3346fcd89c09SVille Tervo }
3347fcd89c09SVille Tervo 
33489aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
33499aa04c91SAndre Guedes 						struct sk_buff *skb)
33509aa04c91SAndre Guedes {
3351e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3352e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
33533c9e9195SAndre Guedes 	s8 rssi;
33549aa04c91SAndre Guedes 
33559aa04c91SAndre Guedes 	hci_dev_lock(hdev);
33569aa04c91SAndre Guedes 
3357e95beb41SAndre Guedes 	while (num_reports--) {
3358e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3359e95beb41SAndre Guedes 
33603c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
33613c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
336204124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
33633c9e9195SAndre Guedes 
3364e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
33659aa04c91SAndre Guedes 	}
33669aa04c91SAndre Guedes 
33679aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
33689aa04c91SAndre Guedes }
33699aa04c91SAndre Guedes 
3370a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
3371a7a595f6SVinicius Costa Gomes 						struct sk_buff *skb)
3372a7a595f6SVinicius Costa Gomes {
3373a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3374a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3375bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3376a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3377c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3378a7a595f6SVinicius Costa Gomes 
3379e4666881SAndrei Emeltchenko 	BT_DBG("%s handle %d", hdev->name, __le16_to_cpu(ev->handle));
3380a7a595f6SVinicius Costa Gomes 
3381a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3382a7a595f6SVinicius Costa Gomes 
3383a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3384bea710feSVinicius Costa Gomes 	if (conn == NULL)
3385bea710feSVinicius Costa Gomes 		goto not_found;
3386a7a595f6SVinicius Costa Gomes 
3387bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3388bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3389bea710feSVinicius Costa Gomes 		goto not_found;
3390bea710feSVinicius Costa Gomes 
3391bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3392a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3393c9839a11SVinicius Costa Gomes 
3394c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3395c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3396a7a595f6SVinicius Costa Gomes 
3397a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3398a7a595f6SVinicius Costa Gomes 
3399c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3400c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3401c9839a11SVinicius Costa Gomes 		kfree(ltk);
3402c9839a11SVinicius Costa Gomes 	}
3403c9839a11SVinicius Costa Gomes 
3404a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3405bea710feSVinicius Costa Gomes 
3406bea710feSVinicius Costa Gomes 	return;
3407bea710feSVinicius Costa Gomes 
3408bea710feSVinicius Costa Gomes not_found:
3409bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3410bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3411bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3412a7a595f6SVinicius Costa Gomes }
3413a7a595f6SVinicius Costa Gomes 
3414fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3415fcd89c09SVille Tervo {
3416fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3417fcd89c09SVille Tervo 
3418fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3419fcd89c09SVille Tervo 
3420fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3421fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3422fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3423fcd89c09SVille Tervo 		break;
3424fcd89c09SVille Tervo 
34259aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
34269aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
34279aa04c91SAndre Guedes 		break;
34289aa04c91SAndre Guedes 
3429a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3430a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3431a7a595f6SVinicius Costa Gomes 		break;
3432a7a595f6SVinicius Costa Gomes 
3433fcd89c09SVille Tervo 	default:
3434fcd89c09SVille Tervo 		break;
3435fcd89c09SVille Tervo 	}
3436fcd89c09SVille Tervo }
3437fcd89c09SVille Tervo 
34381da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
34391da177e4SLinus Torvalds {
3440a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3441a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
34421da177e4SLinus Torvalds 
34431da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
34441da177e4SLinus Torvalds 
3445a9de9248SMarcel Holtmann 	switch (event) {
34461da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
34471da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
34481da177e4SLinus Torvalds 		break;
34491da177e4SLinus Torvalds 
34501da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
34511da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
34521da177e4SLinus Torvalds 		break;
34531da177e4SLinus Torvalds 
3454a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3455a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
345621d9e30eSMarcel Holtmann 		break;
345721d9e30eSMarcel Holtmann 
34581da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
34591da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
34601da177e4SLinus Torvalds 		break;
34611da177e4SLinus Torvalds 
34621da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
34631da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
34641da177e4SLinus Torvalds 		break;
34651da177e4SLinus Torvalds 
34661da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
34671da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
34681da177e4SLinus Torvalds 		break;
34691da177e4SLinus Torvalds 
3470a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3471a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3472a9de9248SMarcel Holtmann 		break;
3473a9de9248SMarcel Holtmann 
34741da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
34751da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
34761da177e4SLinus Torvalds 		break;
34771da177e4SLinus Torvalds 
3478a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3479a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3480a9de9248SMarcel Holtmann 		break;
3481a9de9248SMarcel Holtmann 
3482a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3483a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3484a9de9248SMarcel Holtmann 		break;
3485a9de9248SMarcel Holtmann 
3486a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3487a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3488a9de9248SMarcel Holtmann 		break;
3489a9de9248SMarcel Holtmann 
3490a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3491a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3492a9de9248SMarcel Holtmann 		break;
3493a9de9248SMarcel Holtmann 
3494a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3495a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3496a9de9248SMarcel Holtmann 		break;
3497a9de9248SMarcel Holtmann 
3498a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3499a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3500a9de9248SMarcel Holtmann 		break;
3501a9de9248SMarcel Holtmann 
3502a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3503a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3504a9de9248SMarcel Holtmann 		break;
3505a9de9248SMarcel Holtmann 
3506a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3507a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3508a9de9248SMarcel Holtmann 		break;
3509a9de9248SMarcel Holtmann 
3510a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3511a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
35121da177e4SLinus Torvalds 		break;
35131da177e4SLinus Torvalds 
35141da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
35151da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
35161da177e4SLinus Torvalds 		break;
35171da177e4SLinus Torvalds 
35181da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
35191da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
35201da177e4SLinus Torvalds 		break;
35211da177e4SLinus Torvalds 
35221da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
35231da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
35241da177e4SLinus Torvalds 		break;
35251da177e4SLinus Torvalds 
35261da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
35271da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
35281da177e4SLinus Torvalds 		break;
35291da177e4SLinus Torvalds 
3530a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3531a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3532a8746417SMarcel Holtmann 		break;
3533a8746417SMarcel Holtmann 
353485a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
353585a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
353685a1e930SMarcel Holtmann 		break;
353785a1e930SMarcel Holtmann 
3538a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3539a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3540a9de9248SMarcel Holtmann 		break;
3541a9de9248SMarcel Holtmann 
3542a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3543a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3544a9de9248SMarcel Holtmann 		break;
3545a9de9248SMarcel Holtmann 
3546a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3547a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3548a9de9248SMarcel Holtmann 		break;
3549a9de9248SMarcel Holtmann 
3550a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3551a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3552a9de9248SMarcel Holtmann 		break;
3553a9de9248SMarcel Holtmann 
355404837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
355504837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
355604837f64SMarcel Holtmann 		break;
355704837f64SMarcel Holtmann 
3558a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3559a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
35601da177e4SLinus Torvalds 		break;
35611da177e4SLinus Torvalds 
35620493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
35630493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
35640493684eSMarcel Holtmann 		break;
35650493684eSMarcel Holtmann 
356603b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
356703b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
356803b555e1SJohan Hedberg 		break;
356903b555e1SJohan Hedberg 
3570a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3571a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3572a5c29683SJohan Hedberg 		break;
3573a5c29683SJohan Hedberg 
35741143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
35751143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
35761143d458SBrian Gix 		break;
35771143d458SBrian Gix 
35780493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
35790493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
35800493684eSMarcel Holtmann 		break;
35810493684eSMarcel Holtmann 
358241a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
358341a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
358441a96212SMarcel Holtmann 		break;
358541a96212SMarcel Holtmann 
3586fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3587fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3588fcd89c09SVille Tervo 		break;
3589fcd89c09SVille Tervo 
35902763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
35912763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
35922763eda6SSzymon Janc 		break;
35932763eda6SSzymon Janc 
359425e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
359525e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
359625e89e99SAndrei Emeltchenko 		break;
359725e89e99SAndrei Emeltchenko 
35981da177e4SLinus Torvalds 	default:
3599a9de9248SMarcel Holtmann 		BT_DBG("%s event 0x%x", hdev->name, event);
36001da177e4SLinus Torvalds 		break;
36011da177e4SLinus Torvalds 	}
36021da177e4SLinus Torvalds 
36031da177e4SLinus Torvalds 	kfree_skb(skb);
36041da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
36051da177e4SLinus Torvalds }
3606