xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 223683a5)
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 <asm/unaligned.h>
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
31f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h>
327ef9fbf0SMarcel Holtmann 
337024728eSMarcel Holtmann #include "a2mp.h"
347ef9fbf0SMarcel Holtmann #include "amp.h"
352ceba539SJohan Hedberg #include "smp.h"
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds /* Handle HCI Event packets */
381da177e4SLinus Torvalds 
39a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
401da177e4SLinus Torvalds {
41a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
421da177e4SLinus Torvalds 
439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
441da177e4SLinus Torvalds 
4582f4785cSAndre Guedes 	if (status)
46a9de9248SMarcel Holtmann 		return;
471da177e4SLinus Torvalds 
4889352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
494e857c58SPeter Zijlstra 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
503e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
5189352e7dSAndre Guedes 
5250143a43SJohan Hedberg 	hci_dev_lock(hdev);
5350143a43SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
5450143a43SJohan Hedberg 	hci_dev_unlock(hdev);
5550143a43SJohan Hedberg 
56a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
571da177e4SLinus Torvalds }
586bd57416SMarcel Holtmann 
594d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
604d93483bSAndre Guedes {
614d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
624d93483bSAndre Guedes 
639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
64ae854a70SAndre Guedes 
65ae854a70SAndre Guedes 	if (status)
66ae854a70SAndre Guedes 		return;
67ae854a70SAndre Guedes 
68ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
694d93483bSAndre Guedes }
704d93483bSAndre Guedes 
71a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
721da177e4SLinus Torvalds {
73a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
74a9de9248SMarcel Holtmann 
759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
76a9de9248SMarcel Holtmann 
77a9de9248SMarcel Holtmann 	if (status)
78a9de9248SMarcel Holtmann 		return;
79a9de9248SMarcel Holtmann 
80ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
81ae854a70SAndre Guedes 
82a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
83a9de9248SMarcel Holtmann }
84a9de9248SMarcel Holtmann 
85807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
86807deac2SGustavo Padovan 					  struct sk_buff *skb)
87a9de9248SMarcel Holtmann {
88a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
89a9de9248SMarcel Holtmann }
90a9de9248SMarcel Holtmann 
91a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
92a9de9248SMarcel Holtmann {
93a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
941da177e4SLinus Torvalds 	struct hci_conn *conn;
951da177e4SLinus Torvalds 
969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
971da177e4SLinus Torvalds 
98a9de9248SMarcel Holtmann 	if (rp->status)
99a9de9248SMarcel Holtmann 		return;
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1021da177e4SLinus Torvalds 
103a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1041da177e4SLinus Torvalds 	if (conn) {
105a9de9248SMarcel Holtmann 		if (rp->role)
1064dae2798SJohan Hedberg 			clear_bit(HCI_CONN_MASTER, &conn->flags);
1071da177e4SLinus Torvalds 		else
1084dae2798SJohan Hedberg 			set_bit(HCI_CONN_MASTER, &conn->flags);
1091da177e4SLinus Torvalds 	}
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
112a9de9248SMarcel Holtmann }
1131da177e4SLinus Torvalds 
114e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
115e4e8e37cSMarcel Holtmann {
116e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
117e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
118e4e8e37cSMarcel Holtmann 
1199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
120e4e8e37cSMarcel Holtmann 
121e4e8e37cSMarcel Holtmann 	if (rp->status)
122e4e8e37cSMarcel Holtmann 		return;
123e4e8e37cSMarcel Holtmann 
124e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
125e4e8e37cSMarcel Holtmann 
126e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
127e4e8e37cSMarcel Holtmann 	if (conn)
128e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
129e4e8e37cSMarcel Holtmann 
130e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
131e4e8e37cSMarcel Holtmann }
132e4e8e37cSMarcel Holtmann 
133a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
134a9de9248SMarcel Holtmann {
135a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
136a9de9248SMarcel Holtmann 	struct hci_conn *conn;
137a9de9248SMarcel Holtmann 	void *sent;
138a9de9248SMarcel Holtmann 
1399f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
140a9de9248SMarcel Holtmann 
141a9de9248SMarcel Holtmann 	if (rp->status)
142a9de9248SMarcel Holtmann 		return;
143a9de9248SMarcel Holtmann 
144a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14504837f64SMarcel Holtmann 	if (!sent)
146a9de9248SMarcel Holtmann 		return;
14704837f64SMarcel Holtmann 
14804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14904837f64SMarcel Holtmann 
150a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
151e4e8e37cSMarcel Holtmann 	if (conn)
15283985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15304837f64SMarcel Holtmann 
15404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1551da177e4SLinus Torvalds }
1561da177e4SLinus Torvalds 
157807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
158807deac2SGustavo Padovan 					struct sk_buff *skb)
159e4e8e37cSMarcel Holtmann {
160e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
161e4e8e37cSMarcel Holtmann 
1629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
163e4e8e37cSMarcel Holtmann 
164e4e8e37cSMarcel Holtmann 	if (rp->status)
165e4e8e37cSMarcel Holtmann 		return;
166e4e8e37cSMarcel Holtmann 
167e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
168e4e8e37cSMarcel Holtmann }
169e4e8e37cSMarcel Holtmann 
170807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
171807deac2SGustavo Padovan 					 struct sk_buff *skb)
172e4e8e37cSMarcel Holtmann {
173e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
174e4e8e37cSMarcel Holtmann 	void *sent;
175e4e8e37cSMarcel Holtmann 
1769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
177e4e8e37cSMarcel Holtmann 
17845296acdSMarcel Holtmann 	if (status)
17945296acdSMarcel Holtmann 		return;
18045296acdSMarcel Holtmann 
181e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
182e4e8e37cSMarcel Holtmann 	if (!sent)
183e4e8e37cSMarcel Holtmann 		return;
184e4e8e37cSMarcel Holtmann 
185e4e8e37cSMarcel Holtmann 	hdev->link_policy = get_unaligned_le16(sent);
186e4e8e37cSMarcel Holtmann }
187e4e8e37cSMarcel Holtmann 
188a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1891da177e4SLinus Torvalds {
190a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
191a9de9248SMarcel Holtmann 
1929f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
193a9de9248SMarcel Holtmann 
19410572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19510572132SGustavo F. Padovan 
196a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
1972cc6fb00SJohan Hedberg 	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
19869775ff6SAndre Guedes 
19969775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
200bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
201bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
2023f0f524bSJohan Hedberg 
2033f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
2043f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
205f8e808bdSMarcel Holtmann 
206f8e808bdSMarcel Holtmann 	memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data));
207f8e808bdSMarcel Holtmann 	hdev->scan_rsp_data_len = 0;
20806f5b778SMarcel Holtmann 
209533553f8SMarcel Holtmann 	hdev->le_scan_type = LE_SCAN_PASSIVE;
210533553f8SMarcel Holtmann 
21106f5b778SMarcel Holtmann 	hdev->ssp_debug_mode = 0;
212a9de9248SMarcel Holtmann }
213a9de9248SMarcel Holtmann 
214a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
215a9de9248SMarcel Holtmann {
216a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2171da177e4SLinus Torvalds 	void *sent;
2181da177e4SLinus Torvalds 
2199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2201da177e4SLinus Torvalds 
221a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2221da177e4SLinus Torvalds 	if (!sent)
223a9de9248SMarcel Holtmann 		return;
2241da177e4SLinus Torvalds 
22556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
22656e5cb86SJohan Hedberg 
227f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
228f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
22928cc7bdeSJohan Hedberg 	else if (!status)
23028cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
231f51d5b24SJohan Hedberg 
23256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
233a9de9248SMarcel Holtmann }
234a9de9248SMarcel Holtmann 
235a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
236a9de9248SMarcel Holtmann {
237a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
238a9de9248SMarcel Holtmann 
2399f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
240a9de9248SMarcel Holtmann 
241a9de9248SMarcel Holtmann 	if (rp->status)
242a9de9248SMarcel Holtmann 		return;
243a9de9248SMarcel Holtmann 
244db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2451f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
246a9de9248SMarcel Holtmann }
247a9de9248SMarcel Holtmann 
248a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
249a9de9248SMarcel Holtmann {
250a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
251a9de9248SMarcel Holtmann 	void *sent;
252a9de9248SMarcel Holtmann 
2539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
254a9de9248SMarcel Holtmann 
255a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
256a9de9248SMarcel Holtmann 	if (!sent)
257a9de9248SMarcel Holtmann 		return;
2581da177e4SLinus Torvalds 
2591da177e4SLinus Torvalds 	if (!status) {
260a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
261a9de9248SMarcel Holtmann 
2621da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2631da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2641da177e4SLinus Torvalds 		else
2651da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2661da177e4SLinus Torvalds 	}
267a9de9248SMarcel Holtmann 
26833ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
26933ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
270a9de9248SMarcel Holtmann }
2711da177e4SLinus Torvalds 
272a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
273a9de9248SMarcel Holtmann {
274a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
27545296acdSMarcel Holtmann 	__u8 param;
276a9de9248SMarcel Holtmann 	void *sent;
277a9de9248SMarcel Holtmann 
2789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
279a9de9248SMarcel Holtmann 
28045296acdSMarcel Holtmann 	if (status)
28145296acdSMarcel Holtmann 		return;
28245296acdSMarcel Holtmann 
283a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2841da177e4SLinus Torvalds 	if (!sent)
285a9de9248SMarcel Holtmann 		return;
2861da177e4SLinus Torvalds 
28745296acdSMarcel Holtmann 	param = *((__u8 *) sent);
288a9de9248SMarcel Holtmann 
2891da177e4SLinus Torvalds 	if (param)
2901da177e4SLinus Torvalds 		set_bit(HCI_ENCRYPT, &hdev->flags);
2911da177e4SLinus Torvalds 	else
2921da177e4SLinus Torvalds 		clear_bit(HCI_ENCRYPT, &hdev->flags);
2931da177e4SLinus Torvalds }
2941da177e4SLinus Torvalds 
295a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
296a9de9248SMarcel Holtmann {
29745296acdSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
29845296acdSMarcel Holtmann 	__u8 param;
29936f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
300a9de9248SMarcel Holtmann 	void *sent;
3011da177e4SLinus Torvalds 
3029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
303a9de9248SMarcel Holtmann 
304a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3051da177e4SLinus Torvalds 	if (!sent)
306a9de9248SMarcel Holtmann 		return;
3071da177e4SLinus Torvalds 
30836f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
309a9de9248SMarcel Holtmann 
31056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
31156e5cb86SJohan Hedberg 
312fa1bd918SMikel Astiz 	if (status) {
313744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3142d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3152d7cee58SJohan Hedberg 		goto done;
3162d7cee58SJohan Hedberg 	}
3172d7cee58SJohan Hedberg 
3180663ca2aSJohan Hedberg 	/* We need to ensure that we set this back on if someone changed
3190663ca2aSJohan Hedberg 	 * the scan mode through a raw HCI socket.
3200663ca2aSJohan Hedberg 	 */
3210663ca2aSJohan Hedberg 	set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
3220663ca2aSJohan Hedberg 
3239fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3249fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
325a9de9248SMarcel Holtmann 
32673f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3271da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3289fbcbb45SJohan Hedberg 		if (!old_iscan)
329744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
3309fbcbb45SJohan Hedberg 	} else if (old_iscan)
331744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3321da177e4SLinus Torvalds 
3339fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3341da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3359fbcbb45SJohan Hedberg 		if (!old_pscan)
336744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3379fbcbb45SJohan Hedberg 	} else if (old_pscan)
338744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
339a9de9248SMarcel Holtmann 
34036f7fc7eSJohan Hedberg done:
34156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
3421da177e4SLinus Torvalds }
3431da177e4SLinus Torvalds 
344a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
345a9de9248SMarcel Holtmann {
346a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
347a9de9248SMarcel Holtmann 
3489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
349a9de9248SMarcel Holtmann 
350a9de9248SMarcel Holtmann 	if (rp->status)
351a9de9248SMarcel Holtmann 		return;
352a9de9248SMarcel Holtmann 
353a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
354a9de9248SMarcel Holtmann 
355a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
356a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
357a9de9248SMarcel Holtmann }
358a9de9248SMarcel Holtmann 
359a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
360a9de9248SMarcel Holtmann {
361a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
362a9de9248SMarcel Holtmann 	void *sent;
363a9de9248SMarcel Holtmann 
3649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
365a9de9248SMarcel Holtmann 
366a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
367a9de9248SMarcel Holtmann 	if (!sent)
368a9de9248SMarcel Holtmann 		return;
369a9de9248SMarcel Holtmann 
3707f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3717f9a903cSMarcel Holtmann 
3727f9a903cSMarcel Holtmann 	if (status == 0)
373a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3747f9a903cSMarcel Holtmann 
3757f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3767f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3777f9a903cSMarcel Holtmann 
3787f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
379a9de9248SMarcel Holtmann }
380a9de9248SMarcel Holtmann 
381a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
382a9de9248SMarcel Holtmann {
383a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
384a9de9248SMarcel Holtmann 	__u16 setting;
385a9de9248SMarcel Holtmann 
3869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
387a9de9248SMarcel Holtmann 
388a9de9248SMarcel Holtmann 	if (rp->status)
389a9de9248SMarcel Holtmann 		return;
390a9de9248SMarcel Holtmann 
391a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
392a9de9248SMarcel Holtmann 
393a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
394a9de9248SMarcel Holtmann 		return;
395a9de9248SMarcel Holtmann 
396a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
397a9de9248SMarcel Holtmann 
3989f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
399a9de9248SMarcel Holtmann 
4003c54711cSGustavo F. Padovan 	if (hdev->notify)
401a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
402a9de9248SMarcel Holtmann }
403a9de9248SMarcel Holtmann 
4048fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
4058fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
406a9de9248SMarcel Holtmann {
407a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
408f383f275SMarcel Holtmann 	__u16 setting;
409a9de9248SMarcel Holtmann 	void *sent;
410a9de9248SMarcel Holtmann 
4119f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
412a9de9248SMarcel Holtmann 
413f383f275SMarcel Holtmann 	if (status)
414f383f275SMarcel Holtmann 		return;
415f383f275SMarcel Holtmann 
416a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
417a9de9248SMarcel Holtmann 	if (!sent)
418a9de9248SMarcel Holtmann 		return;
419a9de9248SMarcel Holtmann 
420f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4211da177e4SLinus Torvalds 
422f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
423f383f275SMarcel Holtmann 		return;
424f383f275SMarcel Holtmann 
4251da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4261da177e4SLinus Torvalds 
4279f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4281da177e4SLinus Torvalds 
4293c54711cSGustavo F. Padovan 	if (hdev->notify)
4301da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4311da177e4SLinus Torvalds }
4321da177e4SLinus Torvalds 
433b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev,
434b4cb9fb2SMarcel Holtmann 					  struct sk_buff *skb)
435b4cb9fb2SMarcel Holtmann {
436b4cb9fb2SMarcel Holtmann 	struct hci_rp_read_num_supported_iac *rp = (void *) skb->data;
437b4cb9fb2SMarcel Holtmann 
438b4cb9fb2SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
439b4cb9fb2SMarcel Holtmann 
440b4cb9fb2SMarcel Holtmann 	if (rp->status)
441b4cb9fb2SMarcel Holtmann 		return;
442b4cb9fb2SMarcel Holtmann 
443b4cb9fb2SMarcel Holtmann 	hdev->num_iac = rp->num_iac;
444b4cb9fb2SMarcel Holtmann 
445b4cb9fb2SMarcel Holtmann 	BT_DBG("%s num iac %d", hdev->name, hdev->num_iac);
446b4cb9fb2SMarcel Holtmann }
447b4cb9fb2SMarcel Holtmann 
448333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
449333140b5SMarcel Holtmann {
450333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4515ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
452333140b5SMarcel Holtmann 
4539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
454333140b5SMarcel Holtmann 
455333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
456333140b5SMarcel Holtmann 	if (!sent)
457333140b5SMarcel Holtmann 		return;
458333140b5SMarcel Holtmann 
4595ed8eb2fSJohan Hedberg 	if (!status) {
4605ed8eb2fSJohan Hedberg 		if (sent->mode)
461cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_SSP;
4625ed8eb2fSJohan Hedberg 		else
463cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_SSP;
4645ed8eb2fSJohan Hedberg 	}
4655ed8eb2fSJohan Hedberg 
466c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4675ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
468c0ecddc2SJohan Hedberg 	else if (!status) {
4695ed8eb2fSJohan Hedberg 		if (sent->mode)
47084bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
47184bde9d6SJohan Hedberg 		else
47284bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
473c0ecddc2SJohan Hedberg 	}
474333140b5SMarcel Holtmann }
475333140b5SMarcel Holtmann 
476eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
477eac83dc6SMarcel Holtmann {
478eac83dc6SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
479eac83dc6SMarcel Holtmann 	struct hci_cp_write_sc_support *sent;
480eac83dc6SMarcel Holtmann 
481eac83dc6SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
482eac83dc6SMarcel Holtmann 
483eac83dc6SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
484eac83dc6SMarcel Holtmann 	if (!sent)
485eac83dc6SMarcel Holtmann 		return;
486eac83dc6SMarcel Holtmann 
487eac83dc6SMarcel Holtmann 	if (!status) {
488eac83dc6SMarcel Holtmann 		if (sent->support)
489eac83dc6SMarcel Holtmann 			hdev->features[1][0] |= LMP_HOST_SC;
490eac83dc6SMarcel Holtmann 		else
491eac83dc6SMarcel Holtmann 			hdev->features[1][0] &= ~LMP_HOST_SC;
492eac83dc6SMarcel Holtmann 	}
493eac83dc6SMarcel Holtmann 
494eac83dc6SMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
495eac83dc6SMarcel Holtmann 		mgmt_sc_enable_complete(hdev, sent->support, status);
496eac83dc6SMarcel Holtmann 	else if (!status) {
497eac83dc6SMarcel Holtmann 		if (sent->support)
498eac83dc6SMarcel Holtmann 			set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
499eac83dc6SMarcel Holtmann 		else
500eac83dc6SMarcel Holtmann 			clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
501eac83dc6SMarcel Holtmann 	}
502eac83dc6SMarcel Holtmann }
503eac83dc6SMarcel Holtmann 
504a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
505a9de9248SMarcel Holtmann {
506a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5071143e5a6SMarcel Holtmann 
5089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5091143e5a6SMarcel Holtmann 
510a9de9248SMarcel Holtmann 	if (rp->status)
51142c6b129SJohan Hedberg 		return;
5121143e5a6SMarcel Holtmann 
5130d5551f5SMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
514a9de9248SMarcel Holtmann 		hdev->hci_ver = rp->hci_ver;
515e4e8e37cSMarcel Holtmann 		hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
516d5859e22SJohan Hedberg 		hdev->lmp_ver = rp->lmp_ver;
517e4e8e37cSMarcel Holtmann 		hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
518d5859e22SJohan Hedberg 		hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5190d5551f5SMarcel Holtmann 	}
520d5859e22SJohan Hedberg }
521d5859e22SJohan Hedberg 
5228fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
5238fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
524a9de9248SMarcel Holtmann {
525a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
526a9de9248SMarcel Holtmann 
5279f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
528a9de9248SMarcel Holtmann 
5296a070e6eSMarcel Holtmann 	if (rp->status)
5306a070e6eSMarcel Holtmann 		return;
5316a070e6eSMarcel Holtmann 
5326a070e6eSMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
533a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
534a9de9248SMarcel Holtmann }
535a9de9248SMarcel Holtmann 
5368fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
5378fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
538a9de9248SMarcel Holtmann {
539a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
540a9de9248SMarcel Holtmann 
5419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
542a9de9248SMarcel Holtmann 
543a9de9248SMarcel Holtmann 	if (rp->status)
544a9de9248SMarcel Holtmann 		return;
545a9de9248SMarcel Holtmann 
546a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
5471da177e4SLinus Torvalds 
5481da177e4SLinus Torvalds 	/* Adjust default settings according to features
5491da177e4SLinus Torvalds 	 * supported by device. */
550a9de9248SMarcel Holtmann 
551cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_3SLOT)
5521da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
5531da177e4SLinus Torvalds 
554cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_5SLOT)
5551da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
5561da177e4SLinus Torvalds 
557cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV2) {
5581da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
5595b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
5605b7f9909SMarcel Holtmann 	}
5611da177e4SLinus Torvalds 
562cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV3) {
5631da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
5645b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
5655b7f9909SMarcel Holtmann 	}
5665b7f9909SMarcel Holtmann 
56745db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
5685b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
5695b7f9909SMarcel Holtmann 
570cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV4)
5715b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
5725b7f9909SMarcel Holtmann 
573cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV5)
5745b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
5751da177e4SLinus Torvalds 
576cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
577efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
578efc7688bSMarcel Holtmann 
579cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
580efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
581efc7688bSMarcel Holtmann 
582cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
583efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
5841da177e4SLinus Torvalds }
5851da177e4SLinus Torvalds 
586971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
587971e3a4bSAndre Guedes 					   struct sk_buff *skb)
588971e3a4bSAndre Guedes {
589971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
590971e3a4bSAndre Guedes 
5919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
592971e3a4bSAndre Guedes 
593971e3a4bSAndre Guedes 	if (rp->status)
59442c6b129SJohan Hedberg 		return;
595971e3a4bSAndre Guedes 
59657af75a8SMarcel Holtmann 	if (hdev->max_page < rp->max_page)
597d2c5d77fSJohan Hedberg 		hdev->max_page = rp->max_page;
598d2c5d77fSJohan Hedberg 
599cad718edSJohan Hedberg 	if (rp->page < HCI_MAX_PAGES)
600cad718edSJohan Hedberg 		memcpy(hdev->features[rp->page], rp->features, 8);
601971e3a4bSAndre Guedes }
602971e3a4bSAndre Guedes 
6031e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
6041e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
6051e89cffbSAndrei Emeltchenko {
6061e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
6071e89cffbSAndrei Emeltchenko 
6089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
6091e89cffbSAndrei Emeltchenko 
61045296acdSMarcel Holtmann 	if (rp->status)
61145296acdSMarcel Holtmann 		return;
61245296acdSMarcel Holtmann 
6131e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
6141e89cffbSAndrei Emeltchenko }
6151e89cffbSAndrei Emeltchenko 
616a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
617a9de9248SMarcel Holtmann {
618a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
619a9de9248SMarcel Holtmann 
6209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
621a9de9248SMarcel Holtmann 
622a9de9248SMarcel Holtmann 	if (rp->status)
623a9de9248SMarcel Holtmann 		return;
624a9de9248SMarcel Holtmann 
625a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
626a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
627a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
628a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
629da1f5198SMarcel Holtmann 
630da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
631da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
632da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
633da1f5198SMarcel Holtmann 	}
634da1f5198SMarcel Holtmann 
635da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
636da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
6371da177e4SLinus Torvalds 
638807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
639807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
6401da177e4SLinus Torvalds }
6411da177e4SLinus Torvalds 
642a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
643a9de9248SMarcel Holtmann {
644a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6451da177e4SLinus Torvalds 
6469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
647a9de9248SMarcel Holtmann 
648e30d3f5fSMarcel Holtmann 	if (rp->status)
649e30d3f5fSMarcel Holtmann 		return;
650e30d3f5fSMarcel Holtmann 
651e30d3f5fSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
652a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
653e30d3f5fSMarcel Holtmann 
654e30d3f5fSMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
655e30d3f5fSMarcel Holtmann 		bacpy(&hdev->setup_addr, &rp->bdaddr);
65623bb5763SJohan Hedberg }
65723bb5763SJohan Hedberg 
658f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
659f332ec66SJohan Hedberg 					   struct sk_buff *skb)
660f332ec66SJohan Hedberg {
661f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
662f332ec66SJohan Hedberg 
663f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
664f332ec66SJohan Hedberg 
66545296acdSMarcel Holtmann 	if (rp->status)
66645296acdSMarcel Holtmann 		return;
66745296acdSMarcel Holtmann 
66845296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags)) {
669f332ec66SJohan Hedberg 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
670f332ec66SJohan Hedberg 		hdev->page_scan_window = __le16_to_cpu(rp->window);
671f332ec66SJohan Hedberg 	}
672f332ec66SJohan Hedberg }
673f332ec66SJohan Hedberg 
6744a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
6754a3ee763SJohan Hedberg 					    struct sk_buff *skb)
6764a3ee763SJohan Hedberg {
6774a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6784a3ee763SJohan Hedberg 	struct hci_cp_write_page_scan_activity *sent;
6794a3ee763SJohan Hedberg 
6804a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6814a3ee763SJohan Hedberg 
6824a3ee763SJohan Hedberg 	if (status)
6834a3ee763SJohan Hedberg 		return;
6844a3ee763SJohan Hedberg 
6854a3ee763SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
6864a3ee763SJohan Hedberg 	if (!sent)
6874a3ee763SJohan Hedberg 		return;
6884a3ee763SJohan Hedberg 
6894a3ee763SJohan Hedberg 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
6904a3ee763SJohan Hedberg 	hdev->page_scan_window = __le16_to_cpu(sent->window);
6914a3ee763SJohan Hedberg }
6924a3ee763SJohan Hedberg 
693f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
694f332ec66SJohan Hedberg 					   struct sk_buff *skb)
695f332ec66SJohan Hedberg {
696f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
697f332ec66SJohan Hedberg 
698f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
699f332ec66SJohan Hedberg 
70045296acdSMarcel Holtmann 	if (rp->status)
70145296acdSMarcel Holtmann 		return;
70245296acdSMarcel Holtmann 
70345296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
704f332ec66SJohan Hedberg 		hdev->page_scan_type = rp->type;
705f332ec66SJohan Hedberg }
706f332ec66SJohan Hedberg 
7074a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
7084a3ee763SJohan Hedberg 					struct sk_buff *skb)
7094a3ee763SJohan Hedberg {
7104a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
7114a3ee763SJohan Hedberg 	u8 *type;
7124a3ee763SJohan Hedberg 
7134a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
7144a3ee763SJohan Hedberg 
7154a3ee763SJohan Hedberg 	if (status)
7164a3ee763SJohan Hedberg 		return;
7174a3ee763SJohan Hedberg 
7184a3ee763SJohan Hedberg 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
7194a3ee763SJohan Hedberg 	if (type)
7204a3ee763SJohan Hedberg 		hdev->page_scan_type = *type;
7214a3ee763SJohan Hedberg }
7224a3ee763SJohan Hedberg 
723350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
724350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
725350ee4cfSAndrei Emeltchenko {
726350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
727350ee4cfSAndrei Emeltchenko 
7289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
729350ee4cfSAndrei Emeltchenko 
730350ee4cfSAndrei Emeltchenko 	if (rp->status)
731350ee4cfSAndrei Emeltchenko 		return;
732350ee4cfSAndrei Emeltchenko 
733350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
734350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
735350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
736350ee4cfSAndrei Emeltchenko 
737350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
738350ee4cfSAndrei Emeltchenko 
739350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
740350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
741350ee4cfSAndrei Emeltchenko }
742350ee4cfSAndrei Emeltchenko 
74333f35721SJohan Hedberg static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb)
74433f35721SJohan Hedberg {
74533f35721SJohan Hedberg 	struct hci_rp_read_clock *rp = (void *) skb->data;
74633f35721SJohan Hedberg 	struct hci_cp_read_clock *cp;
74733f35721SJohan Hedberg 	struct hci_conn *conn;
74833f35721SJohan Hedberg 
74933f35721SJohan Hedberg 	BT_DBG("%s", hdev->name);
75033f35721SJohan Hedberg 
75133f35721SJohan Hedberg 	if (skb->len < sizeof(*rp))
75233f35721SJohan Hedberg 		return;
75333f35721SJohan Hedberg 
75433f35721SJohan Hedberg 	if (rp->status)
75533f35721SJohan Hedberg 		return;
75633f35721SJohan Hedberg 
75733f35721SJohan Hedberg 	hci_dev_lock(hdev);
75833f35721SJohan Hedberg 
75933f35721SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
76033f35721SJohan Hedberg 	if (!cp)
76133f35721SJohan Hedberg 		goto unlock;
76233f35721SJohan Hedberg 
76333f35721SJohan Hedberg 	if (cp->which == 0x00) {
76433f35721SJohan Hedberg 		hdev->clock = le32_to_cpu(rp->clock);
76533f35721SJohan Hedberg 		goto unlock;
76633f35721SJohan Hedberg 	}
76733f35721SJohan Hedberg 
76833f35721SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
76933f35721SJohan Hedberg 	if (conn) {
77033f35721SJohan Hedberg 		conn->clock = le32_to_cpu(rp->clock);
77133f35721SJohan Hedberg 		conn->clock_accuracy = le16_to_cpu(rp->accuracy);
77233f35721SJohan Hedberg 	}
77333f35721SJohan Hedberg 
77433f35721SJohan Hedberg unlock:
77533f35721SJohan Hedberg 	hci_dev_unlock(hdev);
77633f35721SJohan Hedberg }
77733f35721SJohan Hedberg 
778928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
779928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
780928abaa7SAndrei Emeltchenko {
781928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
782928abaa7SAndrei Emeltchenko 
7839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
784928abaa7SAndrei Emeltchenko 
785928abaa7SAndrei Emeltchenko 	if (rp->status)
7868e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
787928abaa7SAndrei Emeltchenko 
788928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
789928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
790928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
791928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
792928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
793928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
794928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
795928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
796928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
797928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
798928abaa7SAndrei Emeltchenko 
7998e2a0d92SAndrei Emeltchenko a2mp_rsp:
8008e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
801928abaa7SAndrei Emeltchenko }
802928abaa7SAndrei Emeltchenko 
803903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
804903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
805903e4541SAndrei Emeltchenko {
806903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
807903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
808903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
809903e4541SAndrei Emeltchenko 
810903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
811903e4541SAndrei Emeltchenko 
812903e4541SAndrei Emeltchenko 	if (rp->status)
813903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
814903e4541SAndrei Emeltchenko 
815903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
816903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
817903e4541SAndrei Emeltchenko 
818903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
8192e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
820903e4541SAndrei Emeltchenko 
821903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
822903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
823903e4541SAndrei Emeltchenko 
824903e4541SAndrei Emeltchenko 		/* Read other fragments */
825903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
826903e4541SAndrei Emeltchenko 
827903e4541SAndrei Emeltchenko 		return;
828903e4541SAndrei Emeltchenko 	}
829903e4541SAndrei Emeltchenko 
830903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
831903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
832903e4541SAndrei Emeltchenko 	assoc->offset = 0;
833903e4541SAndrei Emeltchenko 
834903e4541SAndrei Emeltchenko a2mp_rsp:
835903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
836903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
8379495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
838903e4541SAndrei Emeltchenko }
839903e4541SAndrei Emeltchenko 
840d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
841d5859e22SJohan Hedberg 					 struct sk_buff *skb)
842d5859e22SJohan Hedberg {
84391c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
844d5859e22SJohan Hedberg 
8459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
846d5859e22SJohan Hedberg 
84745296acdSMarcel Holtmann 	if (rp->status)
84845296acdSMarcel Holtmann 		return;
84945296acdSMarcel Holtmann 
85091c4e9b1SMarcel Holtmann 	hdev->inq_tx_power = rp->tx_power;
851d5859e22SJohan Hedberg }
852d5859e22SJohan Hedberg 
853980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
854980e1a53SJohan Hedberg {
855980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
856980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
857980e1a53SJohan Hedberg 	struct hci_conn *conn;
858980e1a53SJohan Hedberg 
8599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
860980e1a53SJohan Hedberg 
86156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
86256e5cb86SJohan Hedberg 
863a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
864744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
865980e1a53SJohan Hedberg 
866fa1bd918SMikel Astiz 	if (rp->status)
86756e5cb86SJohan Hedberg 		goto unlock;
868980e1a53SJohan Hedberg 
869980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
870980e1a53SJohan Hedberg 	if (!cp)
87156e5cb86SJohan Hedberg 		goto unlock;
872980e1a53SJohan Hedberg 
873980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
874980e1a53SJohan Hedberg 	if (conn)
875980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
87656e5cb86SJohan Hedberg 
87756e5cb86SJohan Hedberg unlock:
87856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
879980e1a53SJohan Hedberg }
880980e1a53SJohan Hedberg 
881980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
882980e1a53SJohan Hedberg {
883980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
884980e1a53SJohan Hedberg 
8859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
886980e1a53SJohan Hedberg 
88756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
88856e5cb86SJohan Hedberg 
889a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
890744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
891980e1a53SJohan Hedberg 						 rp->status);
89256e5cb86SJohan Hedberg 
89356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
894980e1a53SJohan Hedberg }
89556e5cb86SJohan Hedberg 
8966ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8976ed58ec5SVille Tervo 				       struct sk_buff *skb)
8986ed58ec5SVille Tervo {
8996ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9006ed58ec5SVille Tervo 
9019f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9026ed58ec5SVille Tervo 
9036ed58ec5SVille Tervo 	if (rp->status)
9046ed58ec5SVille Tervo 		return;
9056ed58ec5SVille Tervo 
9066ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9076ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9086ed58ec5SVille Tervo 
9096ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9106ed58ec5SVille Tervo 
9116ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9126ed58ec5SVille Tervo }
913980e1a53SJohan Hedberg 
91460e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
91560e77321SJohan Hedberg 					  struct sk_buff *skb)
91660e77321SJohan Hedberg {
91760e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
91860e77321SJohan Hedberg 
91960e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
92060e77321SJohan Hedberg 
92145296acdSMarcel Holtmann 	if (rp->status)
92245296acdSMarcel Holtmann 		return;
92345296acdSMarcel Holtmann 
92460e77321SJohan Hedberg 	memcpy(hdev->le_features, rp->features, 8);
92560e77321SJohan Hedberg }
92660e77321SJohan Hedberg 
9278fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
9288fa19098SJohan Hedberg 					struct sk_buff *skb)
9298fa19098SJohan Hedberg {
9308fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
9318fa19098SJohan Hedberg 
9328fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9338fa19098SJohan Hedberg 
93445296acdSMarcel Holtmann 	if (rp->status)
93545296acdSMarcel Holtmann 		return;
93645296acdSMarcel Holtmann 
9378fa19098SJohan Hedberg 	hdev->adv_tx_power = rp->tx_power;
9388fa19098SJohan Hedberg }
9398fa19098SJohan Hedberg 
940a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
941a5c29683SJohan Hedberg {
942a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
943a5c29683SJohan Hedberg 
9449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
945a5c29683SJohan Hedberg 
94656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
94756e5cb86SJohan Hedberg 
948a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
94904124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
95004124681SGustavo F. Padovan 						 rp->status);
95156e5cb86SJohan Hedberg 
95256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
953a5c29683SJohan Hedberg }
954a5c29683SJohan Hedberg 
955a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
956a5c29683SJohan Hedberg 					  struct sk_buff *skb)
957a5c29683SJohan Hedberg {
958a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
959a5c29683SJohan Hedberg 
9609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
961a5c29683SJohan Hedberg 
96256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96356e5cb86SJohan Hedberg 
964a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
965744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
96604124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
96756e5cb86SJohan Hedberg 
96856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
969a5c29683SJohan Hedberg }
970a5c29683SJohan Hedberg 
9711143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9721143d458SBrian Gix {
9731143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9741143d458SBrian Gix 
9759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9761143d458SBrian Gix 
9771143d458SBrian Gix 	hci_dev_lock(hdev);
9781143d458SBrian Gix 
979a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
980272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
981272d90dfSJohan Hedberg 						 0, rp->status);
9821143d458SBrian Gix 
9831143d458SBrian Gix 	hci_dev_unlock(hdev);
9841143d458SBrian Gix }
9851143d458SBrian Gix 
9861143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9871143d458SBrian Gix 					  struct sk_buff *skb)
9881143d458SBrian Gix {
9891143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9901143d458SBrian Gix 
9919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9921143d458SBrian Gix 
9931143d458SBrian Gix 	hci_dev_lock(hdev);
9941143d458SBrian Gix 
995a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9961143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
99704124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
9981143d458SBrian Gix 
9991143d458SBrian Gix 	hci_dev_unlock(hdev);
10001143d458SBrian Gix }
10011143d458SBrian Gix 
10024d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
1003c35938b2SSzymon Janc 				       struct sk_buff *skb)
1004c35938b2SSzymon Janc {
1005c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1006c35938b2SSzymon Janc 
10079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1008c35938b2SSzymon Janc 
100956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
10104d2d2796SMarcel Holtmann 	mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer,
10114d2d2796SMarcel Holtmann 					  NULL, NULL, rp->status);
10124d2d2796SMarcel Holtmann 	hci_dev_unlock(hdev);
10134d2d2796SMarcel Holtmann }
10144d2d2796SMarcel Holtmann 
10154d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
10164d2d2796SMarcel Holtmann 					   struct sk_buff *skb)
10174d2d2796SMarcel Holtmann {
10184d2d2796SMarcel Holtmann 	struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
10194d2d2796SMarcel Holtmann 
10204d2d2796SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10214d2d2796SMarcel Holtmann 
10224d2d2796SMarcel Holtmann 	hci_dev_lock(hdev);
10234d2d2796SMarcel Holtmann 	mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192,
10244d2d2796SMarcel Holtmann 					  rp->hash256, rp->randomizer256,
10254d2d2796SMarcel Holtmann 					  rp->status);
102656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1027c35938b2SSzymon Janc }
1028c35938b2SSzymon Janc 
10297a4cd51dSMarcel Holtmann 
10307a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
10317a4cd51dSMarcel Holtmann {
10327a4cd51dSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
10337a4cd51dSMarcel Holtmann 	bdaddr_t *sent;
10347a4cd51dSMarcel Holtmann 
10357a4cd51dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10367a4cd51dSMarcel Holtmann 
103745296acdSMarcel Holtmann 	if (status)
103845296acdSMarcel Holtmann 		return;
103945296acdSMarcel Holtmann 
10407a4cd51dSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
10417a4cd51dSMarcel Holtmann 	if (!sent)
10427a4cd51dSMarcel Holtmann 		return;
10437a4cd51dSMarcel Holtmann 
10447a4cd51dSMarcel Holtmann 	hci_dev_lock(hdev);
10457a4cd51dSMarcel Holtmann 
10467a4cd51dSMarcel Holtmann 	bacpy(&hdev->random_addr, sent);
10477a4cd51dSMarcel Holtmann 
10487a4cd51dSMarcel Holtmann 	hci_dev_unlock(hdev);
10497a4cd51dSMarcel Holtmann }
10507a4cd51dSMarcel Holtmann 
1051c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1052c1d5dc4aSJohan Hedberg {
1053c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
1054c1d5dc4aSJohan Hedberg 
1055c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1056c1d5dc4aSJohan Hedberg 
105745296acdSMarcel Holtmann 	if (status)
1058c1d5dc4aSJohan Hedberg 		return;
1059c1d5dc4aSJohan Hedberg 
106045296acdSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
106145296acdSMarcel Holtmann 	if (!sent)
10623c857757SJohan Hedberg 		return;
10633c857757SJohan Hedberg 
1064c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
1065c1d5dc4aSJohan Hedberg 
10663c857757SJohan Hedberg 	/* If we're doing connection initation as peripheral. Set a
10673c857757SJohan Hedberg 	 * timeout in case something goes wrong.
10683c857757SJohan Hedberg 	 */
10693c857757SJohan Hedberg 	if (*sent) {
10703c857757SJohan Hedberg 		struct hci_conn *conn;
10713c857757SJohan Hedberg 
10723c857757SJohan Hedberg 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
10733c857757SJohan Hedberg 		if (conn)
10743c857757SJohan Hedberg 			queue_delayed_work(hdev->workqueue,
10753c857757SJohan Hedberg 					   &conn->le_conn_timeout,
107609ae260bSJohan Hedberg 					   conn->conn_timeout);
10773c857757SJohan Hedberg 	}
10783c857757SJohan Hedberg 
1079778b235aSJohan Hedberg 	mgmt_advertising(hdev, *sent);
1080c1d5dc4aSJohan Hedberg 
108104b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
1082c1d5dc4aSJohan Hedberg }
1083c1d5dc4aSJohan Hedberg 
1084533553f8SMarcel Holtmann static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1085533553f8SMarcel Holtmann {
1086533553f8SMarcel Holtmann 	struct hci_cp_le_set_scan_param *cp;
1087533553f8SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1088533553f8SMarcel Holtmann 
1089533553f8SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1090533553f8SMarcel Holtmann 
109145296acdSMarcel Holtmann 	if (status)
109245296acdSMarcel Holtmann 		return;
109345296acdSMarcel Holtmann 
1094533553f8SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM);
1095533553f8SMarcel Holtmann 	if (!cp)
1096533553f8SMarcel Holtmann 		return;
1097533553f8SMarcel Holtmann 
1098533553f8SMarcel Holtmann 	hci_dev_lock(hdev);
1099533553f8SMarcel Holtmann 
1100533553f8SMarcel Holtmann 	hdev->le_scan_type = cp->type;
1101533553f8SMarcel Holtmann 
1102533553f8SMarcel Holtmann 	hci_dev_unlock(hdev);
1103533553f8SMarcel Holtmann }
1104533553f8SMarcel Holtmann 
1105b9a6328fSJohan Hedberg static bool has_pending_adv_report(struct hci_dev *hdev)
1106b9a6328fSJohan Hedberg {
1107b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1108b9a6328fSJohan Hedberg 
1109b9a6328fSJohan Hedberg 	return bacmp(&d->last_adv_addr, BDADDR_ANY);
1110b9a6328fSJohan Hedberg }
1111b9a6328fSJohan Hedberg 
1112b9a6328fSJohan Hedberg static void clear_pending_adv_report(struct hci_dev *hdev)
1113b9a6328fSJohan Hedberg {
1114b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1115b9a6328fSJohan Hedberg 
1116b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, BDADDR_ANY);
1117b9a6328fSJohan Hedberg 	d->last_adv_data_len = 0;
1118b9a6328fSJohan Hedberg }
1119b9a6328fSJohan Hedberg 
1120b9a6328fSJohan Hedberg static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
1121c70a7e4cSMarcel Holtmann 				     u8 bdaddr_type, s8 rssi, u32 flags,
1122c70a7e4cSMarcel Holtmann 				     u8 *data, u8 len)
1123b9a6328fSJohan Hedberg {
1124b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1125b9a6328fSJohan Hedberg 
1126b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, bdaddr);
1127b9a6328fSJohan Hedberg 	d->last_adv_addr_type = bdaddr_type;
1128ff5cd29fSJohan Hedberg 	d->last_adv_rssi = rssi;
1129c70a7e4cSMarcel Holtmann 	d->last_adv_flags = flags;
1130b9a6328fSJohan Hedberg 	memcpy(d->last_adv_data, data, len);
1131b9a6328fSJohan Hedberg 	d->last_adv_data_len = len;
1132b9a6328fSJohan Hedberg }
1133b9a6328fSJohan Hedberg 
1134eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1135eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1136eb9d91f5SAndre Guedes {
1137eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1138eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1139eb9d91f5SAndre Guedes 
11409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1141eb9d91f5SAndre Guedes 
114245296acdSMarcel Holtmann 	if (status)
1143eb9d91f5SAndre Guedes 		return;
1144eb9d91f5SAndre Guedes 
114545296acdSMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
114645296acdSMarcel Holtmann 	if (!cp)
11477ba8b4beSAndre Guedes 		return;
11487ba8b4beSAndre Guedes 
11493fd319b8SAndre Guedes 	switch (cp->enable) {
11503fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
1151d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1152b9a6328fSJohan Hedberg 		if (hdev->le_scan_type == LE_SCAN_ACTIVE)
1153b9a6328fSJohan Hedberg 			clear_pending_adv_report(hdev);
115468a8aea4SAndrei Emeltchenko 		break;
115568a8aea4SAndrei Emeltchenko 
115676a388beSAndre Guedes 	case LE_SCAN_DISABLE:
1157b9a6328fSJohan Hedberg 		/* We do this here instead of when setting DISCOVERY_STOPPED
1158b9a6328fSJohan Hedberg 		 * since the latter would potentially require waiting for
1159b9a6328fSJohan Hedberg 		 * inquiry to stop too.
1160b9a6328fSJohan Hedberg 		 */
1161b9a6328fSJohan Hedberg 		if (has_pending_adv_report(hdev)) {
1162b9a6328fSJohan Hedberg 			struct discovery_state *d = &hdev->discovery;
1163b9a6328fSJohan Hedberg 
1164b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
1165ab0aa433SJohan Hedberg 					  d->last_adv_addr_type, NULL,
1166c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
1167ab0aa433SJohan Hedberg 					  d->last_adv_data,
1168b9a6328fSJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
1169b9a6328fSJohan Hedberg 		}
1170b9a6328fSJohan Hedberg 
1171317ac8cbSJohan Hedberg 		/* Cancel this timer so that we don't try to disable scanning
1172317ac8cbSJohan Hedberg 		 * when it's already disabled.
1173317ac8cbSJohan Hedberg 		 */
1174317ac8cbSJohan Hedberg 		cancel_delayed_work(&hdev->le_scan_disable);
1175317ac8cbSJohan Hedberg 
1176d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
117781ad6fd9SJohan Hedberg 		/* The HCI_LE_SCAN_INTERRUPTED flag indicates that we
117881ad6fd9SJohan Hedberg 		 * interrupted scanning due to a connect request. Mark
117981ad6fd9SJohan Hedberg 		 * therefore discovery as stopped.
118081ad6fd9SJohan Hedberg 		 */
118181ad6fd9SJohan Hedberg 		if (test_and_clear_bit(HCI_LE_SCAN_INTERRUPTED,
118281ad6fd9SJohan Hedberg 				       &hdev->dev_flags))
118381ad6fd9SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
118468a8aea4SAndrei Emeltchenko 		break;
118568a8aea4SAndrei Emeltchenko 
118668a8aea4SAndrei Emeltchenko 	default:
118768a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
118868a8aea4SAndrei Emeltchenko 		break;
118935815085SAndre Guedes 	}
1190eb9d91f5SAndre Guedes }
1191eb9d91f5SAndre Guedes 
1192cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1193cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
1194cf1d081fSJohan Hedberg {
1195cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1196cf1d081fSJohan Hedberg 
1197cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1198cf1d081fSJohan Hedberg 
119945296acdSMarcel Holtmann 	if (rp->status)
120045296acdSMarcel Holtmann 		return;
120145296acdSMarcel Holtmann 
1202cf1d081fSJohan Hedberg 	hdev->le_white_list_size = rp->size;
1203cf1d081fSJohan Hedberg }
1204cf1d081fSJohan Hedberg 
12050f36b589SMarcel Holtmann static void hci_cc_le_clear_white_list(struct hci_dev *hdev,
12060f36b589SMarcel Holtmann 				       struct sk_buff *skb)
12070f36b589SMarcel Holtmann {
12080f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12090f36b589SMarcel Holtmann 
12100f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12110f36b589SMarcel Holtmann 
121245296acdSMarcel Holtmann 	if (status)
121345296acdSMarcel Holtmann 		return;
121445296acdSMarcel Holtmann 
12150f36b589SMarcel Holtmann 	hci_white_list_clear(hdev);
12160f36b589SMarcel Holtmann }
12170f36b589SMarcel Holtmann 
12180f36b589SMarcel Holtmann static void hci_cc_le_add_to_white_list(struct hci_dev *hdev,
12190f36b589SMarcel Holtmann 					struct sk_buff *skb)
12200f36b589SMarcel Holtmann {
12210f36b589SMarcel Holtmann 	struct hci_cp_le_add_to_white_list *sent;
12220f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12230f36b589SMarcel Holtmann 
12240f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12250f36b589SMarcel Holtmann 
122645296acdSMarcel Holtmann 	if (status)
122745296acdSMarcel Holtmann 		return;
122845296acdSMarcel Holtmann 
12290f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST);
12300f36b589SMarcel Holtmann 	if (!sent)
12310f36b589SMarcel Holtmann 		return;
12320f36b589SMarcel Holtmann 
12330f36b589SMarcel Holtmann 	hci_white_list_add(hdev, &sent->bdaddr, sent->bdaddr_type);
12340f36b589SMarcel Holtmann }
12350f36b589SMarcel Holtmann 
12360f36b589SMarcel Holtmann static void hci_cc_le_del_from_white_list(struct hci_dev *hdev,
12370f36b589SMarcel Holtmann 					  struct sk_buff *skb)
12380f36b589SMarcel Holtmann {
12390f36b589SMarcel Holtmann 	struct hci_cp_le_del_from_white_list *sent;
12400f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12410f36b589SMarcel Holtmann 
12420f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12430f36b589SMarcel Holtmann 
124445296acdSMarcel Holtmann 	if (status)
124545296acdSMarcel Holtmann 		return;
124645296acdSMarcel Holtmann 
12470f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST);
12480f36b589SMarcel Holtmann 	if (!sent)
12490f36b589SMarcel Holtmann 		return;
12500f36b589SMarcel Holtmann 
12510f36b589SMarcel Holtmann 	hci_white_list_del(hdev, &sent->bdaddr, sent->bdaddr_type);
12520f36b589SMarcel Holtmann }
12530f36b589SMarcel Holtmann 
12549b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
12559b008c04SJohan Hedberg 					    struct sk_buff *skb)
12569b008c04SJohan Hedberg {
12579b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
12589b008c04SJohan Hedberg 
12599b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
12609b008c04SJohan Hedberg 
126145296acdSMarcel Holtmann 	if (rp->status)
126245296acdSMarcel Holtmann 		return;
126345296acdSMarcel Holtmann 
12649b008c04SJohan Hedberg 	memcpy(hdev->le_states, rp->le_states, 8);
12659b008c04SJohan Hedberg }
12669b008c04SJohan Hedberg 
12676039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1268f9b49306SAndre Guedes 					   struct sk_buff *skb)
1269f9b49306SAndre Guedes {
127006199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1271f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1272f9b49306SAndre Guedes 
12739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1274f9b49306SAndre Guedes 
127545296acdSMarcel Holtmann 	if (status)
127645296acdSMarcel Holtmann 		return;
127745296acdSMarcel Holtmann 
127806199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
12798f984dfaSJohan Hedberg 	if (!sent)
1280f9b49306SAndre Guedes 		return;
1281f9b49306SAndre Guedes 
1282416a4ae5SJohan Hedberg 	if (sent->le) {
1283cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE;
1284416a4ae5SJohan Hedberg 		set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1285416a4ae5SJohan Hedberg 	} else {
1286cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE;
1287416a4ae5SJohan Hedberg 		clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1288f3d3444aSJohan Hedberg 		clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1289416a4ae5SJohan Hedberg 	}
129053b2caabSJohan Hedberg 
129153b2caabSJohan Hedberg 	if (sent->simul)
1292cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE_BREDR;
129353b2caabSJohan Hedberg 	else
1294cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
12958f984dfaSJohan Hedberg }
1296f9b49306SAndre Guedes 
129756ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
129856ed2cb8SJohan Hedberg {
129956ed2cb8SJohan Hedberg 	struct hci_cp_le_set_adv_param *cp;
130056ed2cb8SJohan Hedberg 	u8 status = *((u8 *) skb->data);
130156ed2cb8SJohan Hedberg 
130256ed2cb8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
130356ed2cb8SJohan Hedberg 
130456ed2cb8SJohan Hedberg 	if (status)
130556ed2cb8SJohan Hedberg 		return;
130656ed2cb8SJohan Hedberg 
130756ed2cb8SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
130856ed2cb8SJohan Hedberg 	if (!cp)
130956ed2cb8SJohan Hedberg 		return;
131056ed2cb8SJohan Hedberg 
131156ed2cb8SJohan Hedberg 	hci_dev_lock(hdev);
131256ed2cb8SJohan Hedberg 	hdev->adv_addr_type = cp->own_address_type;
131356ed2cb8SJohan Hedberg 	hci_dev_unlock(hdev);
131456ed2cb8SJohan Hedberg }
131556ed2cb8SJohan Hedberg 
131693c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
131793c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
131893c284eeSAndrei Emeltchenko {
131993c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
132093c284eeSAndrei Emeltchenko 
132193c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
132293c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
132393c284eeSAndrei Emeltchenko 
132493c284eeSAndrei Emeltchenko 	if (rp->status)
132593c284eeSAndrei Emeltchenko 		return;
132693c284eeSAndrei Emeltchenko 
132793c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
132893c284eeSAndrei Emeltchenko }
132993c284eeSAndrei Emeltchenko 
13305ae76a94SAndrzej Kaczmarek static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
13315ae76a94SAndrzej Kaczmarek {
13325ae76a94SAndrzej Kaczmarek 	struct hci_rp_read_rssi *rp = (void *) skb->data;
13335ae76a94SAndrzej Kaczmarek 	struct hci_conn *conn;
13345ae76a94SAndrzej Kaczmarek 
13355ae76a94SAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
13365ae76a94SAndrzej Kaczmarek 
13375ae76a94SAndrzej Kaczmarek 	if (rp->status)
13385ae76a94SAndrzej Kaczmarek 		return;
13395ae76a94SAndrzej Kaczmarek 
13405ae76a94SAndrzej Kaczmarek 	hci_dev_lock(hdev);
13415ae76a94SAndrzej Kaczmarek 
13425ae76a94SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
13435ae76a94SAndrzej Kaczmarek 	if (conn)
13445ae76a94SAndrzej Kaczmarek 		conn->rssi = rp->rssi;
13455ae76a94SAndrzej Kaczmarek 
13465ae76a94SAndrzej Kaczmarek 	hci_dev_unlock(hdev);
13475ae76a94SAndrzej Kaczmarek }
13485ae76a94SAndrzej Kaczmarek 
13495a134faeSAndrzej Kaczmarek static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb)
13505a134faeSAndrzej Kaczmarek {
13515a134faeSAndrzej Kaczmarek 	struct hci_cp_read_tx_power *sent;
13525a134faeSAndrzej Kaczmarek 	struct hci_rp_read_tx_power *rp = (void *) skb->data;
13535a134faeSAndrzej Kaczmarek 	struct hci_conn *conn;
13545a134faeSAndrzej Kaczmarek 
13555a134faeSAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
13565a134faeSAndrzej Kaczmarek 
13575a134faeSAndrzej Kaczmarek 	if (rp->status)
13585a134faeSAndrzej Kaczmarek 		return;
13595a134faeSAndrzej Kaczmarek 
13605a134faeSAndrzej Kaczmarek 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
13615a134faeSAndrzej Kaczmarek 	if (!sent)
13625a134faeSAndrzej Kaczmarek 		return;
13635a134faeSAndrzej Kaczmarek 
13645a134faeSAndrzej Kaczmarek 	hci_dev_lock(hdev);
13655a134faeSAndrzej Kaczmarek 
13665a134faeSAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1367d0455ed9SAndrzej Kaczmarek 	if (!conn)
1368d0455ed9SAndrzej Kaczmarek 		goto unlock;
13695a134faeSAndrzej Kaczmarek 
1370d0455ed9SAndrzej Kaczmarek 	switch (sent->type) {
1371d0455ed9SAndrzej Kaczmarek 	case 0x00:
1372d0455ed9SAndrzej Kaczmarek 		conn->tx_power = rp->tx_power;
1373d0455ed9SAndrzej Kaczmarek 		break;
1374d0455ed9SAndrzej Kaczmarek 	case 0x01:
1375d0455ed9SAndrzej Kaczmarek 		conn->max_tx_power = rp->tx_power;
1376d0455ed9SAndrzej Kaczmarek 		break;
1377d0455ed9SAndrzej Kaczmarek 	}
1378d0455ed9SAndrzej Kaczmarek 
1379d0455ed9SAndrzej Kaczmarek unlock:
13805a134faeSAndrzej Kaczmarek 	hci_dev_unlock(hdev);
13815a134faeSAndrzej Kaczmarek }
13825a134faeSAndrzej Kaczmarek 
13836039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1384a9de9248SMarcel Holtmann {
13859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1386a9de9248SMarcel Holtmann 
1387a9de9248SMarcel Holtmann 	if (status) {
1388a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1389314b2381SJohan Hedberg 		return;
1390314b2381SJohan Hedberg 	}
1391314b2381SJohan Hedberg 
139289352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1393a9de9248SMarcel Holtmann }
1394a9de9248SMarcel Holtmann 
13956039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
13961da177e4SLinus Torvalds {
1397a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
13981da177e4SLinus Torvalds 	struct hci_conn *conn;
13991da177e4SLinus Torvalds 
14009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1401a9de9248SMarcel Holtmann 
1402a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
14031da177e4SLinus Torvalds 	if (!cp)
14041da177e4SLinus Torvalds 		return;
14051da177e4SLinus Torvalds 
14061da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14071da177e4SLinus Torvalds 
14081da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
14091da177e4SLinus Torvalds 
14106ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
14111da177e4SLinus Torvalds 
14121da177e4SLinus Torvalds 	if (status) {
14131da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
14144c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
14151da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
14161da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
14171da177e4SLinus Torvalds 				hci_conn_del(conn);
14184c67bc74SMarcel Holtmann 			} else
14194c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
14201da177e4SLinus Torvalds 		}
14211da177e4SLinus Torvalds 	} else {
14221da177e4SLinus Torvalds 		if (!conn) {
14231da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
14241da177e4SLinus Torvalds 			if (conn) {
1425a0c808b3SJohan Hedberg 				conn->out = true;
14264dae2798SJohan Hedberg 				set_bit(HCI_CONN_MASTER, &conn->flags);
14271da177e4SLinus Torvalds 			} else
1428893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
14291da177e4SLinus Torvalds 		}
14301da177e4SLinus Torvalds 	}
14311da177e4SLinus Torvalds 
14321da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14331da177e4SLinus Torvalds }
14341da177e4SLinus Torvalds 
1435a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
14361da177e4SLinus Torvalds {
1437a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
14381da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
14391da177e4SLinus Torvalds 	__u16 handle;
14401da177e4SLinus Torvalds 
14419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1442b6a0dc82SMarcel Holtmann 
1443a9de9248SMarcel Holtmann 	if (!status)
1444a9de9248SMarcel Holtmann 		return;
1445a9de9248SMarcel Holtmann 
1446a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
14471da177e4SLinus Torvalds 	if (!cp)
1448a9de9248SMarcel Holtmann 		return;
14491da177e4SLinus Torvalds 
14501da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
14511da177e4SLinus Torvalds 
14529f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
14531da177e4SLinus Torvalds 
14541da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14551da177e4SLinus Torvalds 
14561da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14575a08ecceSAndrei Emeltchenko 	if (acl) {
14585a08ecceSAndrei Emeltchenko 		sco = acl->link;
14595a08ecceSAndrei Emeltchenko 		if (sco) {
14601da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
14611da177e4SLinus Torvalds 
14621da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
14631da177e4SLinus Torvalds 			hci_conn_del(sco);
14641da177e4SLinus Torvalds 		}
14655a08ecceSAndrei Emeltchenko 	}
14661da177e4SLinus Torvalds 
14671da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14681da177e4SLinus Torvalds }
14691da177e4SLinus Torvalds 
1470f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1471f8558555SMarcel Holtmann {
1472f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1473f8558555SMarcel Holtmann 	struct hci_conn *conn;
1474f8558555SMarcel Holtmann 
14759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1476f8558555SMarcel Holtmann 
1477f8558555SMarcel Holtmann 	if (!status)
1478f8558555SMarcel Holtmann 		return;
1479f8558555SMarcel Holtmann 
1480f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1481f8558555SMarcel Holtmann 	if (!cp)
1482f8558555SMarcel Holtmann 		return;
1483f8558555SMarcel Holtmann 
1484f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1485f8558555SMarcel Holtmann 
1486f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1487f8558555SMarcel Holtmann 	if (conn) {
1488f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1489f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
149076a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1491f8558555SMarcel Holtmann 		}
1492f8558555SMarcel Holtmann 	}
1493f8558555SMarcel Holtmann 
1494f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1495f8558555SMarcel Holtmann }
1496f8558555SMarcel Holtmann 
1497f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1498f8558555SMarcel Holtmann {
1499f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1500f8558555SMarcel Holtmann 	struct hci_conn *conn;
1501f8558555SMarcel Holtmann 
15029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1503f8558555SMarcel Holtmann 
1504f8558555SMarcel Holtmann 	if (!status)
1505f8558555SMarcel Holtmann 		return;
1506f8558555SMarcel Holtmann 
1507f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1508f8558555SMarcel Holtmann 	if (!cp)
1509f8558555SMarcel Holtmann 		return;
1510f8558555SMarcel Holtmann 
1511f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1512f8558555SMarcel Holtmann 
1513f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1514f8558555SMarcel Holtmann 	if (conn) {
1515f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1516f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
151776a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1518f8558555SMarcel Holtmann 		}
1519f8558555SMarcel Holtmann 	}
1520f8558555SMarcel Holtmann 
1521f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1522f8558555SMarcel Holtmann }
1523f8558555SMarcel Holtmann 
1524127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1525392599b9SJohan Hedberg 				    struct hci_conn *conn)
1526392599b9SJohan Hedberg {
1527392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1528392599b9SJohan Hedberg 		return 0;
1529392599b9SJohan Hedberg 
1530765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1531392599b9SJohan Hedberg 		return 0;
1532392599b9SJohan Hedberg 
1533392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1534264b8b4eSJohan Hedberg 	 * devices with sec_level MEDIUM or HIGH or if MITM protection
1535264b8b4eSJohan Hedberg 	 * is requested.
1536264b8b4eSJohan Hedberg 	 */
1537807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
15387e3691e1SJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_FIPS &&
1539264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
1540264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
1541392599b9SJohan Hedberg 		return 0;
1542392599b9SJohan Hedberg 
1543392599b9SJohan Hedberg 	return 1;
1544392599b9SJohan Hedberg }
1545392599b9SJohan Hedberg 
15466039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
154700abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
154830dc78e1SJohan Hedberg {
154930dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
155030dc78e1SJohan Hedberg 
155130dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
155230dc78e1SJohan Hedberg 
155330dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
155430dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
155530dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
155630dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
155730dc78e1SJohan Hedberg 
155830dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
155930dc78e1SJohan Hedberg }
156030dc78e1SJohan Hedberg 
1561b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
156230dc78e1SJohan Hedberg {
156330dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
156430dc78e1SJohan Hedberg 	struct inquiry_entry *e;
156530dc78e1SJohan Hedberg 
1566b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1567b644ba33SJohan Hedberg 		return false;
1568b644ba33SJohan Hedberg 
1569b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1570c810089cSRam Malovany 	if (!e)
1571c810089cSRam Malovany 		return false;
1572c810089cSRam Malovany 
1573b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1574b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1575b644ba33SJohan Hedberg 		return true;
1576b644ba33SJohan Hedberg 	}
1577b644ba33SJohan Hedberg 
1578b644ba33SJohan Hedberg 	return false;
1579b644ba33SJohan Hedberg }
1580b644ba33SJohan Hedberg 
1581b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1582b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1583b644ba33SJohan Hedberg {
1584b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1585b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1586b644ba33SJohan Hedberg 
1587b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
158804124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
158904124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1590b644ba33SJohan Hedberg 
1591b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1592b644ba33SJohan Hedberg 		return;
1593b644ba33SJohan Hedberg 
159430dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
159530dc78e1SJohan Hedberg 		goto discov_complete;
159630dc78e1SJohan Hedberg 
159730dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
159830dc78e1SJohan Hedberg 		return;
159930dc78e1SJohan Hedberg 
160030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
16017cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
16027cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
16037cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
16047cc8380eSRam Malovany 	 * Event */
16057cc8380eSRam Malovany 	if (!e)
16067cc8380eSRam Malovany 		return;
16077cc8380eSRam Malovany 
160830dc78e1SJohan Hedberg 	list_del(&e->list);
16097cc8380eSRam Malovany 	if (name) {
16107cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1611b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1612b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1613c3e7c0d9SRam Malovany 	} else {
1614c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
161530dc78e1SJohan Hedberg 	}
161630dc78e1SJohan Hedberg 
1617b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
161830dc78e1SJohan Hedberg 		return;
161930dc78e1SJohan Hedberg 
162030dc78e1SJohan Hedberg discov_complete:
162130dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
162230dc78e1SJohan Hedberg }
162330dc78e1SJohan Hedberg 
1624a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
16251da177e4SLinus Torvalds {
1626127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1627127178d2SJohan Hedberg 	struct hci_conn *conn;
1628127178d2SJohan Hedberg 
16299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1630127178d2SJohan Hedberg 
1631127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1632127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1633127178d2SJohan Hedberg 	if (!status)
1634127178d2SJohan Hedberg 		return;
1635127178d2SJohan Hedberg 
1636127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1637127178d2SJohan Hedberg 	if (!cp)
1638127178d2SJohan Hedberg 		return;
1639127178d2SJohan Hedberg 
1640127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1641127178d2SJohan Hedberg 
1642127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1643b644ba33SJohan Hedberg 
1644b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1645b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1646b644ba33SJohan Hedberg 
164779c6c70cSJohan Hedberg 	if (!conn)
164879c6c70cSJohan Hedberg 		goto unlock;
164979c6c70cSJohan Hedberg 
165079c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
165179c6c70cSJohan Hedberg 		goto unlock;
165279c6c70cSJohan Hedberg 
165351a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1654c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
1655c1f23a2bSJohannes Berg 
1656c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
1657c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1658c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
1659127178d2SJohan Hedberg 	}
1660127178d2SJohan Hedberg 
166179c6c70cSJohan Hedberg unlock:
1662127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1663a9de9248SMarcel Holtmann }
16641da177e4SLinus Torvalds 
1665769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1666769be974SMarcel Holtmann {
1667769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1668769be974SMarcel Holtmann 	struct hci_conn *conn;
1669769be974SMarcel Holtmann 
16709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1671769be974SMarcel Holtmann 
1672769be974SMarcel Holtmann 	if (!status)
1673769be974SMarcel Holtmann 		return;
1674769be974SMarcel Holtmann 
1675769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1676769be974SMarcel Holtmann 	if (!cp)
1677769be974SMarcel Holtmann 		return;
1678769be974SMarcel Holtmann 
1679769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1680769be974SMarcel Holtmann 
1681769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1682769be974SMarcel Holtmann 	if (conn) {
1683769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1684769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
168576a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1686769be974SMarcel Holtmann 		}
1687769be974SMarcel Holtmann 	}
1688769be974SMarcel Holtmann 
1689769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1690769be974SMarcel Holtmann }
1691769be974SMarcel Holtmann 
1692769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1693769be974SMarcel Holtmann {
1694769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1695769be974SMarcel Holtmann 	struct hci_conn *conn;
1696769be974SMarcel Holtmann 
16979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1698769be974SMarcel Holtmann 
1699769be974SMarcel Holtmann 	if (!status)
1700769be974SMarcel Holtmann 		return;
1701769be974SMarcel Holtmann 
1702769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1703769be974SMarcel Holtmann 	if (!cp)
1704769be974SMarcel Holtmann 		return;
1705769be974SMarcel Holtmann 
1706769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1707769be974SMarcel Holtmann 
1708769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1709769be974SMarcel Holtmann 	if (conn) {
1710769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1711769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
171276a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1713769be974SMarcel Holtmann 		}
1714769be974SMarcel Holtmann 	}
1715769be974SMarcel Holtmann 
1716769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1717769be974SMarcel Holtmann }
1718769be974SMarcel Holtmann 
1719a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1720a9de9248SMarcel Holtmann {
1721b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1722b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1723b6a0dc82SMarcel Holtmann 	__u16 handle;
1724b6a0dc82SMarcel Holtmann 
17259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1726b6a0dc82SMarcel Holtmann 
1727b6a0dc82SMarcel Holtmann 	if (!status)
1728b6a0dc82SMarcel Holtmann 		return;
1729b6a0dc82SMarcel Holtmann 
1730b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1731b6a0dc82SMarcel Holtmann 	if (!cp)
1732b6a0dc82SMarcel Holtmann 		return;
1733b6a0dc82SMarcel Holtmann 
1734b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1735b6a0dc82SMarcel Holtmann 
17369f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1737b6a0dc82SMarcel Holtmann 
1738b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1739b6a0dc82SMarcel Holtmann 
1740b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
17415a08ecceSAndrei Emeltchenko 	if (acl) {
17425a08ecceSAndrei Emeltchenko 		sco = acl->link;
17435a08ecceSAndrei Emeltchenko 		if (sco) {
1744b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1745b6a0dc82SMarcel Holtmann 
1746b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1747b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1748b6a0dc82SMarcel Holtmann 		}
17495a08ecceSAndrei Emeltchenko 	}
1750b6a0dc82SMarcel Holtmann 
1751b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1752a9de9248SMarcel Holtmann }
1753a9de9248SMarcel Holtmann 
1754a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1755a9de9248SMarcel Holtmann {
1756a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
175704837f64SMarcel Holtmann 	struct hci_conn *conn;
175804837f64SMarcel Holtmann 
17599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1760a9de9248SMarcel Holtmann 
1761a9de9248SMarcel Holtmann 	if (!status)
1762a9de9248SMarcel Holtmann 		return;
1763a9de9248SMarcel Holtmann 
1764a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
176504837f64SMarcel Holtmann 	if (!cp)
1766a9de9248SMarcel Holtmann 		return;
176704837f64SMarcel Holtmann 
176804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
176904837f64SMarcel Holtmann 
177004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1771e73439d8SMarcel Holtmann 	if (conn) {
177251a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
177304837f64SMarcel Holtmann 
177451a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1775e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1776e73439d8SMarcel Holtmann 	}
1777e73439d8SMarcel Holtmann 
177804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
177904837f64SMarcel Holtmann }
178004837f64SMarcel Holtmann 
1781a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1782a9de9248SMarcel Holtmann {
1783a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
178404837f64SMarcel Holtmann 	struct hci_conn *conn;
178504837f64SMarcel Holtmann 
17869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1787a9de9248SMarcel Holtmann 
1788a9de9248SMarcel Holtmann 	if (!status)
1789a9de9248SMarcel Holtmann 		return;
1790a9de9248SMarcel Holtmann 
1791a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
179204837f64SMarcel Holtmann 	if (!cp)
1793a9de9248SMarcel Holtmann 		return;
179404837f64SMarcel Holtmann 
179504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
179604837f64SMarcel Holtmann 
179704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1798e73439d8SMarcel Holtmann 	if (conn) {
179951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
180004837f64SMarcel Holtmann 
180151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1802e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1803e73439d8SMarcel Holtmann 	}
1804e73439d8SMarcel Holtmann 
180504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
180604837f64SMarcel Holtmann }
180704837f64SMarcel Holtmann 
180888c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
180988c3df13SJohan Hedberg {
181088c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
181188c3df13SJohan Hedberg 	struct hci_conn *conn;
181288c3df13SJohan Hedberg 
181388c3df13SJohan Hedberg 	if (!status)
181488c3df13SJohan Hedberg 		return;
181588c3df13SJohan Hedberg 
181688c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
181788c3df13SJohan Hedberg 	if (!cp)
181888c3df13SJohan Hedberg 		return;
181988c3df13SJohan Hedberg 
182088c3df13SJohan Hedberg 	hci_dev_lock(hdev);
182188c3df13SJohan Hedberg 
182288c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
182388c3df13SJohan Hedberg 	if (conn)
182488c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
182588c3df13SJohan Hedberg 				       conn->dst_type, status);
182688c3df13SJohan Hedberg 
182788c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
182888c3df13SJohan Hedberg }
182988c3df13SJohan Hedberg 
1830a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1831a02226d6SAndrei Emeltchenko {
183293c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
183393c284eeSAndrei Emeltchenko 
1834a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
183593c284eeSAndrei Emeltchenko 
183693c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
183793c284eeSAndrei Emeltchenko 	if (!cp)
183893c284eeSAndrei Emeltchenko 		return;
183993c284eeSAndrei Emeltchenko 
1840e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1841e58917b9SAndrei Emeltchenko 
1842e58917b9SAndrei Emeltchenko 	if (status) {
1843e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1844e58917b9SAndrei Emeltchenko 
1845e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1846e58917b9SAndrei Emeltchenko 		if (hcon)
1847e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1848e58917b9SAndrei Emeltchenko 	} else {
184993c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1850a02226d6SAndrei Emeltchenko 	}
1851a02226d6SAndrei Emeltchenko 
1852e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1853e58917b9SAndrei Emeltchenko }
1854e58917b9SAndrei Emeltchenko 
18550b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
18560b26ab9dSAndrei Emeltchenko {
18570b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
18580b26ab9dSAndrei Emeltchenko 
18590b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18600b26ab9dSAndrei Emeltchenko 
18610b26ab9dSAndrei Emeltchenko 	if (status)
18620b26ab9dSAndrei Emeltchenko 		return;
18630b26ab9dSAndrei Emeltchenko 
18640b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
18650b26ab9dSAndrei Emeltchenko 	if (!cp)
18660b26ab9dSAndrei Emeltchenko 		return;
18670b26ab9dSAndrei Emeltchenko 
18680b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
18690b26ab9dSAndrei Emeltchenko }
18700b26ab9dSAndrei Emeltchenko 
1871cb1d68f7SJohan Hedberg static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
1872cb1d68f7SJohan Hedberg {
1873cb1d68f7SJohan Hedberg 	struct hci_cp_le_create_conn *cp;
1874cb1d68f7SJohan Hedberg 	struct hci_conn *conn;
1875cb1d68f7SJohan Hedberg 
1876cb1d68f7SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1877cb1d68f7SJohan Hedberg 
1878cb1d68f7SJohan Hedberg 	/* All connection failure handling is taken care of by the
1879cb1d68f7SJohan Hedberg 	 * hci_le_conn_failed function which is triggered by the HCI
1880cb1d68f7SJohan Hedberg 	 * request completion callbacks used for connecting.
1881cb1d68f7SJohan Hedberg 	 */
1882cb1d68f7SJohan Hedberg 	if (status)
1883cb1d68f7SJohan Hedberg 		return;
1884cb1d68f7SJohan Hedberg 
1885cb1d68f7SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1886cb1d68f7SJohan Hedberg 	if (!cp)
1887cb1d68f7SJohan Hedberg 		return;
1888cb1d68f7SJohan Hedberg 
1889cb1d68f7SJohan Hedberg 	hci_dev_lock(hdev);
1890cb1d68f7SJohan Hedberg 
1891cb1d68f7SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1892cb1d68f7SJohan Hedberg 	if (!conn)
1893cb1d68f7SJohan Hedberg 		goto unlock;
1894cb1d68f7SJohan Hedberg 
1895cb1d68f7SJohan Hedberg 	/* Store the initiator and responder address information which
1896cb1d68f7SJohan Hedberg 	 * is needed for SMP. These values will not change during the
1897cb1d68f7SJohan Hedberg 	 * lifetime of the connection.
1898cb1d68f7SJohan Hedberg 	 */
1899cb1d68f7SJohan Hedberg 	conn->init_addr_type = cp->own_address_type;
1900cb1d68f7SJohan Hedberg 	if (cp->own_address_type == ADDR_LE_DEV_RANDOM)
1901cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &hdev->random_addr);
1902cb1d68f7SJohan Hedberg 	else
1903cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &hdev->bdaddr);
1904cb1d68f7SJohan Hedberg 
1905cb1d68f7SJohan Hedberg 	conn->resp_addr_type = cp->peer_addr_type;
1906cb1d68f7SJohan Hedberg 	bacpy(&conn->resp_addr, &cp->peer_addr);
1907cb1d68f7SJohan Hedberg 
19089489eca4SJohan Hedberg 	/* We don't want the connection attempt to stick around
19099489eca4SJohan Hedberg 	 * indefinitely since LE doesn't have a page timeout concept
19109489eca4SJohan Hedberg 	 * like BR/EDR. Set a timer for any connection that doesn't use
19119489eca4SJohan Hedberg 	 * the white list for connecting.
19129489eca4SJohan Hedberg 	 */
19139489eca4SJohan Hedberg 	if (cp->filter_policy == HCI_LE_USE_PEER_ADDR)
19149489eca4SJohan Hedberg 		queue_delayed_work(conn->hdev->workqueue,
19159489eca4SJohan Hedberg 				   &conn->le_conn_timeout,
191609ae260bSJohan Hedberg 				   conn->conn_timeout);
19179489eca4SJohan Hedberg 
1918cb1d68f7SJohan Hedberg unlock:
1919cb1d68f7SJohan Hedberg 	hci_dev_unlock(hdev);
1920cb1d68f7SJohan Hedberg }
1921cb1d68f7SJohan Hedberg 
192281d0c8adSJohan Hedberg static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
192381d0c8adSJohan Hedberg {
192481d0c8adSJohan Hedberg 	struct hci_cp_le_start_enc *cp;
192581d0c8adSJohan Hedberg 	struct hci_conn *conn;
192681d0c8adSJohan Hedberg 
192781d0c8adSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
192881d0c8adSJohan Hedberg 
192981d0c8adSJohan Hedberg 	if (!status)
193081d0c8adSJohan Hedberg 		return;
193181d0c8adSJohan Hedberg 
193281d0c8adSJohan Hedberg 	hci_dev_lock(hdev);
193381d0c8adSJohan Hedberg 
193481d0c8adSJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC);
193581d0c8adSJohan Hedberg 	if (!cp)
193681d0c8adSJohan Hedberg 		goto unlock;
193781d0c8adSJohan Hedberg 
193881d0c8adSJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
193981d0c8adSJohan Hedberg 	if (!conn)
194081d0c8adSJohan Hedberg 		goto unlock;
194181d0c8adSJohan Hedberg 
194281d0c8adSJohan Hedberg 	if (conn->state != BT_CONNECTED)
194381d0c8adSJohan Hedberg 		goto unlock;
194481d0c8adSJohan Hedberg 
194581d0c8adSJohan Hedberg 	hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
194681d0c8adSJohan Hedberg 	hci_conn_drop(conn);
194781d0c8adSJohan Hedberg 
194881d0c8adSJohan Hedberg unlock:
194981d0c8adSJohan Hedberg 	hci_dev_unlock(hdev);
195081d0c8adSJohan Hedberg }
195181d0c8adSJohan Hedberg 
19526039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19531da177e4SLinus Torvalds {
19541da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
195530dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
195630dc78e1SJohan Hedberg 	struct inquiry_entry *e;
19571da177e4SLinus Torvalds 
19589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
19591da177e4SLinus Torvalds 
1960a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
196189352e7dSAndre Guedes 
196289352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
196389352e7dSAndre Guedes 		return;
196489352e7dSAndre Guedes 
19654e857c58SPeter Zijlstra 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
19663e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
19673e13fa1eSAndre Guedes 
1968a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
196930dc78e1SJohan Hedberg 		return;
197030dc78e1SJohan Hedberg 
197156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
197230dc78e1SJohan Hedberg 
1973343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
197430dc78e1SJohan Hedberg 		goto unlock;
197530dc78e1SJohan Hedberg 
197630dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1977ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
197830dc78e1SJohan Hedberg 		goto unlock;
197930dc78e1SJohan Hedberg 	}
198030dc78e1SJohan Hedberg 
198130dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
198230dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
198330dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
198430dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
198530dc78e1SJohan Hedberg 	} else {
198630dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
198730dc78e1SJohan Hedberg 	}
198830dc78e1SJohan Hedberg 
198930dc78e1SJohan Hedberg unlock:
199056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
19911da177e4SLinus Torvalds }
19921da177e4SLinus Torvalds 
19936039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
19941da177e4SLinus Torvalds {
199545bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1996a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
19971da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
19981da177e4SLinus Torvalds 
19991da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
20001da177e4SLinus Torvalds 
200145bb4bf0SMarcel Holtmann 	if (!num_rsp)
200245bb4bf0SMarcel Holtmann 		return;
200345bb4bf0SMarcel Holtmann 
20041519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
20051519cc17SAndre Guedes 		return;
20061519cc17SAndre Guedes 
20071da177e4SLinus Torvalds 	hci_dev_lock(hdev);
200845bb4bf0SMarcel Holtmann 
2009e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2010af58925cSMarcel Holtmann 		u32 flags;
20113175405bSJohan Hedberg 
20121da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
20131da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
20141da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
20151da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
20161da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
20171da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
20181da177e4SLinus Torvalds 		data.rssi		= 0x00;
201941a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
20203175405bSJohan Hedberg 
2021af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, false);
2022af58925cSMarcel Holtmann 
202348264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2024af58925cSMarcel Holtmann 				  info->dev_class, 0, flags, NULL, 0, NULL, 0);
20251da177e4SLinus Torvalds 	}
202645bb4bf0SMarcel Holtmann 
20271da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
20281da177e4SLinus Torvalds }
20291da177e4SLinus Torvalds 
20306039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
20311da177e4SLinus Torvalds {
2032a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
2033a9de9248SMarcel Holtmann 	struct hci_conn *conn;
20341da177e4SLinus Torvalds 
2035a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
203645bb4bf0SMarcel Holtmann 
20371da177e4SLinus Torvalds 	hci_dev_lock(hdev);
203845bb4bf0SMarcel Holtmann 
2039a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
20409499237aSMarcel Holtmann 	if (!conn) {
20419499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
20429499237aSMarcel Holtmann 			goto unlock;
20439499237aSMarcel Holtmann 
20449499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2045a9de9248SMarcel Holtmann 		if (!conn)
2046a9de9248SMarcel Holtmann 			goto unlock;
204745bb4bf0SMarcel Holtmann 
20489499237aSMarcel Holtmann 		conn->type = SCO_LINK;
20499499237aSMarcel Holtmann 	}
20509499237aSMarcel Holtmann 
2051a9de9248SMarcel Holtmann 	if (!ev->status) {
2052a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2053769be974SMarcel Holtmann 
2054769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2055769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
2056769be974SMarcel Holtmann 			hci_conn_hold(conn);
2057a9ea3ed9SSzymon Janc 
2058a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
2059a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
2060a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2061a9ea3ed9SSzymon Janc 			else
2062052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2063769be974SMarcel Holtmann 		} else
2064a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
2065a9de9248SMarcel Holtmann 
20667d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
20677d0db0a3SMarcel Holtmann 
2068a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
20694dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2070a9de9248SMarcel Holtmann 
2071a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
20724dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2073a9de9248SMarcel Holtmann 
2074a9de9248SMarcel Holtmann 		/* Get remote features */
2075a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2076a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
2077a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2078769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
2079769be974SMarcel Holtmann 				     sizeof(cp), &cp);
208045bb4bf0SMarcel Holtmann 		}
2081a9de9248SMarcel Holtmann 
2082a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
2083d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
2084a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
2085a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2086a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
208704124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
208804124681SGustavo F. Padovan 				     &cp);
2089a9de9248SMarcel Holtmann 		}
209017d5c04cSJohan Hedberg 	} else {
2091a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
209217d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
209364c7b77cSMarcel Holtmann 			mgmt_connect_failed(hdev, &conn->dst, conn->type,
209448264f06SJohan Hedberg 					    conn->dst_type, ev->status);
209517d5c04cSJohan Hedberg 	}
209645bb4bf0SMarcel Holtmann 
2097e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
2098e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
209945bb4bf0SMarcel Holtmann 
2100769be974SMarcel Holtmann 	if (ev->status) {
2101a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2102a9de9248SMarcel Holtmann 		hci_conn_del(conn);
2103c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
2104c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2105a9de9248SMarcel Holtmann 
2106a9de9248SMarcel Holtmann unlock:
21071da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
2108a9de9248SMarcel Holtmann 
2109a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
21101da177e4SLinus Torvalds }
21111da177e4SLinus Torvalds 
21126039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
21131da177e4SLinus Torvalds {
2114a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
21151da177e4SLinus Torvalds 	int mask = hdev->link_mode;
211620714bfeSFrédéric Dalleau 	__u8 flags = 0;
21171da177e4SLinus Torvalds 
21186ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
2119807deac2SGustavo Padovan 	       ev->link_type);
21201da177e4SLinus Torvalds 
212120714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
212220714bfeSFrédéric Dalleau 				      &flags);
21231da177e4SLinus Torvalds 
2124138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
2125b9ee0a78SMarcel Holtmann 	    !hci_blacklist_lookup(hdev, &ev->bdaddr, BDADDR_BREDR)) {
21261da177e4SLinus Torvalds 		/* Connection accepted */
2127c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
21281da177e4SLinus Torvalds 		struct hci_conn *conn;
21291da177e4SLinus Torvalds 
21301da177e4SLinus Torvalds 		hci_dev_lock(hdev);
2131b6a0dc82SMarcel Holtmann 
2132cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2133cc11b9c1SAndrei Emeltchenko 		if (ie)
2134c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
2135c7bdd502SMarcel Holtmann 
21368fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
21378fc9ced3SGustavo Padovan 					       &ev->bdaddr);
21381da177e4SLinus Torvalds 		if (!conn) {
2139cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2140cc11b9c1SAndrei Emeltchenko 			if (!conn) {
2141893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
21421da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
21431da177e4SLinus Torvalds 				return;
21441da177e4SLinus Torvalds 			}
21451da177e4SLinus Torvalds 		}
2146b6a0dc82SMarcel Holtmann 
21471da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
2148b6a0dc82SMarcel Holtmann 
21491da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
21501da177e4SLinus Torvalds 
215120714bfeSFrédéric Dalleau 		if (ev->link_type == ACL_LINK ||
215220714bfeSFrédéric Dalleau 		    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
2153b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
215420714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
2155b6a0dc82SMarcel Holtmann 
21561da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
21571da177e4SLinus Torvalds 
21581da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
21591da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
21601da177e4SLinus Torvalds 			else
21611da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
21621da177e4SLinus Torvalds 
216304124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
216404124681SGustavo F. Padovan 				     &cp);
216520714bfeSFrédéric Dalleau 		} else if (!(flags & HCI_PROTO_DEFER)) {
2166b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
216720714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
2168b6a0dc82SMarcel Holtmann 
2169b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
2170a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
2171b6a0dc82SMarcel Holtmann 
2172dcf4adbfSJoe Perches 			cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
2173dcf4adbfSJoe Perches 			cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
2174dcf4adbfSJoe Perches 			cp.max_latency    = cpu_to_le16(0xffff);
2175b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
2176b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
2177b6a0dc82SMarcel Holtmann 
2178b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2179b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
218020714bfeSFrédéric Dalleau 		} else {
218120714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT2;
218220714bfeSFrédéric Dalleau 			hci_proto_connect_cfm(conn, 0);
2183b6a0dc82SMarcel Holtmann 		}
21841da177e4SLinus Torvalds 	} else {
21851da177e4SLinus Torvalds 		/* Connection rejected */
21861da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
21871da177e4SLinus Torvalds 
21881da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
21899f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
2190a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
21911da177e4SLinus Torvalds 	}
21921da177e4SLinus Torvalds }
21931da177e4SLinus Torvalds 
2194f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2195f0d6a0eaSMikel Astiz {
2196f0d6a0eaSMikel Astiz 	switch (err) {
2197f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2198f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2199f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2200f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2201f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2202f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2203f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2204f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2205f0d6a0eaSMikel Astiz 	default:
2206f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2207f0d6a0eaSMikel Astiz 	}
2208f0d6a0eaSMikel Astiz }
2209f0d6a0eaSMikel Astiz 
22106039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
22111da177e4SLinus Torvalds {
2212a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
2213abf54a50SAndre Guedes 	u8 reason = hci_to_mgmt_reason(ev->reason);
22149fcb18efSAndre Guedes 	struct hci_conn_params *params;
221504837f64SMarcel Holtmann 	struct hci_conn *conn;
221612d4a3b2SJohan Hedberg 	bool mgmt_connected;
22173846220bSAndre Guedes 	u8 type;
22181da177e4SLinus Torvalds 
22199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
22201da177e4SLinus Torvalds 
22211da177e4SLinus Torvalds 	hci_dev_lock(hdev);
22221da177e4SLinus Torvalds 
222304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2224f7520543SJohan Hedberg 	if (!conn)
2225f7520543SJohan Hedberg 		goto unlock;
2226f7520543SJohan Hedberg 
2227f0d6a0eaSMikel Astiz 	if (ev->status) {
222888c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
222988c3df13SJohan Hedberg 				       conn->dst_type, ev->status);
2230abf54a50SAndre Guedes 		goto unlock;
2231abf54a50SAndre Guedes 	}
2232f0d6a0eaSMikel Astiz 
22333846220bSAndre Guedes 	conn->state = BT_CLOSED;
22343846220bSAndre Guedes 
223512d4a3b2SJohan Hedberg 	mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
223612d4a3b2SJohan Hedberg 	mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
223712d4a3b2SJohan Hedberg 				reason, mgmt_connected);
2238f7520543SJohan Hedberg 
2239af6a9c32SJohan Hedberg 	if (conn->type == ACL_LINK &&
2240af6a9c32SJohan Hedberg 	    test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
22416ec5bcadSVishal Agarwal 		hci_remove_link_key(hdev, &conn->dst);
22423846220bSAndre Guedes 
22439fcb18efSAndre Guedes 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
22449fcb18efSAndre Guedes 	if (params) {
22459fcb18efSAndre Guedes 		switch (params->auto_connect) {
22469fcb18efSAndre Guedes 		case HCI_AUTO_CONN_LINK_LOSS:
22479fcb18efSAndre Guedes 			if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
22489fcb18efSAndre Guedes 				break;
22499fcb18efSAndre Guedes 			/* Fall through */
22509fcb18efSAndre Guedes 
22519fcb18efSAndre Guedes 		case HCI_AUTO_CONN_ALWAYS:
2252418025d1SJohan Hedberg 			list_del_init(&params->action);
2253418025d1SJohan Hedberg 			list_add(&params->action, &hdev->pend_le_conns);
2254418025d1SJohan Hedberg 			hci_update_background_scan(hdev);
22559fcb18efSAndre Guedes 			break;
22569fcb18efSAndre Guedes 
22579fcb18efSAndre Guedes 		default:
22589fcb18efSAndre Guedes 			break;
22599fcb18efSAndre Guedes 		}
22609fcb18efSAndre Guedes 	}
22619fcb18efSAndre Guedes 
22623846220bSAndre Guedes 	type = conn->type;
22633846220bSAndre Guedes 
22642950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
22651da177e4SLinus Torvalds 	hci_conn_del(conn);
22662210246cSJohan Hedberg 
22672210246cSJohan Hedberg 	/* Re-enable advertising if necessary, since it might
22682210246cSJohan Hedberg 	 * have been disabled by the connection. From the
22692210246cSJohan Hedberg 	 * HCI_LE_Set_Advertise_Enable command description in
22702210246cSJohan Hedberg 	 * the core specification (v4.0):
22712210246cSJohan Hedberg 	 * "The Controller shall continue advertising until the Host
22722210246cSJohan Hedberg 	 * issues an LE_Set_Advertise_Enable command with
22732210246cSJohan Hedberg 	 * Advertising_Enable set to 0x00 (Advertising is disabled)
22742210246cSJohan Hedberg 	 * or until a connection is created or until the Advertising
22752210246cSJohan Hedberg 	 * is timed out due to Directed Advertising."
22762210246cSJohan Hedberg 	 */
22772210246cSJohan Hedberg 	if (type == LE_LINK)
22785976e608SMarcel Holtmann 		mgmt_reenable_advertising(hdev);
22791da177e4SLinus Torvalds 
2280f7520543SJohan Hedberg unlock:
22811da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
22821da177e4SLinus Torvalds }
22831da177e4SLinus Torvalds 
22846039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2285a9de9248SMarcel Holtmann {
2286a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2287a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2288a9de9248SMarcel Holtmann 
22899f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2290a9de9248SMarcel Holtmann 
2291a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2292a9de9248SMarcel Holtmann 
2293a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2294d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2295d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2296d7556e20SWaldemar Rymarkiewicz 
2297765c2a96SJohan Hedberg 	if (!ev->status) {
2298aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
229951a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2300d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
230119f8def0SWaldemar Rymarkiewicz 		} else {
23024dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2303765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
230419f8def0SWaldemar Rymarkiewicz 		}
23052a611692SJohan Hedberg 	} else {
2306bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
2307bab73cb6SJohan Hedberg 				 ev->status);
23082a611692SJohan Hedberg 	}
2309a9de9248SMarcel Holtmann 
231051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
231151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2312a9de9248SMarcel Holtmann 
2313f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2314aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2315f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2316f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2317f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2318d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2319d7556e20SWaldemar Rymarkiewicz 				     &cp);
2320f8558555SMarcel Holtmann 		} else {
2321f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2322f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
232376a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2324f8558555SMarcel Holtmann 		}
2325052b30b0SMarcel Holtmann 	} else {
2326a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2327a9de9248SMarcel Holtmann 
2328052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2329052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
233076a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2331052b30b0SMarcel Holtmann 	}
2332052b30b0SMarcel Holtmann 
233351a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2334a9de9248SMarcel Holtmann 		if (!ev->status) {
2335a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2336f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2337f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2338d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2339d7556e20SWaldemar Rymarkiewicz 				     &cp);
2340a9de9248SMarcel Holtmann 		} else {
234151a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2342a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2343a9de9248SMarcel Holtmann 		}
2344a9de9248SMarcel Holtmann 	}
2345a9de9248SMarcel Holtmann 
2346d7556e20SWaldemar Rymarkiewicz unlock:
2347a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2348a9de9248SMarcel Holtmann }
2349a9de9248SMarcel Holtmann 
23506039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2351a9de9248SMarcel Holtmann {
2352127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2353127178d2SJohan Hedberg 	struct hci_conn *conn;
2354127178d2SJohan Hedberg 
2355a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2356a9de9248SMarcel Holtmann 
2357a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2358127178d2SJohan Hedberg 
2359127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2360127178d2SJohan Hedberg 
2361127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2362b644ba33SJohan Hedberg 
2363b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2364b644ba33SJohan Hedberg 		goto check_auth;
2365b644ba33SJohan Hedberg 
2366b644ba33SJohan Hedberg 	if (ev->status == 0)
2367b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2368b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2369b644ba33SJohan Hedberg 	else
2370b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2371b644ba33SJohan Hedberg 
2372b644ba33SJohan Hedberg check_auth:
237379c6c70cSJohan Hedberg 	if (!conn)
237479c6c70cSJohan Hedberg 		goto unlock;
237579c6c70cSJohan Hedberg 
237679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
237779c6c70cSJohan Hedberg 		goto unlock;
237879c6c70cSJohan Hedberg 
237951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2380127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2381127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2382127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2383127178d2SJohan Hedberg 	}
2384127178d2SJohan Hedberg 
238579c6c70cSJohan Hedberg unlock:
2386127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2387a9de9248SMarcel Holtmann }
2388a9de9248SMarcel Holtmann 
23896039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2390a9de9248SMarcel Holtmann {
2391a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2392a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2393a9de9248SMarcel Holtmann 
23949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2395a9de9248SMarcel Holtmann 
2396a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2397a9de9248SMarcel Holtmann 
2398a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2399dc8357ccSMarcel Holtmann 	if (!conn)
2400dc8357ccSMarcel Holtmann 		goto unlock;
2401dc8357ccSMarcel Holtmann 
2402a9de9248SMarcel Holtmann 	if (!ev->status) {
2403ae293196SMarcel Holtmann 		if (ev->encrypt) {
2404ae293196SMarcel Holtmann 			/* Encryption implies authentication */
24054dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
24064dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2407da85e5e5SVinicius Costa Gomes 			conn->sec_level = conn->pending_sec_level;
2408abf76badSMarcel Holtmann 
2409914a6ffeSMarcel Holtmann 			/* P-256 authentication key implies FIPS */
2410914a6ffeSMarcel Holtmann 			if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
24114dae2798SJohan Hedberg 				set_bit(HCI_CONN_FIPS, &conn->flags);
2412914a6ffeSMarcel Holtmann 
2413abf76badSMarcel Holtmann 			if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
2414abf76badSMarcel Holtmann 			    conn->type == LE_LINK)
2415abf76badSMarcel Holtmann 				set_bit(HCI_CONN_AES_CCM, &conn->flags);
2416abf76badSMarcel Holtmann 		} else {
24174dae2798SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
2418abf76badSMarcel Holtmann 			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
2419abf76badSMarcel Holtmann 		}
2420a9de9248SMarcel Holtmann 	}
2421a9de9248SMarcel Holtmann 
242251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2423a9de9248SMarcel Holtmann 
2424a7d7723aSGustavo Padovan 	if (ev->status && conn->state == BT_CONNECTED) {
2425bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
242676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2427a7d7723aSGustavo Padovan 		goto unlock;
2428a7d7723aSGustavo Padovan 	}
2429a7d7723aSGustavo Padovan 
2430f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2431f8558555SMarcel Holtmann 		if (!ev->status)
2432f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2433f8558555SMarcel Holtmann 
243440b552aaSMarcel Holtmann 		/* In Secure Connections Only mode, do not allow any
243540b552aaSMarcel Holtmann 		 * connections that are not encrypted with AES-CCM
243640b552aaSMarcel Holtmann 		 * using a P-256 authenticated combination key.
243740b552aaSMarcel Holtmann 		 */
243840b552aaSMarcel Holtmann 		if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) &&
243940b552aaSMarcel Holtmann 		    (!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
244040b552aaSMarcel Holtmann 		     conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) {
244140b552aaSMarcel Holtmann 			hci_proto_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE);
244240b552aaSMarcel Holtmann 			hci_conn_drop(conn);
244340b552aaSMarcel Holtmann 			goto unlock;
244440b552aaSMarcel Holtmann 		}
244540b552aaSMarcel Holtmann 
2446f8558555SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
244776a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2448f8558555SMarcel Holtmann 	} else
2449a9de9248SMarcel Holtmann 		hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2450a9de9248SMarcel Holtmann 
2451a7d7723aSGustavo Padovan unlock:
2452a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2453a9de9248SMarcel Holtmann }
2454a9de9248SMarcel Holtmann 
24556039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2456807deac2SGustavo Padovan 					     struct sk_buff *skb)
2457a9de9248SMarcel Holtmann {
2458a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2459a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2460a9de9248SMarcel Holtmann 
24619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2462a9de9248SMarcel Holtmann 
2463a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2464a9de9248SMarcel Holtmann 
2465a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2466a9de9248SMarcel Holtmann 	if (conn) {
2467a9de9248SMarcel Holtmann 		if (!ev->status)
24684dae2798SJohan Hedberg 			set_bit(HCI_CONN_SECURE, &conn->flags);
2469a9de9248SMarcel Holtmann 
247051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2471a9de9248SMarcel Holtmann 
2472a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2473a9de9248SMarcel Holtmann 	}
2474a9de9248SMarcel Holtmann 
2475a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2476a9de9248SMarcel Holtmann }
2477a9de9248SMarcel Holtmann 
24786039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2479807deac2SGustavo Padovan 				    struct sk_buff *skb)
2480a9de9248SMarcel Holtmann {
2481a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2482a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2483a9de9248SMarcel Holtmann 
24849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2485a9de9248SMarcel Holtmann 
2486a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2487a9de9248SMarcel Holtmann 
2488a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2489ccd556feSJohan Hedberg 	if (!conn)
2490ccd556feSJohan Hedberg 		goto unlock;
2491ccd556feSJohan Hedberg 
2492769be974SMarcel Holtmann 	if (!ev->status)
2493cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
2494a9de9248SMarcel Holtmann 
2495ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2496ccd556feSJohan Hedberg 		goto unlock;
2497ccd556feSJohan Hedberg 
2498ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2499769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2500769be974SMarcel Holtmann 		cp.handle = ev->handle;
2501769be974SMarcel Holtmann 		cp.page = 0x01;
2502ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2503769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2504392599b9SJohan Hedberg 		goto unlock;
2505392599b9SJohan Hedberg 	}
2506392599b9SJohan Hedberg 
2507671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2508127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2509127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2510127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2511127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2512127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2513b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2514b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
251508c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2516b644ba33SJohan Hedberg 				      conn->dev_class);
2517392599b9SJohan Hedberg 
2518127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2519769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2520769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
252176a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2522769be974SMarcel Holtmann 	}
2523769be974SMarcel Holtmann 
2524ccd556feSJohan Hedberg unlock:
2525a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2526a9de9248SMarcel Holtmann }
2527a9de9248SMarcel Holtmann 
25286039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2529a9de9248SMarcel Holtmann {
2530a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
25319238f36aSJohan Hedberg 	u8 status = skb->data[sizeof(*ev)];
2532a9de9248SMarcel Holtmann 	__u16 opcode;
2533a9de9248SMarcel Holtmann 
2534a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2535a9de9248SMarcel Holtmann 
2536a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2537a9de9248SMarcel Holtmann 
2538a9de9248SMarcel Holtmann 	switch (opcode) {
2539a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2540a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2541a9de9248SMarcel Holtmann 		break;
2542a9de9248SMarcel Holtmann 
25434d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
25444d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
25454d93483bSAndre Guedes 		break;
25464d93483bSAndre Guedes 
2547a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2548a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2549a9de9248SMarcel Holtmann 		break;
2550a9de9248SMarcel Holtmann 
2551a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2552a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2553a9de9248SMarcel Holtmann 		break;
2554a9de9248SMarcel Holtmann 
2555a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2556a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2557a9de9248SMarcel Holtmann 		break;
2558a9de9248SMarcel Holtmann 
2559e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2560e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2561e4e8e37cSMarcel Holtmann 		break;
2562e4e8e37cSMarcel Holtmann 
2563a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2564a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2565a9de9248SMarcel Holtmann 		break;
2566a9de9248SMarcel Holtmann 
2567e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2568e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2569e4e8e37cSMarcel Holtmann 		break;
2570e4e8e37cSMarcel Holtmann 
2571e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2572e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2573e4e8e37cSMarcel Holtmann 		break;
2574e4e8e37cSMarcel Holtmann 
2575a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2576a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2577a9de9248SMarcel Holtmann 		break;
2578a9de9248SMarcel Holtmann 
2579a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2580a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2581a9de9248SMarcel Holtmann 		break;
2582a9de9248SMarcel Holtmann 
2583a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2584a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2585a9de9248SMarcel Holtmann 		break;
2586a9de9248SMarcel Holtmann 
2587a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2588a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2589a9de9248SMarcel Holtmann 		break;
2590a9de9248SMarcel Holtmann 
2591a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2592a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2593a9de9248SMarcel Holtmann 		break;
2594a9de9248SMarcel Holtmann 
2595a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2596a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2597a9de9248SMarcel Holtmann 		break;
2598a9de9248SMarcel Holtmann 
2599a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2600a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2601a9de9248SMarcel Holtmann 		break;
2602a9de9248SMarcel Holtmann 
2603a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2604a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2605a9de9248SMarcel Holtmann 		break;
2606a9de9248SMarcel Holtmann 
2607a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2608a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2609a9de9248SMarcel Holtmann 		break;
2610a9de9248SMarcel Holtmann 
2611a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2612a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2613a9de9248SMarcel Holtmann 		break;
2614a9de9248SMarcel Holtmann 
2615b4cb9fb2SMarcel Holtmann 	case HCI_OP_READ_NUM_SUPPORTED_IAC:
2616b4cb9fb2SMarcel Holtmann 		hci_cc_read_num_supported_iac(hdev, skb);
2617b4cb9fb2SMarcel Holtmann 		break;
2618b4cb9fb2SMarcel Holtmann 
2619333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2620333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2621333140b5SMarcel Holtmann 		break;
2622333140b5SMarcel Holtmann 
2623eac83dc6SMarcel Holtmann 	case HCI_OP_WRITE_SC_SUPPORT:
2624eac83dc6SMarcel Holtmann 		hci_cc_write_sc_support(hdev, skb);
2625eac83dc6SMarcel Holtmann 		break;
2626eac83dc6SMarcel Holtmann 
2627a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2628a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2629a9de9248SMarcel Holtmann 		break;
2630a9de9248SMarcel Holtmann 
2631a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2632a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2633a9de9248SMarcel Holtmann 		break;
2634a9de9248SMarcel Holtmann 
2635a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2636a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2637a9de9248SMarcel Holtmann 		break;
2638a9de9248SMarcel Holtmann 
2639971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2640971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2641971e3a4bSAndre Guedes 		break;
2642971e3a4bSAndre Guedes 
2643a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2644a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2645a9de9248SMarcel Holtmann 		break;
2646a9de9248SMarcel Holtmann 
2647a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2648a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2649a9de9248SMarcel Holtmann 		break;
2650a9de9248SMarcel Holtmann 
2651f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2652f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
2653f332ec66SJohan Hedberg 		break;
2654f332ec66SJohan Hedberg 
26554a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
26564a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
26574a3ee763SJohan Hedberg 		break;
26584a3ee763SJohan Hedberg 
2659f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
2660f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
2661f332ec66SJohan Hedberg 		break;
2662f332ec66SJohan Hedberg 
26634a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
26644a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
26654a3ee763SJohan Hedberg 		break;
26664a3ee763SJohan Hedberg 
2667350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2668350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2669350ee4cfSAndrei Emeltchenko 		break;
2670350ee4cfSAndrei Emeltchenko 
26711e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
26721e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
26731e89cffbSAndrei Emeltchenko 		break;
26741e89cffbSAndrei Emeltchenko 
2675928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2676928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2677928abaa7SAndrei Emeltchenko 		break;
2678928abaa7SAndrei Emeltchenko 
267933f35721SJohan Hedberg 	case HCI_OP_READ_CLOCK:
268033f35721SJohan Hedberg 		hci_cc_read_clock(hdev, skb);
268133f35721SJohan Hedberg 		break;
268233f35721SJohan Hedberg 
2683903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2684903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2685903e4541SAndrei Emeltchenko 		break;
2686903e4541SAndrei Emeltchenko 
2687d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2688d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2689d5859e22SJohan Hedberg 		break;
2690d5859e22SJohan Hedberg 
2691980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2692980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2693980e1a53SJohan Hedberg 		break;
2694980e1a53SJohan Hedberg 
2695980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2696980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2697980e1a53SJohan Hedberg 		break;
2698980e1a53SJohan Hedberg 
2699c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
27004d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_data(hdev, skb);
27014d2d2796SMarcel Holtmann 		break;
27024d2d2796SMarcel Holtmann 
27034d2d2796SMarcel Holtmann 	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
27044d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_ext_data(hdev, skb);
2705c35938b2SSzymon Janc 		break;
2706c35938b2SSzymon Janc 
27076ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
27086ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
27096ed58ec5SVille Tervo 		break;
27106ed58ec5SVille Tervo 
271160e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
271260e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
271360e77321SJohan Hedberg 		break;
271460e77321SJohan Hedberg 
27158fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
27168fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
27178fa19098SJohan Hedberg 		break;
27188fa19098SJohan Hedberg 
2719a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2720a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2721a5c29683SJohan Hedberg 		break;
2722a5c29683SJohan Hedberg 
2723a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2724a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2725a5c29683SJohan Hedberg 		break;
2726a5c29683SJohan Hedberg 
27271143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
27281143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
27291143d458SBrian Gix 		break;
27301143d458SBrian Gix 
27311143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
27321143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
273316cde993SSzymon Janc 		break;
273407f7fa5dSAndre Guedes 
27357a4cd51dSMarcel Holtmann 	case HCI_OP_LE_SET_RANDOM_ADDR:
27367a4cd51dSMarcel Holtmann 		hci_cc_le_set_random_addr(hdev, skb);
27377a4cd51dSMarcel Holtmann 		break;
27387a4cd51dSMarcel Holtmann 
2739c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2740c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2741c1d5dc4aSJohan Hedberg 		break;
2742c1d5dc4aSJohan Hedberg 
2743533553f8SMarcel Holtmann 	case HCI_OP_LE_SET_SCAN_PARAM:
2744533553f8SMarcel Holtmann 		hci_cc_le_set_scan_param(hdev, skb);
2745533553f8SMarcel Holtmann 		break;
2746533553f8SMarcel Holtmann 
2747eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2748eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2749eb9d91f5SAndre Guedes 		break;
2750eb9d91f5SAndre Guedes 
2751cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2752cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2753cf1d081fSJohan Hedberg 		break;
2754cf1d081fSJohan Hedberg 
27550f36b589SMarcel Holtmann 	case HCI_OP_LE_CLEAR_WHITE_LIST:
27560f36b589SMarcel Holtmann 		hci_cc_le_clear_white_list(hdev, skb);
27570f36b589SMarcel Holtmann 		break;
27580f36b589SMarcel Holtmann 
27590f36b589SMarcel Holtmann 	case HCI_OP_LE_ADD_TO_WHITE_LIST:
27600f36b589SMarcel Holtmann 		hci_cc_le_add_to_white_list(hdev, skb);
27610f36b589SMarcel Holtmann 		break;
27620f36b589SMarcel Holtmann 
27630f36b589SMarcel Holtmann 	case HCI_OP_LE_DEL_FROM_WHITE_LIST:
27640f36b589SMarcel Holtmann 		hci_cc_le_del_from_white_list(hdev, skb);
27650f36b589SMarcel Holtmann 		break;
27660f36b589SMarcel Holtmann 
27679b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
27689b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
27699b008c04SJohan Hedberg 		break;
27709b008c04SJohan Hedberg 
2771f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2772f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2773f9b49306SAndre Guedes 		break;
2774f9b49306SAndre Guedes 
277556ed2cb8SJohan Hedberg 	case HCI_OP_LE_SET_ADV_PARAM:
277656ed2cb8SJohan Hedberg 		hci_cc_set_adv_param(hdev, skb);
277756ed2cb8SJohan Hedberg 		break;
277856ed2cb8SJohan Hedberg 
277993c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
278093c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
278193c284eeSAndrei Emeltchenko 		break;
278293c284eeSAndrei Emeltchenko 
27835ae76a94SAndrzej Kaczmarek 	case HCI_OP_READ_RSSI:
27845ae76a94SAndrzej Kaczmarek 		hci_cc_read_rssi(hdev, skb);
27855ae76a94SAndrzej Kaczmarek 		break;
27865ae76a94SAndrzej Kaczmarek 
27875a134faeSAndrzej Kaczmarek 	case HCI_OP_READ_TX_POWER:
27885a134faeSAndrzej Kaczmarek 		hci_cc_read_tx_power(hdev, skb);
27895a134faeSAndrzej Kaczmarek 		break;
27905a134faeSAndrzej Kaczmarek 
2791a9de9248SMarcel Holtmann 	default:
27929f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2793a9de9248SMarcel Holtmann 		break;
2794a9de9248SMarcel Holtmann 	}
2795a9de9248SMarcel Holtmann 
2796ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
279765cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
27986bd32326SVille Tervo 
2799ad82cdd1SJohan Hedberg 	hci_req_cmd_complete(hdev, opcode, status);
28009238f36aSJohan Hedberg 
2801dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2802a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2803a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2804c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2805a9de9248SMarcel Holtmann 	}
2806a9de9248SMarcel Holtmann }
2807a9de9248SMarcel Holtmann 
28086039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2809a9de9248SMarcel Holtmann {
2810a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2811a9de9248SMarcel Holtmann 	__u16 opcode;
2812a9de9248SMarcel Holtmann 
2813a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2814a9de9248SMarcel Holtmann 
2815a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2816a9de9248SMarcel Holtmann 
2817a9de9248SMarcel Holtmann 	switch (opcode) {
2818a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2819a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2820a9de9248SMarcel Holtmann 		break;
2821a9de9248SMarcel Holtmann 
2822a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2823a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2824a9de9248SMarcel Holtmann 		break;
2825a9de9248SMarcel Holtmann 
2826a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2827a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2828a9de9248SMarcel Holtmann 		break;
2829a9de9248SMarcel Holtmann 
2830f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2831f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2832f8558555SMarcel Holtmann 		break;
2833f8558555SMarcel Holtmann 
2834f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2835f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2836f8558555SMarcel Holtmann 		break;
2837f8558555SMarcel Holtmann 
2838a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2839a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2840a9de9248SMarcel Holtmann 		break;
2841a9de9248SMarcel Holtmann 
2842769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2843769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2844769be974SMarcel Holtmann 		break;
2845769be974SMarcel Holtmann 
2846769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2847769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2848769be974SMarcel Holtmann 		break;
2849769be974SMarcel Holtmann 
2850a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2851a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2852a9de9248SMarcel Holtmann 		break;
2853a9de9248SMarcel Holtmann 
2854a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2855a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2856a9de9248SMarcel Holtmann 		break;
2857a9de9248SMarcel Holtmann 
2858a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2859a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2860a9de9248SMarcel Holtmann 		break;
2861a9de9248SMarcel Holtmann 
28628962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
286388c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
28648962ee74SJohan Hedberg 		break;
28658962ee74SJohan Hedberg 
2866a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2867a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2868a02226d6SAndrei Emeltchenko 		break;
2869a02226d6SAndrei Emeltchenko 
28700b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
28710b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
28720b26ab9dSAndrei Emeltchenko 		break;
28730b26ab9dSAndrei Emeltchenko 
2874cb1d68f7SJohan Hedberg 	case HCI_OP_LE_CREATE_CONN:
2875cb1d68f7SJohan Hedberg 		hci_cs_le_create_conn(hdev, ev->status);
2876cb1d68f7SJohan Hedberg 		break;
2877cb1d68f7SJohan Hedberg 
287881d0c8adSJohan Hedberg 	case HCI_OP_LE_START_ENC:
287981d0c8adSJohan Hedberg 		hci_cs_le_start_enc(hdev, ev->status);
288081d0c8adSJohan Hedberg 		break;
288181d0c8adSJohan Hedberg 
2882a9de9248SMarcel Holtmann 	default:
28839f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2884a9de9248SMarcel Holtmann 		break;
2885a9de9248SMarcel Holtmann 	}
2886a9de9248SMarcel Holtmann 
2887ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
288865cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
28896bd32326SVille Tervo 
289002350a72SJohan Hedberg 	if (ev->status ||
289102350a72SJohan Hedberg 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
289233720450SAndre Guedes 		hci_req_cmd_complete(hdev, opcode, ev->status);
28939238f36aSJohan Hedberg 
289410572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2895a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2896a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2897c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2898a9de9248SMarcel Holtmann 	}
2899a9de9248SMarcel Holtmann }
2900a9de9248SMarcel Holtmann 
29016039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2902a9de9248SMarcel Holtmann {
2903a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2904a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2905a9de9248SMarcel Holtmann 
29069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2907a9de9248SMarcel Holtmann 
2908a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2909a9de9248SMarcel Holtmann 
2910a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2911a9de9248SMarcel Holtmann 	if (conn) {
2912a9de9248SMarcel Holtmann 		if (!ev->status) {
2913a9de9248SMarcel Holtmann 			if (ev->role)
29144dae2798SJohan Hedberg 				clear_bit(HCI_CONN_MASTER, &conn->flags);
2915a9de9248SMarcel Holtmann 			else
29164dae2798SJohan Hedberg 				set_bit(HCI_CONN_MASTER, &conn->flags);
2917a9de9248SMarcel Holtmann 		}
2918a9de9248SMarcel Holtmann 
291951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2920a9de9248SMarcel Holtmann 
2921a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2922a9de9248SMarcel Holtmann 	}
2923a9de9248SMarcel Holtmann 
2924a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2925a9de9248SMarcel Holtmann }
2926a9de9248SMarcel Holtmann 
29276039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
29281da177e4SLinus Torvalds {
2929a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
29301da177e4SLinus Torvalds 	int i;
29311da177e4SLinus Torvalds 
293232ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
293332ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
293432ac5b9bSAndrei Emeltchenko 		return;
293532ac5b9bSAndrei Emeltchenko 	}
293632ac5b9bSAndrei Emeltchenko 
2937c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2938c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
29391da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
29401da177e4SLinus Torvalds 		return;
29411da177e4SLinus Torvalds 	}
29421da177e4SLinus Torvalds 
2943c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2944c5993de8SAndrei Emeltchenko 
2945613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2946613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
29471da177e4SLinus Torvalds 		struct hci_conn *conn;
29481da177e4SLinus Torvalds 		__u16  handle, count;
29491da177e4SLinus Torvalds 
2950613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2951613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
29521da177e4SLinus Torvalds 
29531da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2954f4280918SAndrei Emeltchenko 		if (!conn)
2955f4280918SAndrei Emeltchenko 			continue;
2956f4280918SAndrei Emeltchenko 
29571da177e4SLinus Torvalds 		conn->sent -= count;
29581da177e4SLinus Torvalds 
2959f4280918SAndrei Emeltchenko 		switch (conn->type) {
2960f4280918SAndrei Emeltchenko 		case ACL_LINK:
296170f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
296270f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
29631da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2964f4280918SAndrei Emeltchenko 			break;
2965f4280918SAndrei Emeltchenko 
2966f4280918SAndrei Emeltchenko 		case LE_LINK:
29676ed58ec5SVille Tervo 			if (hdev->le_pkts) {
29686ed58ec5SVille Tervo 				hdev->le_cnt += count;
29696ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
29706ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
29716ed58ec5SVille Tervo 			} else {
29726ed58ec5SVille Tervo 				hdev->acl_cnt += count;
29736ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
29746ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
29756ed58ec5SVille Tervo 			}
2976f4280918SAndrei Emeltchenko 			break;
2977f4280918SAndrei Emeltchenko 
2978f4280918SAndrei Emeltchenko 		case SCO_LINK:
297970f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
298070f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
29815b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2982f4280918SAndrei Emeltchenko 			break;
2983f4280918SAndrei Emeltchenko 
2984f4280918SAndrei Emeltchenko 		default:
2985f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2986f4280918SAndrei Emeltchenko 			break;
29871da177e4SLinus Torvalds 		}
29881da177e4SLinus Torvalds 	}
2989a9de9248SMarcel Holtmann 
29903eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
29911da177e4SLinus Torvalds }
29921da177e4SLinus Torvalds 
299376ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
299476ef7cf7SAndrei Emeltchenko 						 __u16 handle)
299576ef7cf7SAndrei Emeltchenko {
299676ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
299776ef7cf7SAndrei Emeltchenko 
299876ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
299976ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
300076ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
300176ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
300276ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
300376ef7cf7SAndrei Emeltchenko 		if (chan)
300476ef7cf7SAndrei Emeltchenko 			return chan->conn;
300576ef7cf7SAndrei Emeltchenko 		break;
300676ef7cf7SAndrei Emeltchenko 	default:
300776ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
300876ef7cf7SAndrei Emeltchenko 		break;
300976ef7cf7SAndrei Emeltchenko 	}
301076ef7cf7SAndrei Emeltchenko 
301176ef7cf7SAndrei Emeltchenko 	return NULL;
301276ef7cf7SAndrei Emeltchenko }
301376ef7cf7SAndrei Emeltchenko 
30146039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
301525e89e99SAndrei Emeltchenko {
301625e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
301725e89e99SAndrei Emeltchenko 	int i;
301825e89e99SAndrei Emeltchenko 
301925e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
302025e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
302125e89e99SAndrei Emeltchenko 		return;
302225e89e99SAndrei Emeltchenko 	}
302325e89e99SAndrei Emeltchenko 
302425e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
302525e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
302625e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
302725e89e99SAndrei Emeltchenko 		return;
302825e89e99SAndrei Emeltchenko 	}
302925e89e99SAndrei Emeltchenko 
303025e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
303125e89e99SAndrei Emeltchenko 	       ev->num_hndl);
303225e89e99SAndrei Emeltchenko 
303325e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
303425e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
303576ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
303625e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
303725e89e99SAndrei Emeltchenko 
303825e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
303925e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
304025e89e99SAndrei Emeltchenko 
304176ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
304225e89e99SAndrei Emeltchenko 		if (!conn)
304325e89e99SAndrei Emeltchenko 			continue;
304425e89e99SAndrei Emeltchenko 
304525e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
304625e89e99SAndrei Emeltchenko 
304725e89e99SAndrei Emeltchenko 		switch (conn->type) {
304825e89e99SAndrei Emeltchenko 		case ACL_LINK:
3049bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
305025e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
305125e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
305225e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
305325e89e99SAndrei Emeltchenko 			break;
305425e89e99SAndrei Emeltchenko 
305525e89e99SAndrei Emeltchenko 		default:
305625e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
305725e89e99SAndrei Emeltchenko 			break;
305825e89e99SAndrei Emeltchenko 		}
305925e89e99SAndrei Emeltchenko 	}
306025e89e99SAndrei Emeltchenko 
306125e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
306225e89e99SAndrei Emeltchenko }
306325e89e99SAndrei Emeltchenko 
30646039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
30651da177e4SLinus Torvalds {
3066a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
306704837f64SMarcel Holtmann 	struct hci_conn *conn;
30681da177e4SLinus Torvalds 
30699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
30701da177e4SLinus Torvalds 
30711da177e4SLinus Torvalds 	hci_dev_lock(hdev);
30721da177e4SLinus Torvalds 
307304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
307404837f64SMarcel Holtmann 	if (conn) {
307504837f64SMarcel Holtmann 		conn->mode = ev->mode;
307604837f64SMarcel Holtmann 
30778fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
30788fc9ced3SGustavo Padovan 					&conn->flags)) {
307904837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
308058a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
308104837f64SMarcel Holtmann 			else
308258a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
308304837f64SMarcel Holtmann 		}
3084e73439d8SMarcel Holtmann 
308551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
3086e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
308704837f64SMarcel Holtmann 	}
308804837f64SMarcel Holtmann 
308904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
309004837f64SMarcel Holtmann }
309104837f64SMarcel Holtmann 
30926039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
30931da177e4SLinus Torvalds {
3094052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
3095052b30b0SMarcel Holtmann 	struct hci_conn *conn;
3096052b30b0SMarcel Holtmann 
3097a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3098052b30b0SMarcel Holtmann 
3099052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3100052b30b0SMarcel Holtmann 
3101052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3102b6f98044SWaldemar Rymarkiewicz 	if (!conn)
3103b6f98044SWaldemar Rymarkiewicz 		goto unlock;
3104b6f98044SWaldemar Rymarkiewicz 
3105b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
3106052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3107052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
310876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3109052b30b0SMarcel Holtmann 	}
3110052b30b0SMarcel Holtmann 
3111a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
311203b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
311303b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
3114a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
3115a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
3116a770bb5aSWaldemar Rymarkiewicz 
3117a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
3118a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
3119a770bb5aSWaldemar Rymarkiewicz 		else
3120a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
3121a770bb5aSWaldemar Rymarkiewicz 
3122744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
3123a770bb5aSWaldemar Rymarkiewicz 	}
3124980e1a53SJohan Hedberg 
3125b6f98044SWaldemar Rymarkiewicz unlock:
3126052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
31271da177e4SLinus Torvalds }
31281da177e4SLinus Torvalds 
31296039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
31301da177e4SLinus Torvalds {
313155ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
313255ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
313355ed8ca1SJohan Hedberg 	struct hci_conn *conn;
313455ed8ca1SJohan Hedberg 	struct link_key *key;
313555ed8ca1SJohan Hedberg 
3136a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
313755ed8ca1SJohan Hedberg 
3138034cbea0SAndrei Emeltchenko 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
313955ed8ca1SJohan Hedberg 		return;
314055ed8ca1SJohan Hedberg 
314155ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
314255ed8ca1SJohan Hedberg 
314355ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
314455ed8ca1SJohan Hedberg 	if (!key) {
31456ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
31466ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
314755ed8ca1SJohan Hedberg 		goto not_found;
314855ed8ca1SJohan Hedberg 	}
314955ed8ca1SJohan Hedberg 
31506ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
31516ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
315255ed8ca1SJohan Hedberg 
315355ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
315460b83f57SWaldemar Rymarkiewicz 	if (conn) {
315566138ce8SMarcel Holtmann 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
315666138ce8SMarcel Holtmann 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
3157807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
315855ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
315955ed8ca1SJohan Hedberg 			goto not_found;
316055ed8ca1SJohan Hedberg 		}
316155ed8ca1SJohan Hedberg 
316260b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
3163f3fb0b58SJohan Hedberg 		    (conn->pending_sec_level == BT_SECURITY_HIGH ||
3164f3fb0b58SJohan Hedberg 		     conn->pending_sec_level == BT_SECURITY_FIPS)) {
31658fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
31668fc9ced3SGustavo Padovan 			       hdev->name);
316760b83f57SWaldemar Rymarkiewicz 			goto not_found;
316860b83f57SWaldemar Rymarkiewicz 		}
316960b83f57SWaldemar Rymarkiewicz 
317060b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
317160b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
317260b83f57SWaldemar Rymarkiewicz 	}
317360b83f57SWaldemar Rymarkiewicz 
317455ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
31759b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
317655ed8ca1SJohan Hedberg 
317755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
317855ed8ca1SJohan Hedberg 
317955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
318055ed8ca1SJohan Hedberg 
318155ed8ca1SJohan Hedberg 	return;
318255ed8ca1SJohan Hedberg 
318355ed8ca1SJohan Hedberg not_found:
318455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
318555ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
31861da177e4SLinus Torvalds }
31871da177e4SLinus Torvalds 
31886039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
31891da177e4SLinus Torvalds {
3190052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
3191052b30b0SMarcel Holtmann 	struct hci_conn *conn;
31927652ff6aSJohan Hedberg 	struct link_key *key;
31937652ff6aSJohan Hedberg 	bool persistent;
319455ed8ca1SJohan Hedberg 	u8 pin_len = 0;
3195052b30b0SMarcel Holtmann 
3196a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3197052b30b0SMarcel Holtmann 
3198052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3199052b30b0SMarcel Holtmann 
3200052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3201052b30b0SMarcel Holtmann 	if (conn) {
3202052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3203052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3204980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
320513d39315SWaldemar Rymarkiewicz 
320613d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
320713d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
320813d39315SWaldemar Rymarkiewicz 
320976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3210052b30b0SMarcel Holtmann 	}
3211052b30b0SMarcel Holtmann 
32127652ff6aSJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
32137652ff6aSJohan Hedberg 		goto unlock;
321455ed8ca1SJohan Hedberg 
32157652ff6aSJohan Hedberg 	key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key,
32167652ff6aSJohan Hedberg 			        ev->key_type, pin_len, &persistent);
32177652ff6aSJohan Hedberg 	if (!key)
32187652ff6aSJohan Hedberg 		goto unlock;
32197652ff6aSJohan Hedberg 
32207652ff6aSJohan Hedberg 	mgmt_new_link_key(hdev, key, persistent);
32217652ff6aSJohan Hedberg 
32226d5650c4SJohan Hedberg 	/* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
32236d5650c4SJohan Hedberg 	 * is set. If it's not set simply remove the key from the kernel
32246d5650c4SJohan Hedberg 	 * list (we've still notified user space about it but with
32256d5650c4SJohan Hedberg 	 * store_hint being 0).
32266d5650c4SJohan Hedberg 	 */
32276d5650c4SJohan Hedberg 	if (key->type == HCI_LK_DEBUG_COMBINATION &&
32286d5650c4SJohan Hedberg 	    !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) {
32296d5650c4SJohan Hedberg 		list_del(&key->list);
32306d5650c4SJohan Hedberg 		kfree(key);
32316d5650c4SJohan Hedberg 	} else if (conn) {
3232af6a9c32SJohan Hedberg 		if (persistent)
3233af6a9c32SJohan Hedberg 			clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
3234af6a9c32SJohan Hedberg 		else
3235af6a9c32SJohan Hedberg 			set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
32366d5650c4SJohan Hedberg 	}
32377652ff6aSJohan Hedberg 
32387652ff6aSJohan Hedberg unlock:
3239052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
32401da177e4SLinus Torvalds }
32411da177e4SLinus Torvalds 
32426039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
324304837f64SMarcel Holtmann {
3244a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
324504837f64SMarcel Holtmann 	struct hci_conn *conn;
324604837f64SMarcel Holtmann 
32479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
324804837f64SMarcel Holtmann 
324904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
325004837f64SMarcel Holtmann 
325104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
32521da177e4SLinus Torvalds 	if (conn && !ev->status) {
32531da177e4SLinus Torvalds 		struct inquiry_entry *ie;
32541da177e4SLinus Torvalds 
3255cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3256cc11b9c1SAndrei Emeltchenko 		if (ie) {
32571da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
32581da177e4SLinus Torvalds 			ie->timestamp = jiffies;
32591da177e4SLinus Torvalds 		}
32601da177e4SLinus Torvalds 	}
32611da177e4SLinus Torvalds 
32621da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
32631da177e4SLinus Torvalds }
32641da177e4SLinus Torvalds 
32656039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3266a8746417SMarcel Holtmann {
3267a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3268a8746417SMarcel Holtmann 	struct hci_conn *conn;
3269a8746417SMarcel Holtmann 
32709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3271a8746417SMarcel Holtmann 
3272a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
3273a8746417SMarcel Holtmann 
3274a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3275a8746417SMarcel Holtmann 	if (conn && !ev->status)
3276a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3277a8746417SMarcel Holtmann 
3278a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
3279a8746417SMarcel Holtmann }
3280a8746417SMarcel Holtmann 
32816039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
328285a1e930SMarcel Holtmann {
3283a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
328485a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
328585a1e930SMarcel Holtmann 
328685a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
328785a1e930SMarcel Holtmann 
328885a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
328985a1e930SMarcel Holtmann 
3290cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3291cc11b9c1SAndrei Emeltchenko 	if (ie) {
329285a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
329385a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
329485a1e930SMarcel Holtmann 	}
329585a1e930SMarcel Holtmann 
329685a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
329785a1e930SMarcel Holtmann }
329885a1e930SMarcel Holtmann 
32996039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3300807deac2SGustavo Padovan 					     struct sk_buff *skb)
3301a9de9248SMarcel Holtmann {
3302a9de9248SMarcel Holtmann 	struct inquiry_data data;
3303a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
3304a9de9248SMarcel Holtmann 
3305a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3306a9de9248SMarcel Holtmann 
3307a9de9248SMarcel Holtmann 	if (!num_rsp)
3308a9de9248SMarcel Holtmann 		return;
3309a9de9248SMarcel Holtmann 
33101519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
33111519cc17SAndre Guedes 		return;
33121519cc17SAndre Guedes 
3313a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3314a9de9248SMarcel Holtmann 
3315a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3316138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3317138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3318a9de9248SMarcel Holtmann 
3319e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3320af58925cSMarcel Holtmann 			u32 flags;
3321af58925cSMarcel Holtmann 
3322a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3323a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3324a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3325a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3326a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3327a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3328a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
332941a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
33303175405bSJohan Hedberg 
3331af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
3332af58925cSMarcel Holtmann 
333348264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3334e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3335af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
3336a9de9248SMarcel Holtmann 		}
3337a9de9248SMarcel Holtmann 	} else {
3338a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3339a9de9248SMarcel Holtmann 
3340e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3341af58925cSMarcel Holtmann 			u32 flags;
3342af58925cSMarcel Holtmann 
3343a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3344a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3345a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3346a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3347a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3348a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3349a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
335041a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
3351af58925cSMarcel Holtmann 
3352af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
3353af58925cSMarcel Holtmann 
335448264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3355e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3356af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
3357a9de9248SMarcel Holtmann 		}
3358a9de9248SMarcel Holtmann 	}
3359a9de9248SMarcel Holtmann 
3360a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3361a9de9248SMarcel Holtmann }
3362a9de9248SMarcel Holtmann 
33636039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3364807deac2SGustavo Padovan 					struct sk_buff *skb)
3365a9de9248SMarcel Holtmann {
336641a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
336741a96212SMarcel Holtmann 	struct hci_conn *conn;
336841a96212SMarcel Holtmann 
3369a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
337041a96212SMarcel Holtmann 
337141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
337241a96212SMarcel Holtmann 
337341a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3374ccd556feSJohan Hedberg 	if (!conn)
3375ccd556feSJohan Hedberg 		goto unlock;
3376ccd556feSJohan Hedberg 
3377cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
3378cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
3379cad718edSJohan Hedberg 
3380769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
338141a96212SMarcel Holtmann 		struct inquiry_entry *ie;
338241a96212SMarcel Holtmann 
3383cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3384cc11b9c1SAndrei Emeltchenko 		if (ie)
338502b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
338641a96212SMarcel Holtmann 
3387bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
338858a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
3389bbb0eadaSJaganath Kanakkassery 		} else {
3390bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
3391bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
3392bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
3393bbb0eadaSJaganath Kanakkassery 			 * this.
3394bbb0eadaSJaganath Kanakkassery 			 *
3395bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
3396bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
3397bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
3398bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
3399bbb0eadaSJaganath Kanakkassery 		}
3400eb9a8f3fSMarcel Holtmann 
3401eb9a8f3fSMarcel Holtmann 		if (ev->features[0] & LMP_HOST_SC)
3402eb9a8f3fSMarcel Holtmann 			set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
340341a96212SMarcel Holtmann 	}
340441a96212SMarcel Holtmann 
3405ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3406ccd556feSJohan Hedberg 		goto unlock;
3407ccd556feSJohan Hedberg 
3408671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3409127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3410127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3411127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3412127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3413127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3414b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3415b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
341608c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
3417b644ba33SJohan Hedberg 				      conn->dev_class);
3418392599b9SJohan Hedberg 
3419127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3420769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3421769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
342276a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3423769be974SMarcel Holtmann 	}
3424769be974SMarcel Holtmann 
3425ccd556feSJohan Hedberg unlock:
342641a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3427a9de9248SMarcel Holtmann }
3428a9de9248SMarcel Holtmann 
34296039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3430807deac2SGustavo Padovan 				       struct sk_buff *skb)
3431a9de9248SMarcel Holtmann {
3432b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3433b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3434b6a0dc82SMarcel Holtmann 
34359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3436b6a0dc82SMarcel Holtmann 
3437b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3438b6a0dc82SMarcel Holtmann 
3439b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
34409dc0a3afSMarcel Holtmann 	if (!conn) {
34419dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
34429dc0a3afSMarcel Holtmann 			goto unlock;
34439dc0a3afSMarcel Holtmann 
34449dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3445b6a0dc82SMarcel Holtmann 		if (!conn)
3446b6a0dc82SMarcel Holtmann 			goto unlock;
3447b6a0dc82SMarcel Holtmann 
34489dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
34499dc0a3afSMarcel Holtmann 	}
34509dc0a3afSMarcel Holtmann 
3451732547f9SMarcel Holtmann 	switch (ev->status) {
3452732547f9SMarcel Holtmann 	case 0x00:
3453732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3454732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3455732547f9SMarcel Holtmann 
3456732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3457732547f9SMarcel Holtmann 		break;
3458732547f9SMarcel Holtmann 
345981218d20SNick Pelly 	case 0x10:	/* Connection Accept Timeout */
34601a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
3461705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3462732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
34631038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3464732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
346527539bc4SAndrew Earl 	case 0x20:	/* Unsupported LMP Parameter value */
34662dea632fSFrédéric Dalleau 		if (conn->out) {
3467efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3468efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
34692dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
3470efc7688bSMarcel Holtmann 				goto unlock;
3471efc7688bSMarcel Holtmann 		}
3472732547f9SMarcel Holtmann 		/* fall through */
3473efc7688bSMarcel Holtmann 
3474732547f9SMarcel Holtmann 	default:
3475b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3476732547f9SMarcel Holtmann 		break;
3477732547f9SMarcel Holtmann 	}
3478b6a0dc82SMarcel Holtmann 
3479b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3480b6a0dc82SMarcel Holtmann 	if (ev->status)
3481b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3482b6a0dc82SMarcel Holtmann 
3483b6a0dc82SMarcel Holtmann unlock:
3484b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3485a9de9248SMarcel Holtmann }
3486a9de9248SMarcel Holtmann 
3487efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len)
3488efdcf8e3SMarcel Holtmann {
3489efdcf8e3SMarcel Holtmann 	size_t parsed = 0;
3490efdcf8e3SMarcel Holtmann 
3491efdcf8e3SMarcel Holtmann 	while (parsed < eir_len) {
3492efdcf8e3SMarcel Holtmann 		u8 field_len = eir[0];
3493efdcf8e3SMarcel Holtmann 
3494efdcf8e3SMarcel Holtmann 		if (field_len == 0)
3495efdcf8e3SMarcel Holtmann 			return parsed;
3496efdcf8e3SMarcel Holtmann 
3497efdcf8e3SMarcel Holtmann 		parsed += field_len + 1;
3498efdcf8e3SMarcel Holtmann 		eir += field_len + 1;
3499efdcf8e3SMarcel Holtmann 	}
3500efdcf8e3SMarcel Holtmann 
3501efdcf8e3SMarcel Holtmann 	return eir_len;
3502efdcf8e3SMarcel Holtmann }
3503efdcf8e3SMarcel Holtmann 
35046039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3505807deac2SGustavo Padovan 					    struct sk_buff *skb)
3506a9de9248SMarcel Holtmann {
3507a9de9248SMarcel Holtmann 	struct inquiry_data data;
3508a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3509a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
35109d939d94SVishal Agarwal 	size_t eir_len;
3511a9de9248SMarcel Holtmann 
3512a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3513a9de9248SMarcel Holtmann 
3514a9de9248SMarcel Holtmann 	if (!num_rsp)
3515a9de9248SMarcel Holtmann 		return;
3516a9de9248SMarcel Holtmann 
35171519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
35181519cc17SAndre Guedes 		return;
35191519cc17SAndre Guedes 
3520a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3521a9de9248SMarcel Holtmann 
3522e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3523af58925cSMarcel Holtmann 		u32 flags;
3524af58925cSMarcel Holtmann 		bool name_known;
3525561aafbcSJohan Hedberg 
3526a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3527a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3528a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3529a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3530a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3531a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3532a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
353341a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3534561aafbcSJohan Hedberg 
3535a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
35364ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
35374ddb1930SJohan Hedberg 						       sizeof(info->data),
35384ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3539561aafbcSJohan Hedberg 		else
3540561aafbcSJohan Hedberg 			name_known = true;
3541561aafbcSJohan Hedberg 
3542af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, name_known);
3543af58925cSMarcel Holtmann 
35449d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
3545af58925cSMarcel Holtmann 
354648264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3547af58925cSMarcel Holtmann 				  info->dev_class, info->rssi,
3548af58925cSMarcel Holtmann 				  flags, info->data, eir_len, NULL, 0);
3549a9de9248SMarcel Holtmann 	}
3550a9de9248SMarcel Holtmann 
3551a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3552a9de9248SMarcel Holtmann }
3553a9de9248SMarcel Holtmann 
35541c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
35551c2e0041SJohan Hedberg 					 struct sk_buff *skb)
35561c2e0041SJohan Hedberg {
35571c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
35581c2e0041SJohan Hedberg 	struct hci_conn *conn;
35591c2e0041SJohan Hedberg 
35609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
35611c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
35621c2e0041SJohan Hedberg 
35631c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
35641c2e0041SJohan Hedberg 
35651c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
35661c2e0041SJohan Hedberg 	if (!conn)
35671c2e0041SJohan Hedberg 		goto unlock;
35681c2e0041SJohan Hedberg 
35699eb1fbfaSJohan Hedberg 	/* For BR/EDR the necessary steps are taken through the
35709eb1fbfaSJohan Hedberg 	 * auth_complete event.
35719eb1fbfaSJohan Hedberg 	 */
35729eb1fbfaSJohan Hedberg 	if (conn->type != LE_LINK)
35739eb1fbfaSJohan Hedberg 		goto unlock;
35749eb1fbfaSJohan Hedberg 
35751c2e0041SJohan Hedberg 	if (!ev->status)
35761c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
35771c2e0041SJohan Hedberg 
35781c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
35791c2e0041SJohan Hedberg 
35801c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3581bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
358276a68ba0SDavid Herrmann 		hci_conn_drop(conn);
35831c2e0041SJohan Hedberg 		goto unlock;
35841c2e0041SJohan Hedberg 	}
35851c2e0041SJohan Hedberg 
35861c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
35871c2e0041SJohan Hedberg 		if (!ev->status)
35881c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
35891c2e0041SJohan Hedberg 
35901c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
359176a68ba0SDavid Herrmann 		hci_conn_drop(conn);
35921c2e0041SJohan Hedberg 	} else {
35931c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
35941c2e0041SJohan Hedberg 
35951c2e0041SJohan Hedberg 		hci_conn_hold(conn);
35961c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
359776a68ba0SDavid Herrmann 		hci_conn_drop(conn);
35981c2e0041SJohan Hedberg 	}
35991c2e0041SJohan Hedberg 
36001c2e0041SJohan Hedberg unlock:
36011c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
36021c2e0041SJohan Hedberg }
36031c2e0041SJohan Hedberg 
36046039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
360517fa4b9dSJohan Hedberg {
360617fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
3607acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
3608acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
360958797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
361017fa4b9dSJohan Hedberg 
3611b7f94c88SMikel Astiz 	/* If both remote and local have enough IO capabilities, require
3612b7f94c88SMikel Astiz 	 * MITM protection
3613b7f94c88SMikel Astiz 	 */
3614b7f94c88SMikel Astiz 	if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT &&
3615b7f94c88SMikel Astiz 	    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT)
3616b7f94c88SMikel Astiz 		return conn->remote_auth | 0x01;
3617b7f94c88SMikel Astiz 
36187e74170aSTimo Mueller 	/* No MITM protection possible so ignore remote requirement */
36197e74170aSTimo Mueller 	return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01);
362017fa4b9dSJohan Hedberg }
362117fa4b9dSJohan Hedberg 
36226039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
36230493684eSMarcel Holtmann {
36240493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
36250493684eSMarcel Holtmann 	struct hci_conn *conn;
36260493684eSMarcel Holtmann 
36270493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
36280493684eSMarcel Holtmann 
36290493684eSMarcel Holtmann 	hci_dev_lock(hdev);
36300493684eSMarcel Holtmann 
36310493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
363203b555e1SJohan Hedberg 	if (!conn)
363303b555e1SJohan Hedberg 		goto unlock;
363403b555e1SJohan Hedberg 
36350493684eSMarcel Holtmann 	hci_conn_hold(conn);
36360493684eSMarcel Holtmann 
3637a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
363803b555e1SJohan Hedberg 		goto unlock;
363903b555e1SJohan Hedberg 
3640a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
364103b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
364217fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
364317fa4b9dSJohan Hedberg 
364417fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
36457a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
36467a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
36477a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
3648a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
3649b7f94c88SMikel Astiz 
3650b7f94c88SMikel Astiz 		/* If we are initiators, there is no remote information yet */
3651b7f94c88SMikel Astiz 		if (conn->remote_auth == 0xff) {
3652b7f94c88SMikel Astiz 			cp.authentication = conn->auth_type;
36536fd6b915SMikel Astiz 
3654b16c6604SMikel Astiz 			/* Request MITM protection if our IO caps allow it
36554ad51a75SJohan Hedberg 			 * except for the no-bonding case.
36564ad51a75SJohan Hedberg 			 * conn->auth_type is not updated here since
36574ad51a75SJohan Hedberg 			 * that might cause the user confirmation to be
36584ad51a75SJohan Hedberg 			 * rejected in case the remote doesn't have the
36594ad51a75SJohan Hedberg 			 * IO capabilities for MITM.
3660b16c6604SMikel Astiz 			 */
36616fd6b915SMikel Astiz 			if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
3662b16c6604SMikel Astiz 			    cp.authentication != HCI_AT_NO_BONDING)
36636fd6b915SMikel Astiz 				cp.authentication |= 0x01;
3664b7f94c88SMikel Astiz 		} else {
36657cbc9bd9SJohan Hedberg 			conn->auth_type = hci_get_auth_req(conn);
36667cbc9bd9SJohan Hedberg 			cp.authentication = conn->auth_type;
3667b7f94c88SMikel Astiz 		}
366817fa4b9dSJohan Hedberg 
36698fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
36708fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3671ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3672ce85ee13SSzymon Janc 		else
3673ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3674ce85ee13SSzymon Janc 
367517fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
367617fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
367703b555e1SJohan Hedberg 	} else {
367803b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
367903b555e1SJohan Hedberg 
368003b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
36819f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
368203b555e1SJohan Hedberg 
368303b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
368403b555e1SJohan Hedberg 			     sizeof(cp), &cp);
368503b555e1SJohan Hedberg 	}
368603b555e1SJohan Hedberg 
368703b555e1SJohan Hedberg unlock:
368803b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
368903b555e1SJohan Hedberg }
369003b555e1SJohan Hedberg 
36916039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
369203b555e1SJohan Hedberg {
369303b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
369403b555e1SJohan Hedberg 	struct hci_conn *conn;
369503b555e1SJohan Hedberg 
369603b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
369703b555e1SJohan Hedberg 
369803b555e1SJohan Hedberg 	hci_dev_lock(hdev);
369903b555e1SJohan Hedberg 
370003b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
370103b555e1SJohan Hedberg 	if (!conn)
370203b555e1SJohan Hedberg 		goto unlock;
370303b555e1SJohan Hedberg 
370403b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
370503b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
370658a681efSJohan Hedberg 	if (ev->oob_data)
370758a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
370803b555e1SJohan Hedberg 
370903b555e1SJohan Hedberg unlock:
37100493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
37110493684eSMarcel Holtmann }
37120493684eSMarcel Holtmann 
37136039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3714a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3715a5c29683SJohan Hedberg {
3716a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
371755bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
37187a828908SJohan Hedberg 	struct hci_conn *conn;
3719a5c29683SJohan Hedberg 
3720a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3721a5c29683SJohan Hedberg 
3722a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3723a5c29683SJohan Hedberg 
3724a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
37257a828908SJohan Hedberg 		goto unlock;
37267a828908SJohan Hedberg 
37277a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
37287a828908SJohan Hedberg 	if (!conn)
37297a828908SJohan Hedberg 		goto unlock;
37307a828908SJohan Hedberg 
37317a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
37327a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
37337a828908SJohan Hedberg 
37347a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
37356fd6b915SMikel Astiz 	 * (it has NoInputNoOutput) then reject the confirmation request
37366fd6b915SMikel Astiz 	 */
37376fd6b915SMikel Astiz 	if (loc_mitm && conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
37387a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
37397a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
37407a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
37417a828908SJohan Hedberg 		goto unlock;
37427a828908SJohan Hedberg 	}
37437a828908SJohan Hedberg 
37447a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
3745a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
3746a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
374755bc1a37SJohan Hedberg 
374855bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
374955bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
3750ba15a58bSJohan Hedberg 		 * confirm_hint set to 1). The exception is if neither
3751ba15a58bSJohan Hedberg 		 * side had MITM in which case we do auto-accept.
3752ba15a58bSJohan Hedberg 		 */
3753ba15a58bSJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
3754ba15a58bSJohan Hedberg 		    (loc_mitm || rem_mitm)) {
375555bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
375655bc1a37SJohan Hedberg 			confirm_hint = 1;
375755bc1a37SJohan Hedberg 			goto confirm;
375855bc1a37SJohan Hedberg 		}
375955bc1a37SJohan Hedberg 
37609f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
37619f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
37629f61656aSJohan Hedberg 
37639f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
37649f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
37657bc18d9dSJohan Hedberg 			queue_delayed_work(conn->hdev->workqueue,
37667bc18d9dSJohan Hedberg 					   &conn->auto_accept_work, delay);
37679f61656aSJohan Hedberg 			goto unlock;
37689f61656aSJohan Hedberg 		}
37699f61656aSJohan Hedberg 
37707a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
37717a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
37727a828908SJohan Hedberg 		goto unlock;
37737a828908SJohan Hedberg 	}
37747a828908SJohan Hedberg 
377555bc1a37SJohan Hedberg confirm:
377639adbffeSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0,
377739adbffeSJohan Hedberg 				  le32_to_cpu(ev->passkey), confirm_hint);
3778a5c29683SJohan Hedberg 
37797a828908SJohan Hedberg unlock:
3780a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3781a5c29683SJohan Hedberg }
3782a5c29683SJohan Hedberg 
37836039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
37841143d458SBrian Gix 					 struct sk_buff *skb)
37851143d458SBrian Gix {
37861143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
37871143d458SBrian Gix 
37881143d458SBrian Gix 	BT_DBG("%s", hdev->name);
37891143d458SBrian Gix 
3790a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3791272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
37921143d458SBrian Gix }
37931143d458SBrian Gix 
379492a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
379592a25256SJohan Hedberg 					struct sk_buff *skb)
379692a25256SJohan Hedberg {
379792a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
379892a25256SJohan Hedberg 	struct hci_conn *conn;
379992a25256SJohan Hedberg 
380092a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
380192a25256SJohan Hedberg 
380292a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
380392a25256SJohan Hedberg 	if (!conn)
380492a25256SJohan Hedberg 		return;
380592a25256SJohan Hedberg 
380692a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
380792a25256SJohan Hedberg 	conn->passkey_entered = 0;
380892a25256SJohan Hedberg 
380992a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
381092a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
381192a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
381292a25256SJohan Hedberg 					 conn->passkey_entered);
381392a25256SJohan Hedberg }
381492a25256SJohan Hedberg 
381592a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
381692a25256SJohan Hedberg {
381792a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
381892a25256SJohan Hedberg 	struct hci_conn *conn;
381992a25256SJohan Hedberg 
382092a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
382192a25256SJohan Hedberg 
382292a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
382392a25256SJohan Hedberg 	if (!conn)
382492a25256SJohan Hedberg 		return;
382592a25256SJohan Hedberg 
382692a25256SJohan Hedberg 	switch (ev->type) {
382792a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
382892a25256SJohan Hedberg 		conn->passkey_entered = 0;
382992a25256SJohan Hedberg 		return;
383092a25256SJohan Hedberg 
383192a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
383292a25256SJohan Hedberg 		conn->passkey_entered++;
383392a25256SJohan Hedberg 		break;
383492a25256SJohan Hedberg 
383592a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
383692a25256SJohan Hedberg 		conn->passkey_entered--;
383792a25256SJohan Hedberg 		break;
383892a25256SJohan Hedberg 
383992a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
384092a25256SJohan Hedberg 		conn->passkey_entered = 0;
384192a25256SJohan Hedberg 		break;
384292a25256SJohan Hedberg 
384392a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
384492a25256SJohan Hedberg 		return;
384592a25256SJohan Hedberg 	}
384692a25256SJohan Hedberg 
384792a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
384892a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
384992a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
385092a25256SJohan Hedberg 					 conn->passkey_entered);
385192a25256SJohan Hedberg }
385292a25256SJohan Hedberg 
38536039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3854807deac2SGustavo Padovan 					 struct sk_buff *skb)
38550493684eSMarcel Holtmann {
38560493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
38570493684eSMarcel Holtmann 	struct hci_conn *conn;
38580493684eSMarcel Holtmann 
38590493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
38600493684eSMarcel Holtmann 
38610493684eSMarcel Holtmann 	hci_dev_lock(hdev);
38620493684eSMarcel Holtmann 
38630493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
38642a611692SJohan Hedberg 	if (!conn)
38652a611692SJohan Hedberg 		goto unlock;
38662a611692SJohan Hedberg 
38672a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
38682a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
38692a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
38702a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
38712a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3872fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3873bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3874bab73cb6SJohan Hedberg 				 ev->status);
38752a611692SJohan Hedberg 
387676a68ba0SDavid Herrmann 	hci_conn_drop(conn);
38770493684eSMarcel Holtmann 
38782a611692SJohan Hedberg unlock:
38790493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
38800493684eSMarcel Holtmann }
38810493684eSMarcel Holtmann 
38826039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3883807deac2SGustavo Padovan 					 struct sk_buff *skb)
388441a96212SMarcel Holtmann {
388541a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
388641a96212SMarcel Holtmann 	struct inquiry_entry *ie;
3887cad718edSJohan Hedberg 	struct hci_conn *conn;
388841a96212SMarcel Holtmann 
388941a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
389041a96212SMarcel Holtmann 
389141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
389241a96212SMarcel Holtmann 
3893cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3894cad718edSJohan Hedberg 	if (conn)
3895cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
3896cad718edSJohan Hedberg 
3897cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3898cc11b9c1SAndrei Emeltchenko 	if (ie)
389902b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
390041a96212SMarcel Holtmann 
390141a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
390241a96212SMarcel Holtmann }
390341a96212SMarcel Holtmann 
39046039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
39052763eda6SSzymon Janc 					    struct sk_buff *skb)
39062763eda6SSzymon Janc {
39072763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
39082763eda6SSzymon Janc 	struct oob_data *data;
39092763eda6SSzymon Janc 
39102763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
39112763eda6SSzymon Janc 
39122763eda6SSzymon Janc 	hci_dev_lock(hdev);
39132763eda6SSzymon Janc 
3914a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3915e1ba1f15SSzymon Janc 		goto unlock;
3916e1ba1f15SSzymon Janc 
39172763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
39182763eda6SSzymon Janc 	if (data) {
3919519ca9d0SMarcel Holtmann 		if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
3920519ca9d0SMarcel Holtmann 			struct hci_cp_remote_oob_ext_data_reply cp;
3921519ca9d0SMarcel Holtmann 
3922519ca9d0SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
3923519ca9d0SMarcel Holtmann 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
3924519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer192, data->randomizer192,
3925519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer192));
3926519ca9d0SMarcel Holtmann 			memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
3927519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer256, data->randomizer256,
3928519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer256));
3929519ca9d0SMarcel Holtmann 
3930519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
3931519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3932519ca9d0SMarcel Holtmann 		} else {
39332763eda6SSzymon Janc 			struct hci_cp_remote_oob_data_reply cp;
39342763eda6SSzymon Janc 
39352763eda6SSzymon Janc 			bacpy(&cp.bdaddr, &ev->bdaddr);
3936519ca9d0SMarcel Holtmann 			memcpy(cp.hash, data->hash192, sizeof(cp.hash));
3937519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer, data->randomizer192,
3938519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer));
39392763eda6SSzymon Janc 
3940519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
3941519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3942519ca9d0SMarcel Holtmann 		}
39432763eda6SSzymon Janc 	} else {
39442763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
39452763eda6SSzymon Janc 
39462763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
3947519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
3948519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
39492763eda6SSzymon Janc 	}
39502763eda6SSzymon Janc 
3951e1ba1f15SSzymon Janc unlock:
39522763eda6SSzymon Janc 	hci_dev_unlock(hdev);
39532763eda6SSzymon Janc }
39542763eda6SSzymon Janc 
3955d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3956d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3957d5e91192SAndrei Emeltchenko {
3958d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3959d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3960d5e91192SAndrei Emeltchenko 
3961d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3962d5e91192SAndrei Emeltchenko 	       ev->status);
3963d5e91192SAndrei Emeltchenko 
3964d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3965d5e91192SAndrei Emeltchenko 
3966d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3967d5e91192SAndrei Emeltchenko 	if (!hcon) {
3968d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3969d5e91192SAndrei Emeltchenko 		return;
3970d5e91192SAndrei Emeltchenko 	}
3971d5e91192SAndrei Emeltchenko 
3972d5e91192SAndrei Emeltchenko 	if (ev->status) {
3973d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3974d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3975d5e91192SAndrei Emeltchenko 		return;
3976d5e91192SAndrei Emeltchenko 	}
3977d5e91192SAndrei Emeltchenko 
3978d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3979d5e91192SAndrei Emeltchenko 
3980d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3981d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3982d5e91192SAndrei Emeltchenko 
3983d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3984d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
398576a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
3986d5e91192SAndrei Emeltchenko 
3987d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3988d5e91192SAndrei Emeltchenko 
3989cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
3990cf70ff22SAndrei Emeltchenko 
3991d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3992d5e91192SAndrei Emeltchenko }
3993d5e91192SAndrei Emeltchenko 
399427695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
399527695fb4SAndrei Emeltchenko {
399627695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
399727695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
399827695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
399927695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
400027695fb4SAndrei Emeltchenko 
400127695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
400227695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
400327695fb4SAndrei Emeltchenko 	       ev->status);
400427695fb4SAndrei Emeltchenko 
400527695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
400627695fb4SAndrei Emeltchenko 	if (!hcon)
400727695fb4SAndrei Emeltchenko 		return;
400827695fb4SAndrei Emeltchenko 
400927695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
401027695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
401127695fb4SAndrei Emeltchenko 	if (!hchan)
401227695fb4SAndrei Emeltchenko 		return;
401327695fb4SAndrei Emeltchenko 
401427695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
401527695fb4SAndrei Emeltchenko 
401627695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
401727695fb4SAndrei Emeltchenko 
401827695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
401927695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
402027695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
402127695fb4SAndrei Emeltchenko 
402227695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
402327695fb4SAndrei Emeltchenko 
402427695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
402527695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
402627695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
402727695fb4SAndrei Emeltchenko 
402827695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
402927695fb4SAndrei Emeltchenko 	}
403027695fb4SAndrei Emeltchenko }
403127695fb4SAndrei Emeltchenko 
4032606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
4033606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
4034606e2a10SAndrei Emeltchenko {
4035606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
4036606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
4037606e2a10SAndrei Emeltchenko 
4038606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
4039606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
4040606e2a10SAndrei Emeltchenko 
4041606e2a10SAndrei Emeltchenko 	if (ev->status)
4042606e2a10SAndrei Emeltchenko 		return;
4043606e2a10SAndrei Emeltchenko 
4044606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
4045606e2a10SAndrei Emeltchenko 
4046606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
4047606e2a10SAndrei Emeltchenko 	if (!hchan)
4048606e2a10SAndrei Emeltchenko 		goto unlock;
4049606e2a10SAndrei Emeltchenko 
4050606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
4051606e2a10SAndrei Emeltchenko 
4052606e2a10SAndrei Emeltchenko unlock:
4053606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
4054606e2a10SAndrei Emeltchenko }
4055606e2a10SAndrei Emeltchenko 
40569eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
40579eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
40589eef6b3aSAndrei Emeltchenko {
40599eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
40609eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
40619eef6b3aSAndrei Emeltchenko 
40629eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
40639eef6b3aSAndrei Emeltchenko 
40649eef6b3aSAndrei Emeltchenko 	if (ev->status)
40659eef6b3aSAndrei Emeltchenko 		return;
40669eef6b3aSAndrei Emeltchenko 
40679eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
40689eef6b3aSAndrei Emeltchenko 
40699eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
40709eef6b3aSAndrei Emeltchenko 	if (hcon) {
40719eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
40729eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
40739eef6b3aSAndrei Emeltchenko 	}
40749eef6b3aSAndrei Emeltchenko 
40759eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
40769eef6b3aSAndrei Emeltchenko }
40779eef6b3aSAndrei Emeltchenko 
40786039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
4079fcd89c09SVille Tervo {
4080fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
4081912b42efSJohan Hedberg 	struct hci_conn_params *params;
4082fcd89c09SVille Tervo 	struct hci_conn *conn;
408368d6f6deSJohan Hedberg 	struct smp_irk *irk;
4084837d502eSJohan Hedberg 	u8 addr_type;
4085fcd89c09SVille Tervo 
40869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
4087fcd89c09SVille Tervo 
4088fcd89c09SVille Tervo 	hci_dev_lock(hdev);
4089fcd89c09SVille Tervo 
40904f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
4091b62f328bSVille Tervo 	if (!conn) {
4092b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
4093b62f328bSVille Tervo 		if (!conn) {
4094b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
4095230fd16aSAndre Guedes 			goto unlock;
4096b62f328bSVille Tervo 		}
409729b7988aSAndre Guedes 
409829b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
4099b9b343d2SAndre Guedes 
4100b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
4101b9b343d2SAndre Guedes 			conn->out = true;
41024dae2798SJohan Hedberg 			set_bit(HCI_CONN_MASTER, &conn->flags);
4103b9b343d2SAndre Guedes 		}
4104cb1d68f7SJohan Hedberg 
4105cb1d68f7SJohan Hedberg 		/* If we didn't have a hci_conn object previously
4106cb1d68f7SJohan Hedberg 		 * but we're in master role this must be something
4107cb1d68f7SJohan Hedberg 		 * initiated using a white list. Since white list based
4108cb1d68f7SJohan Hedberg 		 * connections are not "first class citizens" we don't
4109cb1d68f7SJohan Hedberg 		 * have full tracking of them. Therefore, we go ahead
4110cb1d68f7SJohan Hedberg 		 * with a "best effort" approach of determining the
4111cb1d68f7SJohan Hedberg 		 * initiator address based on the HCI_PRIVACY flag.
4112cb1d68f7SJohan Hedberg 		 */
4113cb1d68f7SJohan Hedberg 		if (conn->out) {
4114cb1d68f7SJohan Hedberg 			conn->resp_addr_type = ev->bdaddr_type;
4115cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &ev->bdaddr);
4116cb1d68f7SJohan Hedberg 			if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) {
4117cb1d68f7SJohan Hedberg 				conn->init_addr_type = ADDR_LE_DEV_RANDOM;
4118cb1d68f7SJohan Hedberg 				bacpy(&conn->init_addr, &hdev->rpa);
4119cb1d68f7SJohan Hedberg 			} else {
4120cb1d68f7SJohan Hedberg 				hci_copy_identity_address(hdev,
4121cb1d68f7SJohan Hedberg 							  &conn->init_addr,
4122cb1d68f7SJohan Hedberg 							  &conn->init_addr_type);
4123cb1d68f7SJohan Hedberg 			}
412480c24ab8SJohan Hedberg 		}
4125cb1d68f7SJohan Hedberg 	} else {
412680c24ab8SJohan Hedberg 		cancel_delayed_work(&conn->le_conn_timeout);
412780c24ab8SJohan Hedberg 	}
412880c24ab8SJohan Hedberg 
412980c24ab8SJohan Hedberg 	if (!conn->out) {
4130cb1d68f7SJohan Hedberg 		/* Set the responder (our side) address type based on
4131cb1d68f7SJohan Hedberg 		 * the advertising address type.
4132cb1d68f7SJohan Hedberg 		 */
4133cb1d68f7SJohan Hedberg 		conn->resp_addr_type = hdev->adv_addr_type;
4134cb1d68f7SJohan Hedberg 		if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM)
4135cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &hdev->random_addr);
4136cb1d68f7SJohan Hedberg 		else
4137cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &hdev->bdaddr);
4138cb1d68f7SJohan Hedberg 
4139cb1d68f7SJohan Hedberg 		conn->init_addr_type = ev->bdaddr_type;
4140cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &ev->bdaddr);
4141a720d735SMarcel Holtmann 
4142a720d735SMarcel Holtmann 		/* For incoming connections, set the default minimum
4143a720d735SMarcel Holtmann 		 * and maximum connection interval. They will be used
4144a720d735SMarcel Holtmann 		 * to check if the parameters are in range and if not
4145a720d735SMarcel Holtmann 		 * trigger the connection update procedure.
4146a720d735SMarcel Holtmann 		 */
4147a720d735SMarcel Holtmann 		conn->le_conn_min_interval = hdev->le_conn_min_interval;
4148a720d735SMarcel Holtmann 		conn->le_conn_max_interval = hdev->le_conn_max_interval;
4149cb1d68f7SJohan Hedberg 	}
41507be2edbbSJohan Hedberg 
4151edb4b466SMarcel Holtmann 	/* Lookup the identity address from the stored connection
4152edb4b466SMarcel Holtmann 	 * address and address type.
4153edb4b466SMarcel Holtmann 	 *
4154edb4b466SMarcel Holtmann 	 * When establishing connections to an identity address, the
4155edb4b466SMarcel Holtmann 	 * connection procedure will store the resolvable random
4156edb4b466SMarcel Holtmann 	 * address first. Now if it can be converted back into the
4157edb4b466SMarcel Holtmann 	 * identity address, start using the identity address from
4158edb4b466SMarcel Holtmann 	 * now on.
4159edb4b466SMarcel Holtmann 	 */
4160edb4b466SMarcel Holtmann 	irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
416168d6f6deSJohan Hedberg 	if (irk) {
416268d6f6deSJohan Hedberg 		bacpy(&conn->dst, &irk->bdaddr);
416368d6f6deSJohan Hedberg 		conn->dst_type = irk->addr_type;
416468d6f6deSJohan Hedberg 	}
416568d6f6deSJohan Hedberg 
4166837d502eSJohan Hedberg 	if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
4167837d502eSJohan Hedberg 		addr_type = BDADDR_LE_PUBLIC;
4168837d502eSJohan Hedberg 	else
4169837d502eSJohan Hedberg 		addr_type = BDADDR_LE_RANDOM;
4170837d502eSJohan Hedberg 
4171837d502eSJohan Hedberg 	/* Drop the connection if he device is blocked */
4172837d502eSJohan Hedberg 	if (hci_blacklist_lookup(hdev, &conn->dst, addr_type)) {
4173837d502eSJohan Hedberg 		hci_conn_drop(conn);
4174837d502eSJohan Hedberg 		goto unlock;
4175837d502eSJohan Hedberg 	}
4176837d502eSJohan Hedberg 
4177cd17decbSAndre Guedes 	if (ev->status) {
417806c053fbSAndre Guedes 		hci_le_conn_failed(conn, ev->status);
4179cd17decbSAndre Guedes 		goto unlock;
4180cd17decbSAndre Guedes 	}
4181cd17decbSAndre Guedes 
4182b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
418301fdb0fcSMarcel Holtmann 		mgmt_device_connected(hdev, &conn->dst, conn->type,
418495b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
418583bc71b4SVinicius Costa Gomes 
41867b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
4187fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
4188fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
4189fcd89c09SVille Tervo 
4190e04fde60SMarcel Holtmann 	conn->le_conn_interval = le16_to_cpu(ev->interval);
4191e04fde60SMarcel Holtmann 	conn->le_conn_latency = le16_to_cpu(ev->latency);
4192e04fde60SMarcel Holtmann 	conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
4193e04fde60SMarcel Holtmann 
4194fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
4195fcd89c09SVille Tervo 
4196fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
4197fcd89c09SVille Tervo 
4198912b42efSJohan Hedberg 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
4199223683a5SJohan Hedberg 	if (params)
420095305baaSJohan Hedberg 		list_del_init(&params->action);
4201a4790dbdSAndre Guedes 
4202fcd89c09SVille Tervo unlock:
4203223683a5SJohan Hedberg 	hci_update_background_scan(hdev);
4204fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
4205fcd89c09SVille Tervo }
4206fcd89c09SVille Tervo 
42071855d92dSMarcel Holtmann static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
42081855d92dSMarcel Holtmann 					    struct sk_buff *skb)
42091855d92dSMarcel Holtmann {
42101855d92dSMarcel Holtmann 	struct hci_ev_le_conn_update_complete *ev = (void *) skb->data;
42111855d92dSMarcel Holtmann 	struct hci_conn *conn;
42121855d92dSMarcel Holtmann 
42131855d92dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
42141855d92dSMarcel Holtmann 
42151855d92dSMarcel Holtmann 	if (ev->status)
42161855d92dSMarcel Holtmann 		return;
42171855d92dSMarcel Holtmann 
42181855d92dSMarcel Holtmann 	hci_dev_lock(hdev);
42191855d92dSMarcel Holtmann 
42201855d92dSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
42211855d92dSMarcel Holtmann 	if (conn) {
42221855d92dSMarcel Holtmann 		conn->le_conn_interval = le16_to_cpu(ev->interval);
42231855d92dSMarcel Holtmann 		conn->le_conn_latency = le16_to_cpu(ev->latency);
42241855d92dSMarcel Holtmann 		conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
42251855d92dSMarcel Holtmann 	}
42261855d92dSMarcel Holtmann 
42271855d92dSMarcel Holtmann 	hci_dev_unlock(hdev);
42281855d92dSMarcel Holtmann }
42291855d92dSMarcel Holtmann 
4230a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */
4231bb5ce4d0SJohan Hedberg static bool check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
4232a4790dbdSAndre Guedes 				  u8 addr_type)
4233a4790dbdSAndre Guedes {
4234a4790dbdSAndre Guedes 	struct hci_conn *conn;
4235a4790dbdSAndre Guedes 
4236501f8827SJohan Hedberg 	if (!hci_pend_le_action_lookup(&hdev->pend_le_conns, addr, addr_type))
4237bb5ce4d0SJohan Hedberg 		return false;
4238a4790dbdSAndre Guedes 
4239a4790dbdSAndre Guedes 	conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
424009ae260bSJohan Hedberg 			      HCI_AT_NO_BONDING, HCI_LE_AUTOCONN_TIMEOUT);
4241a4790dbdSAndre Guedes 	if (!IS_ERR(conn))
4242bb5ce4d0SJohan Hedberg 		return true;
4243a4790dbdSAndre Guedes 
4244a4790dbdSAndre Guedes 	switch (PTR_ERR(conn)) {
4245a4790dbdSAndre Guedes 	case -EBUSY:
4246a4790dbdSAndre Guedes 		/* If hci_connect() returns -EBUSY it means there is already
4247a4790dbdSAndre Guedes 		 * an LE connection attempt going on. Since controllers don't
4248a4790dbdSAndre Guedes 		 * support more than one connection attempt at the time, we
4249a4790dbdSAndre Guedes 		 * don't consider this an error case.
4250a4790dbdSAndre Guedes 		 */
4251a4790dbdSAndre Guedes 		break;
4252a4790dbdSAndre Guedes 	default:
4253a4790dbdSAndre Guedes 		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
4254a4790dbdSAndre Guedes 	}
4255bb5ce4d0SJohan Hedberg 
4256bb5ce4d0SJohan Hedberg 	return true;
4257a4790dbdSAndre Guedes }
4258a4790dbdSAndre Guedes 
42594af605d8SJohan Hedberg static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
42604af605d8SJohan Hedberg 			       u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
42614af605d8SJohan Hedberg {
4262b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
4263474ee066SJohan Hedberg 	bool match;
4264c70a7e4cSMarcel Holtmann 	u32 flags;
4265b9a6328fSJohan Hedberg 
42660d2bf134SJohan Hedberg 	/* Passive scanning shouldn't trigger any device found events,
42670d2bf134SJohan Hedberg 	 * except for devices marked as CONN_REPORT for which we do send
42680d2bf134SJohan Hedberg 	 * device found events.
42690d2bf134SJohan Hedberg 	 */
4270ca5c4be7SJohan Hedberg 	if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
42710d2bf134SJohan Hedberg 		struct hci_conn_params *param;
4272079446c8SJohan Hedberg 		struct smp_irk *irk;
42730d2bf134SJohan Hedberg 
4274435a13d8SJohan Hedberg 		/* Check if we need to convert to identity address */
4275435a13d8SJohan Hedberg 		irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
4276435a13d8SJohan Hedberg 		if (irk) {
4277435a13d8SJohan Hedberg 			bdaddr = &irk->bdaddr;
4278435a13d8SJohan Hedberg 			bdaddr_type = irk->addr_type;
4279435a13d8SJohan Hedberg 		}
4280435a13d8SJohan Hedberg 
428199a6768eSJohan Hedberg 		/* Ignore if the device is blocked */
428299a6768eSJohan Hedberg 		if (hci_blacklist_lookup(hdev, bdaddr, bdaddr_type))
428399a6768eSJohan Hedberg 			return;
428499a6768eSJohan Hedberg 
4285bb5ce4d0SJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_DIRECT_IND) {
4286bb5ce4d0SJohan Hedberg 			if (check_pending_le_conn(hdev, bdaddr, bdaddr_type))
4287bb5ce4d0SJohan Hedberg 				return;
4288bb5ce4d0SJohan Hedberg 		}
42890d2bf134SJohan Hedberg 
42900d2bf134SJohan Hedberg 		if (type == LE_ADV_DIRECT_IND)
42910d2bf134SJohan Hedberg 			return;
42920d2bf134SJohan Hedberg 
4293a7545f2aSJohan Hedberg 		param = hci_pend_le_action_lookup(&hdev->pend_le_reports,
4294a7545f2aSJohan Hedberg 						  bdaddr, bdaddr_type);
4295a7545f2aSJohan Hedberg 		if (!param)
42960d2bf134SJohan Hedberg 			return;
42970d2bf134SJohan Hedberg 
42980d2bf134SJohan Hedberg 		if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND)
42990d2bf134SJohan Hedberg 			flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
43000d2bf134SJohan Hedberg 		else
43010d2bf134SJohan Hedberg 			flags = 0;
43020d2bf134SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
43030d2bf134SJohan Hedberg 				  rssi, flags, data, len, NULL, 0);
430497bf2e99SJohan Hedberg 		return;
4305ca5c4be7SJohan Hedberg 	}
43064af605d8SJohan Hedberg 
4307c70a7e4cSMarcel Holtmann 	/* When receiving non-connectable or scannable undirected
4308c70a7e4cSMarcel Holtmann 	 * advertising reports, this means that the remote device is
4309c70a7e4cSMarcel Holtmann 	 * not connectable and then clearly indicate this in the
4310c70a7e4cSMarcel Holtmann 	 * device found event.
4311c70a7e4cSMarcel Holtmann 	 *
4312c70a7e4cSMarcel Holtmann 	 * When receiving a scan response, then there is no way to
4313c70a7e4cSMarcel Holtmann 	 * know if the remote device is connectable or not. However
4314c70a7e4cSMarcel Holtmann 	 * since scan responses are merged with a previously seen
4315c70a7e4cSMarcel Holtmann 	 * advertising report, the flags field from that report
4316c70a7e4cSMarcel Holtmann 	 * will be used.
4317c70a7e4cSMarcel Holtmann 	 *
4318c70a7e4cSMarcel Holtmann 	 * In the really unlikely case that a controller get confused
4319c70a7e4cSMarcel Holtmann 	 * and just sends a scan response event, then it is marked as
4320c70a7e4cSMarcel Holtmann 	 * not connectable as well.
4321c70a7e4cSMarcel Holtmann 	 */
4322c70a7e4cSMarcel Holtmann 	if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND ||
4323c70a7e4cSMarcel Holtmann 	    type == LE_ADV_SCAN_RSP)
4324c70a7e4cSMarcel Holtmann 		flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
4325c70a7e4cSMarcel Holtmann 	else
4326c70a7e4cSMarcel Holtmann 		flags = 0;
4327c70a7e4cSMarcel Holtmann 
4328b9a6328fSJohan Hedberg 	/* If there's nothing pending either store the data from this
4329b9a6328fSJohan Hedberg 	 * event or send an immediate device found event if the data
4330b9a6328fSJohan Hedberg 	 * should not be stored for later.
4331b9a6328fSJohan Hedberg 	 */
4332b9a6328fSJohan Hedberg 	if (!has_pending_adv_report(hdev)) {
4333b9a6328fSJohan Hedberg 		/* If the report will trigger a SCAN_REQ store it for
4334b9a6328fSJohan Hedberg 		 * later merging.
4335b9a6328fSJohan Hedberg 		 */
4336b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
4337b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
4338c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
4339b9a6328fSJohan Hedberg 			return;
4340b9a6328fSJohan Hedberg 		}
4341b9a6328fSJohan Hedberg 
4342b9a6328fSJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
4343c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
4344b9a6328fSJohan Hedberg 		return;
4345b9a6328fSJohan Hedberg 	}
4346b9a6328fSJohan Hedberg 
4347474ee066SJohan Hedberg 	/* Check if the pending report is for the same device as the new one */
4348474ee066SJohan Hedberg 	match = (!bacmp(bdaddr, &d->last_adv_addr) &&
4349474ee066SJohan Hedberg 		 bdaddr_type == d->last_adv_addr_type);
4350474ee066SJohan Hedberg 
4351b9a6328fSJohan Hedberg 	/* If the pending data doesn't match this report or this isn't a
4352b9a6328fSJohan Hedberg 	 * scan response (e.g. we got a duplicate ADV_IND) then force
4353b9a6328fSJohan Hedberg 	 * sending of the pending data.
4354b9a6328fSJohan Hedberg 	 */
4355474ee066SJohan Hedberg 	if (type != LE_ADV_SCAN_RSP || !match) {
4356474ee066SJohan Hedberg 		/* Send out whatever is in the cache, but skip duplicates */
4357474ee066SJohan Hedberg 		if (!match)
4358b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4359ff5cd29fSJohan Hedberg 					  d->last_adv_addr_type, NULL,
4360c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
4361ff5cd29fSJohan Hedberg 					  d->last_adv_data,
4362474ee066SJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
4363b9a6328fSJohan Hedberg 
4364b9a6328fSJohan Hedberg 		/* If the new report will trigger a SCAN_REQ store it for
4365b9a6328fSJohan Hedberg 		 * later merging.
4366b9a6328fSJohan Hedberg 		 */
4367b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
4368b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
4369c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
4370b9a6328fSJohan Hedberg 			return;
4371b9a6328fSJohan Hedberg 		}
4372b9a6328fSJohan Hedberg 
4373b9a6328fSJohan Hedberg 		/* The advertising reports cannot be merged, so clear
4374b9a6328fSJohan Hedberg 		 * the pending report and send out a device found event.
4375b9a6328fSJohan Hedberg 		 */
4376b9a6328fSJohan Hedberg 		clear_pending_adv_report(hdev);
43775c5b93e4SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
4378c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
4379b9a6328fSJohan Hedberg 		return;
4380b9a6328fSJohan Hedberg 	}
4381b9a6328fSJohan Hedberg 
4382b9a6328fSJohan Hedberg 	/* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
4383b9a6328fSJohan Hedberg 	 * the new event is a SCAN_RSP. We can therefore proceed with
4384b9a6328fSJohan Hedberg 	 * sending a merged device found event.
4385b9a6328fSJohan Hedberg 	 */
4386b9a6328fSJohan Hedberg 	mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4387c70a7e4cSMarcel Holtmann 			  d->last_adv_addr_type, NULL, rssi, d->last_adv_flags,
438842bd6a56SMarcel Holtmann 			  d->last_adv_data, d->last_adv_data_len, data, len);
4389b9a6328fSJohan Hedberg 	clear_pending_adv_report(hdev);
43904af605d8SJohan Hedberg }
43914af605d8SJohan Hedberg 
43926039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
43939aa04c91SAndre Guedes {
4394e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
4395e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
43969aa04c91SAndre Guedes 
4397a4790dbdSAndre Guedes 	hci_dev_lock(hdev);
4398a4790dbdSAndre Guedes 
4399e95beb41SAndre Guedes 	while (num_reports--) {
4400e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
44014af605d8SJohan Hedberg 		s8 rssi;
4402a4790dbdSAndre Guedes 
44033c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
44044af605d8SJohan Hedberg 		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
44054af605d8SJohan Hedberg 				   ev->bdaddr_type, rssi, ev->data, ev->length);
44063c9e9195SAndre Guedes 
4407e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
44089aa04c91SAndre Guedes 	}
4409a4790dbdSAndre Guedes 
4410a4790dbdSAndre Guedes 	hci_dev_unlock(hdev);
44119aa04c91SAndre Guedes }
44129aa04c91SAndre Guedes 
44136039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
4414a7a595f6SVinicius Costa Gomes {
4415a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
4416a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
4417bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
4418a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
4419c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
4420a7a595f6SVinicius Costa Gomes 
44219f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
4422a7a595f6SVinicius Costa Gomes 
4423a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
4424a7a595f6SVinicius Costa Gomes 
4425a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
4426bea710feSVinicius Costa Gomes 	if (conn == NULL)
4427bea710feSVinicius Costa Gomes 		goto not_found;
4428a7a595f6SVinicius Costa Gomes 
4429fe39c7b2SMarcel Holtmann 	ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->out);
4430bea710feSVinicius Costa Gomes 	if (ltk == NULL)
4431bea710feSVinicius Costa Gomes 		goto not_found;
4432bea710feSVinicius Costa Gomes 
4433bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
4434a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
4435c9839a11SVinicius Costa Gomes 
4436c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
4437f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_HIGH;
4438f8776218SAndre Guedes 	else
4439f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_MEDIUM;
4440a7a595f6SVinicius Costa Gomes 
444189cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
4442a7a595f6SVinicius Costa Gomes 
4443a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
4444a7a595f6SVinicius Costa Gomes 
44455981a882SClaudio Takahasi 	/* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a
44465981a882SClaudio Takahasi 	 * temporary key used to encrypt a connection following
44475981a882SClaudio Takahasi 	 * pairing. It is used during the Encrypted Session Setup to
44485981a882SClaudio Takahasi 	 * distribute the keys. Later, security can be re-established
44495981a882SClaudio Takahasi 	 * using a distributed LTK.
44505981a882SClaudio Takahasi 	 */
44512ceba539SJohan Hedberg 	if (ltk->type == SMP_STK) {
4452fe59a05fSJohan Hedberg 		set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
4453c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
4454c9839a11SVinicius Costa Gomes 		kfree(ltk);
4455fe59a05fSJohan Hedberg 	} else {
4456fe59a05fSJohan Hedberg 		clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
4457c9839a11SVinicius Costa Gomes 	}
4458c9839a11SVinicius Costa Gomes 
4459a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
4460bea710feSVinicius Costa Gomes 
4461bea710feSVinicius Costa Gomes 	return;
4462bea710feSVinicius Costa Gomes 
4463bea710feSVinicius Costa Gomes not_found:
4464bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
4465bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
4466bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
4467a7a595f6SVinicius Costa Gomes }
4468a7a595f6SVinicius Costa Gomes 
44698e75b46aSAndre Guedes static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
44708e75b46aSAndre Guedes 				      u8 reason)
44718e75b46aSAndre Guedes {
44728e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_neg_reply cp;
44738e75b46aSAndre Guedes 
44748e75b46aSAndre Guedes 	cp.handle = cpu_to_le16(handle);
44758e75b46aSAndre Guedes 	cp.reason = reason;
44768e75b46aSAndre Guedes 
44778e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp),
44788e75b46aSAndre Guedes 		     &cp);
44798e75b46aSAndre Guedes }
44808e75b46aSAndre Guedes 
44818e75b46aSAndre Guedes static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
44828e75b46aSAndre Guedes 					     struct sk_buff *skb)
44838e75b46aSAndre Guedes {
44848e75b46aSAndre Guedes 	struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data;
44858e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_reply cp;
44868e75b46aSAndre Guedes 	struct hci_conn *hcon;
44878e75b46aSAndre Guedes 	u16 handle, min, max, latency, timeout;
44888e75b46aSAndre Guedes 
44898e75b46aSAndre Guedes 	handle = le16_to_cpu(ev->handle);
44908e75b46aSAndre Guedes 	min = le16_to_cpu(ev->interval_min);
44918e75b46aSAndre Guedes 	max = le16_to_cpu(ev->interval_max);
44928e75b46aSAndre Guedes 	latency = le16_to_cpu(ev->latency);
44938e75b46aSAndre Guedes 	timeout = le16_to_cpu(ev->timeout);
44948e75b46aSAndre Guedes 
44958e75b46aSAndre Guedes 	hcon = hci_conn_hash_lookup_handle(hdev, handle);
44968e75b46aSAndre Guedes 	if (!hcon || hcon->state != BT_CONNECTED)
44978e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
44988e75b46aSAndre Guedes 						 HCI_ERROR_UNKNOWN_CONN_ID);
44998e75b46aSAndre Guedes 
45008e75b46aSAndre Guedes 	if (hci_check_conn_params(min, max, latency, timeout))
45018e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
45028e75b46aSAndre Guedes 						 HCI_ERROR_INVALID_LL_PARAMS);
45038e75b46aSAndre Guedes 
4504348d50b8SJohan Hedberg 	if (test_bit(HCI_CONN_MASTER, &hcon->flags)) {
4505348d50b8SJohan Hedberg 		struct hci_conn_params *params;
4506f4869e2aSJohan Hedberg 		u8 store_hint;
4507348d50b8SJohan Hedberg 
4508348d50b8SJohan Hedberg 		hci_dev_lock(hdev);
4509348d50b8SJohan Hedberg 
4510348d50b8SJohan Hedberg 		params = hci_conn_params_lookup(hdev, &hcon->dst,
4511348d50b8SJohan Hedberg 						hcon->dst_type);
4512348d50b8SJohan Hedberg 		if (params) {
4513348d50b8SJohan Hedberg 			params->conn_min_interval = min;
4514348d50b8SJohan Hedberg 			params->conn_max_interval = max;
4515348d50b8SJohan Hedberg 			params->conn_latency = latency;
4516348d50b8SJohan Hedberg 			params->supervision_timeout = timeout;
4517f4869e2aSJohan Hedberg 			store_hint = 0x01;
4518f4869e2aSJohan Hedberg 		} else{
4519f4869e2aSJohan Hedberg 			store_hint = 0x00;
4520348d50b8SJohan Hedberg 		}
4521348d50b8SJohan Hedberg 
4522348d50b8SJohan Hedberg 		hci_dev_unlock(hdev);
4523348d50b8SJohan Hedberg 
4524f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type,
4525f4869e2aSJohan Hedberg 				    store_hint, min, max, latency, timeout);
4526348d50b8SJohan Hedberg 	}
4527ffb5a827SAndre Guedes 
45288e75b46aSAndre Guedes 	cp.handle = ev->handle;
45298e75b46aSAndre Guedes 	cp.interval_min = ev->interval_min;
45308e75b46aSAndre Guedes 	cp.interval_max = ev->interval_max;
45318e75b46aSAndre Guedes 	cp.latency = ev->latency;
45328e75b46aSAndre Guedes 	cp.timeout = ev->timeout;
45338e75b46aSAndre Guedes 	cp.min_ce_len = 0;
45348e75b46aSAndre Guedes 	cp.max_ce_len = 0;
45358e75b46aSAndre Guedes 
45368e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
45378e75b46aSAndre Guedes }
45388e75b46aSAndre Guedes 
45396039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
4540fcd89c09SVille Tervo {
4541fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
4542fcd89c09SVille Tervo 
4543fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
4544fcd89c09SVille Tervo 
4545fcd89c09SVille Tervo 	switch (le_ev->subevent) {
4546fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
4547fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
4548fcd89c09SVille Tervo 		break;
4549fcd89c09SVille Tervo 
45501855d92dSMarcel Holtmann 	case HCI_EV_LE_CONN_UPDATE_COMPLETE:
45511855d92dSMarcel Holtmann 		hci_le_conn_update_complete_evt(hdev, skb);
45521855d92dSMarcel Holtmann 		break;
45531855d92dSMarcel Holtmann 
45549aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
45559aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
45569aa04c91SAndre Guedes 		break;
45579aa04c91SAndre Guedes 
4558a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
4559a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
4560a7a595f6SVinicius Costa Gomes 		break;
4561a7a595f6SVinicius Costa Gomes 
45628e75b46aSAndre Guedes 	case HCI_EV_LE_REMOTE_CONN_PARAM_REQ:
45638e75b46aSAndre Guedes 		hci_le_remote_conn_param_req_evt(hdev, skb);
45648e75b46aSAndre Guedes 		break;
45658e75b46aSAndre Guedes 
4566fcd89c09SVille Tervo 	default:
4567fcd89c09SVille Tervo 		break;
4568fcd89c09SVille Tervo 	}
4569fcd89c09SVille Tervo }
4570fcd89c09SVille Tervo 
45719495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
45729495b2eeSAndrei Emeltchenko {
45739495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
45749495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
45759495b2eeSAndrei Emeltchenko 
45769495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
45779495b2eeSAndrei Emeltchenko 
45789495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
45799495b2eeSAndrei Emeltchenko 
45809495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
45819495b2eeSAndrei Emeltchenko 	if (!hcon)
45829495b2eeSAndrei Emeltchenko 		return;
45839495b2eeSAndrei Emeltchenko 
45849495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
45859495b2eeSAndrei Emeltchenko }
45869495b2eeSAndrei Emeltchenko 
45871da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
45881da177e4SLinus Torvalds {
4589a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
4590a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
45911da177e4SLinus Torvalds 
4592b6ddb638SJohan Hedberg 	hci_dev_lock(hdev);
4593b6ddb638SJohan Hedberg 
4594b6ddb638SJohan Hedberg 	/* Received events are (currently) only needed when a request is
4595b6ddb638SJohan Hedberg 	 * ongoing so avoid unnecessary memory allocation.
4596b6ddb638SJohan Hedberg 	 */
4597b6ddb638SJohan Hedberg 	if (hdev->req_status == HCI_REQ_PEND) {
4598b6ddb638SJohan Hedberg 		kfree_skb(hdev->recv_evt);
4599b6ddb638SJohan Hedberg 		hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
4600b6ddb638SJohan Hedberg 	}
4601b6ddb638SJohan Hedberg 
4602b6ddb638SJohan Hedberg 	hci_dev_unlock(hdev);
4603b6ddb638SJohan Hedberg 
46041da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
46051da177e4SLinus Torvalds 
460602350a72SJohan Hedberg 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
4607c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
4608c1f23a2bSJohannes Berg 		u16 opcode = __le16_to_cpu(cmd_hdr->opcode);
460902350a72SJohan Hedberg 
461002350a72SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, 0);
461102350a72SJohan Hedberg 	}
461202350a72SJohan Hedberg 
4613a9de9248SMarcel Holtmann 	switch (event) {
46141da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
46151da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
46161da177e4SLinus Torvalds 		break;
46171da177e4SLinus Torvalds 
46181da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
46191da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
46201da177e4SLinus Torvalds 		break;
46211da177e4SLinus Torvalds 
4622a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
4623a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
462421d9e30eSMarcel Holtmann 		break;
462521d9e30eSMarcel Holtmann 
46261da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
46271da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
46281da177e4SLinus Torvalds 		break;
46291da177e4SLinus Torvalds 
46301da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
46311da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
46321da177e4SLinus Torvalds 		break;
46331da177e4SLinus Torvalds 
46341da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
46351da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
46361da177e4SLinus Torvalds 		break;
46371da177e4SLinus Torvalds 
4638a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
4639a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
4640a9de9248SMarcel Holtmann 		break;
4641a9de9248SMarcel Holtmann 
46421da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
46431da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
46441da177e4SLinus Torvalds 		break;
46451da177e4SLinus Torvalds 
4646a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
4647a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
4648a9de9248SMarcel Holtmann 		break;
4649a9de9248SMarcel Holtmann 
4650a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
4651a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
4652a9de9248SMarcel Holtmann 		break;
4653a9de9248SMarcel Holtmann 
4654a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
4655a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
4656a9de9248SMarcel Holtmann 		break;
4657a9de9248SMarcel Holtmann 
4658a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
4659a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
4660a9de9248SMarcel Holtmann 		break;
4661a9de9248SMarcel Holtmann 
4662a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
4663a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
4664a9de9248SMarcel Holtmann 		break;
4665a9de9248SMarcel Holtmann 
4666a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
4667a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
4668a9de9248SMarcel Holtmann 		break;
4669a9de9248SMarcel Holtmann 
4670a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
4671a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
46721da177e4SLinus Torvalds 		break;
46731da177e4SLinus Torvalds 
46741da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
46751da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
46761da177e4SLinus Torvalds 		break;
46771da177e4SLinus Torvalds 
46781da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
46791da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
46801da177e4SLinus Torvalds 		break;
46811da177e4SLinus Torvalds 
46821da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
46831da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
46841da177e4SLinus Torvalds 		break;
46851da177e4SLinus Torvalds 
46861da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
46871da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
46881da177e4SLinus Torvalds 		break;
46891da177e4SLinus Torvalds 
4690a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
4691a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
4692a8746417SMarcel Holtmann 		break;
4693a8746417SMarcel Holtmann 
469485a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
469585a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
469685a1e930SMarcel Holtmann 		break;
469785a1e930SMarcel Holtmann 
4698a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4699a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
4700a9de9248SMarcel Holtmann 		break;
4701a9de9248SMarcel Holtmann 
4702a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
4703a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
4704a9de9248SMarcel Holtmann 		break;
4705a9de9248SMarcel Holtmann 
4706a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
4707a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
4708a9de9248SMarcel Holtmann 		break;
4709a9de9248SMarcel Holtmann 
4710a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
4711a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
47121da177e4SLinus Torvalds 		break;
47131da177e4SLinus Torvalds 
47141c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
47151c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
47161c2e0041SJohan Hedberg 		break;
47171c2e0041SJohan Hedberg 
47180493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
47190493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
47200493684eSMarcel Holtmann 		break;
47210493684eSMarcel Holtmann 
472203b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
472303b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
472403b555e1SJohan Hedberg 		break;
472503b555e1SJohan Hedberg 
4726a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
4727a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
4728a5c29683SJohan Hedberg 		break;
4729a5c29683SJohan Hedberg 
47301143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
47311143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
47321143d458SBrian Gix 		break;
47331143d458SBrian Gix 
473492a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
473592a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
473692a25256SJohan Hedberg 		break;
473792a25256SJohan Hedberg 
473892a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
473992a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
474092a25256SJohan Hedberg 		break;
474192a25256SJohan Hedberg 
47420493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
47430493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
47440493684eSMarcel Holtmann 		break;
47450493684eSMarcel Holtmann 
474641a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
474741a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
474841a96212SMarcel Holtmann 		break;
474941a96212SMarcel Holtmann 
4750fcd89c09SVille Tervo 	case HCI_EV_LE_META:
4751fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
4752fcd89c09SVille Tervo 		break;
4753fcd89c09SVille Tervo 
47549495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
47559495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
47569495b2eeSAndrei Emeltchenko 		break;
47579495b2eeSAndrei Emeltchenko 
47582763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
47592763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
47602763eda6SSzymon Janc 		break;
47612763eda6SSzymon Janc 
4762d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
4763d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
4764d5e91192SAndrei Emeltchenko 		break;
4765d5e91192SAndrei Emeltchenko 
476627695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
476727695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
476827695fb4SAndrei Emeltchenko 		break;
476927695fb4SAndrei Emeltchenko 
4770606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4771606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
4772606e2a10SAndrei Emeltchenko 		break;
4773606e2a10SAndrei Emeltchenko 
47749eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
47759eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
47769eef6b3aSAndrei Emeltchenko 		break;
47779eef6b3aSAndrei Emeltchenko 
477825e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
477925e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
478025e89e99SAndrei Emeltchenko 		break;
478125e89e99SAndrei Emeltchenko 
47821da177e4SLinus Torvalds 	default:
47839f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
47841da177e4SLinus Torvalds 		break;
47851da177e4SLinus Torvalds 	}
47861da177e4SLinus Torvalds 
47871da177e4SLinus Torvalds 	kfree_skb(skb);
47881da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
47891da177e4SLinus Torvalds }
4790