xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 2f20216c)
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 
330857dd3bSJohan Hedberg #include "hci_request.h"
3423b9ceb7SMarcel Holtmann #include "hci_debugfs.h"
357024728eSMarcel Holtmann #include "a2mp.h"
367ef9fbf0SMarcel Holtmann #include "amp.h"
372ceba539SJohan Hedberg #include "smp.h"
38145373cbSMiao-chen Chou #include "msft.h"
391da177e4SLinus Torvalds 
40aa5b0345SMarcel Holtmann #define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
41aa5b0345SMarcel Holtmann 		 "\x00\x00\x00\x00\x00\x00\x00\x00"
42aa5b0345SMarcel Holtmann 
431da177e4SLinus Torvalds /* Handle HCI Event packets */
441da177e4SLinus Torvalds 
45adf1d692SSonny Sasaka static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
46adf1d692SSonny Sasaka 				  u8 *new_status)
471da177e4SLinus Torvalds {
48a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
491da177e4SLinus Torvalds 
509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
511da177e4SLinus Torvalds 
52adf1d692SSonny Sasaka 	/* It is possible that we receive Inquiry Complete event right
53adf1d692SSonny Sasaka 	 * before we receive Inquiry Cancel Command Complete event, in
54adf1d692SSonny Sasaka 	 * which case the latter event should have status of Command
55adf1d692SSonny Sasaka 	 * Disallowed (0x0c). This should not be treated as error, since
56adf1d692SSonny Sasaka 	 * we actually achieve what Inquiry Cancel wants to achieve,
57adf1d692SSonny Sasaka 	 * which is to end the last Inquiry session.
58adf1d692SSonny Sasaka 	 */
59adf1d692SSonny Sasaka 	if (status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) {
60adf1d692SSonny Sasaka 		bt_dev_warn(hdev, "Ignoring error of Inquiry Cancel command");
61adf1d692SSonny Sasaka 		status = 0x00;
62adf1d692SSonny Sasaka 	}
63adf1d692SSonny Sasaka 
64adf1d692SSonny Sasaka 	*new_status = status;
65adf1d692SSonny Sasaka 
6682f4785cSAndre Guedes 	if (status)
67a9de9248SMarcel Holtmann 		return;
681da177e4SLinus Torvalds 
6989352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
704e857c58SPeter Zijlstra 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
713e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
7289352e7dSAndre Guedes 
7350143a43SJohan Hedberg 	hci_dev_lock(hdev);
74168b8a25SJakub Pawlowski 	/* Set discovery state to stopped if we're not doing LE active
75168b8a25SJakub Pawlowski 	 * scanning.
76168b8a25SJakub Pawlowski 	 */
77168b8a25SJakub Pawlowski 	if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
78168b8a25SJakub Pawlowski 	    hdev->le_scan_type != LE_SCAN_ACTIVE)
7950143a43SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
8050143a43SJohan Hedberg 	hci_dev_unlock(hdev);
8150143a43SJohan Hedberg 
82a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
831da177e4SLinus Torvalds }
846bd57416SMarcel Holtmann 
854d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
864d93483bSAndre Guedes {
874d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
884d93483bSAndre Guedes 
899f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
90ae854a70SAndre Guedes 
91ae854a70SAndre Guedes 	if (status)
92ae854a70SAndre Guedes 		return;
93ae854a70SAndre Guedes 
94a1536da2SMarcel Holtmann 	hci_dev_set_flag(hdev, HCI_PERIODIC_INQ);
954d93483bSAndre Guedes }
964d93483bSAndre Guedes 
97a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
981da177e4SLinus Torvalds {
99a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
100a9de9248SMarcel Holtmann 
1019f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
102a9de9248SMarcel Holtmann 
103a9de9248SMarcel Holtmann 	if (status)
104a9de9248SMarcel Holtmann 		return;
105a9de9248SMarcel Holtmann 
106a358dc11SMarcel Holtmann 	hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ);
107ae854a70SAndre Guedes 
108a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
109a9de9248SMarcel Holtmann }
110a9de9248SMarcel Holtmann 
111807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
112807deac2SGustavo Padovan 					  struct sk_buff *skb)
113a9de9248SMarcel Holtmann {
114a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
115a9de9248SMarcel Holtmann }
116a9de9248SMarcel Holtmann 
117a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
118a9de9248SMarcel Holtmann {
119a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
1201da177e4SLinus Torvalds 	struct hci_conn *conn;
1211da177e4SLinus Torvalds 
1229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1231da177e4SLinus Torvalds 
124a9de9248SMarcel Holtmann 	if (rp->status)
125a9de9248SMarcel Holtmann 		return;
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1281da177e4SLinus Torvalds 
129a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
13040bef302SJohan Hedberg 	if (conn)
13140bef302SJohan Hedberg 		conn->role = rp->role;
1321da177e4SLinus Torvalds 
1331da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
134a9de9248SMarcel Holtmann }
1351da177e4SLinus Torvalds 
136e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
137e4e8e37cSMarcel Holtmann {
138e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
139e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
140e4e8e37cSMarcel Holtmann 
1419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
142e4e8e37cSMarcel Holtmann 
143e4e8e37cSMarcel Holtmann 	if (rp->status)
144e4e8e37cSMarcel Holtmann 		return;
145e4e8e37cSMarcel Holtmann 
146e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
147e4e8e37cSMarcel Holtmann 
148e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
149e4e8e37cSMarcel Holtmann 	if (conn)
150e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
151e4e8e37cSMarcel Holtmann 
152e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
153e4e8e37cSMarcel Holtmann }
154e4e8e37cSMarcel Holtmann 
155a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
156a9de9248SMarcel Holtmann {
157a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
158a9de9248SMarcel Holtmann 	struct hci_conn *conn;
159a9de9248SMarcel Holtmann 	void *sent;
160a9de9248SMarcel Holtmann 
1619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
162a9de9248SMarcel Holtmann 
163a9de9248SMarcel Holtmann 	if (rp->status)
164a9de9248SMarcel Holtmann 		return;
165a9de9248SMarcel Holtmann 
166a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
16704837f64SMarcel Holtmann 	if (!sent)
168a9de9248SMarcel Holtmann 		return;
16904837f64SMarcel Holtmann 
17004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
17104837f64SMarcel Holtmann 
172a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
173e4e8e37cSMarcel Holtmann 	if (conn)
17483985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
17504837f64SMarcel Holtmann 
17604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1771da177e4SLinus Torvalds }
1781da177e4SLinus Torvalds 
179807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
180807deac2SGustavo Padovan 					struct sk_buff *skb)
181e4e8e37cSMarcel Holtmann {
182e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
183e4e8e37cSMarcel Holtmann 
1849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
185e4e8e37cSMarcel Holtmann 
186e4e8e37cSMarcel Holtmann 	if (rp->status)
187e4e8e37cSMarcel Holtmann 		return;
188e4e8e37cSMarcel Holtmann 
189e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
190e4e8e37cSMarcel Holtmann }
191e4e8e37cSMarcel Holtmann 
192807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
193807deac2SGustavo Padovan 					 struct sk_buff *skb)
194e4e8e37cSMarcel Holtmann {
195e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
196e4e8e37cSMarcel Holtmann 	void *sent;
197e4e8e37cSMarcel Holtmann 
1989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
199e4e8e37cSMarcel Holtmann 
20045296acdSMarcel Holtmann 	if (status)
20145296acdSMarcel Holtmann 		return;
20245296acdSMarcel Holtmann 
203e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
204e4e8e37cSMarcel Holtmann 	if (!sent)
205e4e8e37cSMarcel Holtmann 		return;
206e4e8e37cSMarcel Holtmann 
207e4e8e37cSMarcel Holtmann 	hdev->link_policy = get_unaligned_le16(sent);
208e4e8e37cSMarcel Holtmann }
209e4e8e37cSMarcel Holtmann 
210a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
2111da177e4SLinus Torvalds {
212a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
213a9de9248SMarcel Holtmann 
2149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
215a9de9248SMarcel Holtmann 
21610572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
21710572132SGustavo F. Padovan 
2188761f9d6SMarcel Holtmann 	if (status)
2198761f9d6SMarcel Holtmann 		return;
2208761f9d6SMarcel Holtmann 
221a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
222eacb44dfSMarcel Holtmann 	hci_dev_clear_volatile_flags(hdev);
22369775ff6SAndre Guedes 
22439c5d970SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
22539c5d970SJohan Hedberg 
226bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
227bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
2283f0f524bSJohan Hedberg 
2293f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
2303f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
231f8e808bdSMarcel Holtmann 
232f8e808bdSMarcel Holtmann 	memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data));
233f8e808bdSMarcel Holtmann 	hdev->scan_rsp_data_len = 0;
23406f5b778SMarcel Holtmann 
235533553f8SMarcel Holtmann 	hdev->le_scan_type = LE_SCAN_PASSIVE;
236533553f8SMarcel Holtmann 
23706f5b778SMarcel Holtmann 	hdev->ssp_debug_mode = 0;
238a4d5504dSMarcel Holtmann 
239a4d5504dSMarcel Holtmann 	hci_bdaddr_list_clear(&hdev->le_white_list);
240cfdb0c2dSAnkit Navik 	hci_bdaddr_list_clear(&hdev->le_resolv_list);
241a9de9248SMarcel Holtmann }
242a9de9248SMarcel Holtmann 
243c2f0f979SMarcel Holtmann static void hci_cc_read_stored_link_key(struct hci_dev *hdev,
244c2f0f979SMarcel Holtmann 					struct sk_buff *skb)
245c2f0f979SMarcel Holtmann {
246c2f0f979SMarcel Holtmann 	struct hci_rp_read_stored_link_key *rp = (void *)skb->data;
247c2f0f979SMarcel Holtmann 	struct hci_cp_read_stored_link_key *sent;
248c2f0f979SMarcel Holtmann 
249c2f0f979SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
250c2f0f979SMarcel Holtmann 
251c2f0f979SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY);
252c2f0f979SMarcel Holtmann 	if (!sent)
253c2f0f979SMarcel Holtmann 		return;
254c2f0f979SMarcel Holtmann 
255c2f0f979SMarcel Holtmann 	if (!rp->status && sent->read_all == 0x01) {
256c2f0f979SMarcel Holtmann 		hdev->stored_max_keys = rp->max_keys;
257c2f0f979SMarcel Holtmann 		hdev->stored_num_keys = rp->num_keys;
258c2f0f979SMarcel Holtmann 	}
259c2f0f979SMarcel Holtmann }
260c2f0f979SMarcel Holtmann 
261a9366120SMarcel Holtmann static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
262a9366120SMarcel Holtmann 					  struct sk_buff *skb)
263a9366120SMarcel Holtmann {
264a9366120SMarcel Holtmann 	struct hci_rp_delete_stored_link_key *rp = (void *)skb->data;
265a9366120SMarcel Holtmann 
266a9366120SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
267a9366120SMarcel Holtmann 
268a9366120SMarcel Holtmann 	if (rp->status)
269a9366120SMarcel Holtmann 		return;
270a9366120SMarcel Holtmann 
271a9366120SMarcel Holtmann 	if (rp->num_keys <= hdev->stored_num_keys)
272a9366120SMarcel Holtmann 		hdev->stored_num_keys -= rp->num_keys;
273a9366120SMarcel Holtmann 	else
274a9366120SMarcel Holtmann 		hdev->stored_num_keys = 0;
275a9366120SMarcel Holtmann }
276a9366120SMarcel Holtmann 
277a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
278a9de9248SMarcel Holtmann {
279a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2801da177e4SLinus Torvalds 	void *sent;
2811da177e4SLinus Torvalds 
2829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2831da177e4SLinus Torvalds 
284a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2851da177e4SLinus Torvalds 	if (!sent)
286a9de9248SMarcel Holtmann 		return;
2871da177e4SLinus Torvalds 
28856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
28956e5cb86SJohan Hedberg 
290d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
291f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
29228cc7bdeSJohan Hedberg 	else if (!status)
29328cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
294f51d5b24SJohan Hedberg 
29556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
296a9de9248SMarcel Holtmann }
297a9de9248SMarcel Holtmann 
298a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
299a9de9248SMarcel Holtmann {
300a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
301a9de9248SMarcel Holtmann 
3029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
303a9de9248SMarcel Holtmann 
304a9de9248SMarcel Holtmann 	if (rp->status)
305a9de9248SMarcel Holtmann 		return;
306a9de9248SMarcel Holtmann 
307d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
308d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hdev, HCI_CONFIG))
3091f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
310a9de9248SMarcel Holtmann }
311a9de9248SMarcel Holtmann 
312a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
313a9de9248SMarcel Holtmann {
314a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
315a9de9248SMarcel Holtmann 	void *sent;
316a9de9248SMarcel Holtmann 
3179f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
318a9de9248SMarcel Holtmann 
319a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
320a9de9248SMarcel Holtmann 	if (!sent)
321a9de9248SMarcel Holtmann 		return;
3221da177e4SLinus Torvalds 
3235c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
3245c1a4c8fSJaganath Kanakkassery 
3251da177e4SLinus Torvalds 	if (!status) {
326a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
327a9de9248SMarcel Holtmann 
3281da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
3291da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
3301da177e4SLinus Torvalds 		else
3311da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
3321da177e4SLinus Torvalds 	}
333a9de9248SMarcel Holtmann 
334d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
33533ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
3365c1a4c8fSJaganath Kanakkassery 
3375c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
338a9de9248SMarcel Holtmann }
3391da177e4SLinus Torvalds 
340a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
341a9de9248SMarcel Holtmann {
342a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
34345296acdSMarcel Holtmann 	__u8 param;
344a9de9248SMarcel Holtmann 	void *sent;
345a9de9248SMarcel Holtmann 
3469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
347a9de9248SMarcel Holtmann 
34845296acdSMarcel Holtmann 	if (status)
34945296acdSMarcel Holtmann 		return;
35045296acdSMarcel Holtmann 
351a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
3521da177e4SLinus Torvalds 	if (!sent)
353a9de9248SMarcel Holtmann 		return;
3541da177e4SLinus Torvalds 
35545296acdSMarcel Holtmann 	param = *((__u8 *) sent);
356a9de9248SMarcel Holtmann 
3571da177e4SLinus Torvalds 	if (param)
3581da177e4SLinus Torvalds 		set_bit(HCI_ENCRYPT, &hdev->flags);
3591da177e4SLinus Torvalds 	else
3601da177e4SLinus Torvalds 		clear_bit(HCI_ENCRYPT, &hdev->flags);
3611da177e4SLinus Torvalds }
3621da177e4SLinus Torvalds 
363a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
364a9de9248SMarcel Holtmann {
36545296acdSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
36645296acdSMarcel Holtmann 	__u8 param;
367a9de9248SMarcel Holtmann 	void *sent;
3681da177e4SLinus Torvalds 
3699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
370a9de9248SMarcel Holtmann 
371a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3721da177e4SLinus Torvalds 	if (!sent)
373a9de9248SMarcel Holtmann 		return;
3741da177e4SLinus Torvalds 
37536f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
376a9de9248SMarcel Holtmann 
37756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
37856e5cb86SJohan Hedberg 
379fa1bd918SMikel Astiz 	if (status) {
3802d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3812d7cee58SJohan Hedberg 		goto done;
3822d7cee58SJohan Hedberg 	}
3832d7cee58SJohan Hedberg 
384bc6d2d04SJohan Hedberg 	if (param & SCAN_INQUIRY)
3851da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
386bc6d2d04SJohan Hedberg 	else
387bc6d2d04SJohan Hedberg 		clear_bit(HCI_ISCAN, &hdev->flags);
3881da177e4SLinus Torvalds 
389031547d8SJohan Hedberg 	if (param & SCAN_PAGE)
3901da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
391bc6d2d04SJohan Hedberg 	else
392204e3990SJohan Hedberg 		clear_bit(HCI_PSCAN, &hdev->flags);
393a9de9248SMarcel Holtmann 
39436f7fc7eSJohan Hedberg done:
39556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
3961da177e4SLinus Torvalds }
3971da177e4SLinus Torvalds 
398a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
399a9de9248SMarcel Holtmann {
400a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
401a9de9248SMarcel Holtmann 
4029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
403a9de9248SMarcel Holtmann 
404a9de9248SMarcel Holtmann 	if (rp->status)
405a9de9248SMarcel Holtmann 		return;
406a9de9248SMarcel Holtmann 
407a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
408a9de9248SMarcel Holtmann 
409a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
410a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
411a9de9248SMarcel Holtmann }
412a9de9248SMarcel Holtmann 
413a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
414a9de9248SMarcel Holtmann {
415a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
416a9de9248SMarcel Holtmann 	void *sent;
417a9de9248SMarcel Holtmann 
4189f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
419a9de9248SMarcel Holtmann 
420a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
421a9de9248SMarcel Holtmann 	if (!sent)
422a9de9248SMarcel Holtmann 		return;
423a9de9248SMarcel Holtmann 
4247f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
4257f9a903cSMarcel Holtmann 
4267f9a903cSMarcel Holtmann 	if (status == 0)
427a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
4287f9a903cSMarcel Holtmann 
429d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
4307f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
4317f9a903cSMarcel Holtmann 
4327f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
433a9de9248SMarcel Holtmann }
434a9de9248SMarcel Holtmann 
435a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
436a9de9248SMarcel Holtmann {
437a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
438a9de9248SMarcel Holtmann 	__u16 setting;
439a9de9248SMarcel Holtmann 
4409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
441a9de9248SMarcel Holtmann 
442a9de9248SMarcel Holtmann 	if (rp->status)
443a9de9248SMarcel Holtmann 		return;
444a9de9248SMarcel Holtmann 
445a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
446a9de9248SMarcel Holtmann 
447a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
448a9de9248SMarcel Holtmann 		return;
449a9de9248SMarcel Holtmann 
450a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
451a9de9248SMarcel Holtmann 
4529f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
453a9de9248SMarcel Holtmann 
4543c54711cSGustavo F. Padovan 	if (hdev->notify)
455a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
456a9de9248SMarcel Holtmann }
457a9de9248SMarcel Holtmann 
4588fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
4598fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
460a9de9248SMarcel Holtmann {
461a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
462f383f275SMarcel Holtmann 	__u16 setting;
463a9de9248SMarcel Holtmann 	void *sent;
464a9de9248SMarcel Holtmann 
4659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
466a9de9248SMarcel Holtmann 
467f383f275SMarcel Holtmann 	if (status)
468f383f275SMarcel Holtmann 		return;
469f383f275SMarcel Holtmann 
470a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
471a9de9248SMarcel Holtmann 	if (!sent)
472a9de9248SMarcel Holtmann 		return;
473a9de9248SMarcel Holtmann 
474f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4751da177e4SLinus Torvalds 
476f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
477f383f275SMarcel Holtmann 		return;
478f383f275SMarcel Holtmann 
4791da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4801da177e4SLinus Torvalds 
4819f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4821da177e4SLinus Torvalds 
4833c54711cSGustavo F. Padovan 	if (hdev->notify)
4841da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4851da177e4SLinus Torvalds }
4861da177e4SLinus Torvalds 
487b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev,
488b4cb9fb2SMarcel Holtmann 					  struct sk_buff *skb)
489b4cb9fb2SMarcel Holtmann {
490b4cb9fb2SMarcel Holtmann 	struct hci_rp_read_num_supported_iac *rp = (void *) skb->data;
491b4cb9fb2SMarcel Holtmann 
492b4cb9fb2SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
493b4cb9fb2SMarcel Holtmann 
494b4cb9fb2SMarcel Holtmann 	if (rp->status)
495b4cb9fb2SMarcel Holtmann 		return;
496b4cb9fb2SMarcel Holtmann 
497b4cb9fb2SMarcel Holtmann 	hdev->num_iac = rp->num_iac;
498b4cb9fb2SMarcel Holtmann 
499b4cb9fb2SMarcel Holtmann 	BT_DBG("%s num iac %d", hdev->name, hdev->num_iac);
500b4cb9fb2SMarcel Holtmann }
501b4cb9fb2SMarcel Holtmann 
502333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
503333140b5SMarcel Holtmann {
504333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
5055ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
506333140b5SMarcel Holtmann 
5079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
508333140b5SMarcel Holtmann 
509333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
510333140b5SMarcel Holtmann 	if (!sent)
511333140b5SMarcel Holtmann 		return;
512333140b5SMarcel Holtmann 
5135c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
5145c1a4c8fSJaganath Kanakkassery 
5155ed8eb2fSJohan Hedberg 	if (!status) {
5165ed8eb2fSJohan Hedberg 		if (sent->mode)
517cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_SSP;
5185ed8eb2fSJohan Hedberg 		else
519cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_SSP;
5205ed8eb2fSJohan Hedberg 	}
5215ed8eb2fSJohan Hedberg 
522d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
5235ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
524c0ecddc2SJohan Hedberg 	else if (!status) {
5255ed8eb2fSJohan Hedberg 		if (sent->mode)
526a1536da2SMarcel Holtmann 			hci_dev_set_flag(hdev, HCI_SSP_ENABLED);
52784bde9d6SJohan Hedberg 		else
528a358dc11SMarcel Holtmann 			hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
529c0ecddc2SJohan Hedberg 	}
5305c1a4c8fSJaganath Kanakkassery 
5315c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
532333140b5SMarcel Holtmann }
533333140b5SMarcel Holtmann 
534eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
535eac83dc6SMarcel Holtmann {
536eac83dc6SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
537eac83dc6SMarcel Holtmann 	struct hci_cp_write_sc_support *sent;
538eac83dc6SMarcel Holtmann 
539eac83dc6SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
540eac83dc6SMarcel Holtmann 
541eac83dc6SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
542eac83dc6SMarcel Holtmann 	if (!sent)
543eac83dc6SMarcel Holtmann 		return;
544eac83dc6SMarcel Holtmann 
5455c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
5465c1a4c8fSJaganath Kanakkassery 
547eac83dc6SMarcel Holtmann 	if (!status) {
548eac83dc6SMarcel Holtmann 		if (sent->support)
549eac83dc6SMarcel Holtmann 			hdev->features[1][0] |= LMP_HOST_SC;
550eac83dc6SMarcel Holtmann 		else
551eac83dc6SMarcel Holtmann 			hdev->features[1][0] &= ~LMP_HOST_SC;
552eac83dc6SMarcel Holtmann 	}
553eac83dc6SMarcel Holtmann 
554d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT) && !status) {
555eac83dc6SMarcel Holtmann 		if (sent->support)
556a1536da2SMarcel Holtmann 			hci_dev_set_flag(hdev, HCI_SC_ENABLED);
557eac83dc6SMarcel Holtmann 		else
558a358dc11SMarcel Holtmann 			hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
559eac83dc6SMarcel Holtmann 	}
5605c1a4c8fSJaganath Kanakkassery 
5615c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
562eac83dc6SMarcel Holtmann }
563eac83dc6SMarcel Holtmann 
564a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
565a9de9248SMarcel Holtmann {
566a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5671143e5a6SMarcel Holtmann 
5689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5691143e5a6SMarcel Holtmann 
570a9de9248SMarcel Holtmann 	if (rp->status)
57142c6b129SJohan Hedberg 		return;
5721143e5a6SMarcel Holtmann 
573d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
574d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hdev, HCI_CONFIG)) {
575a9de9248SMarcel Holtmann 		hdev->hci_ver = rp->hci_ver;
576e4e8e37cSMarcel Holtmann 		hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
577d5859e22SJohan Hedberg 		hdev->lmp_ver = rp->lmp_ver;
578e4e8e37cSMarcel Holtmann 		hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
579d5859e22SJohan Hedberg 		hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5800d5551f5SMarcel Holtmann 	}
581d5859e22SJohan Hedberg }
582d5859e22SJohan Hedberg 
5838fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
5848fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
585a9de9248SMarcel Holtmann {
586a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
587a9de9248SMarcel Holtmann 
5889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
589a9de9248SMarcel Holtmann 
5906a070e6eSMarcel Holtmann 	if (rp->status)
5916a070e6eSMarcel Holtmann 		return;
5926a070e6eSMarcel Holtmann 
593d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
594d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hdev, HCI_CONFIG))
595a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
596a9de9248SMarcel Holtmann }
597a9de9248SMarcel Holtmann 
598302975cbSSpoorthi Ravishankar Koppad static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev,
599302975cbSSpoorthi Ravishankar Koppad 					     struct sk_buff *skb)
600302975cbSSpoorthi Ravishankar Koppad {
601302975cbSSpoorthi Ravishankar Koppad 	struct hci_rp_read_auth_payload_to *rp = (void *)skb->data;
602302975cbSSpoorthi Ravishankar Koppad 	struct hci_conn *conn;
603302975cbSSpoorthi Ravishankar Koppad 
604302975cbSSpoorthi Ravishankar Koppad 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
605302975cbSSpoorthi Ravishankar Koppad 
606302975cbSSpoorthi Ravishankar Koppad 	if (rp->status)
607302975cbSSpoorthi Ravishankar Koppad 		return;
608302975cbSSpoorthi Ravishankar Koppad 
609302975cbSSpoorthi Ravishankar Koppad 	hci_dev_lock(hdev);
610302975cbSSpoorthi Ravishankar Koppad 
611302975cbSSpoorthi Ravishankar Koppad 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
612302975cbSSpoorthi Ravishankar Koppad 	if (conn)
613302975cbSSpoorthi Ravishankar Koppad 		conn->auth_payload_timeout = __le16_to_cpu(rp->timeout);
614302975cbSSpoorthi Ravishankar Koppad 
615302975cbSSpoorthi Ravishankar Koppad 	hci_dev_unlock(hdev);
616302975cbSSpoorthi Ravishankar Koppad }
617302975cbSSpoorthi Ravishankar Koppad 
618302975cbSSpoorthi Ravishankar Koppad static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev,
619302975cbSSpoorthi Ravishankar Koppad 					      struct sk_buff *skb)
620302975cbSSpoorthi Ravishankar Koppad {
621302975cbSSpoorthi Ravishankar Koppad 	struct hci_rp_write_auth_payload_to *rp = (void *)skb->data;
622302975cbSSpoorthi Ravishankar Koppad 	struct hci_conn *conn;
623302975cbSSpoorthi Ravishankar Koppad 	void *sent;
624302975cbSSpoorthi Ravishankar Koppad 
625302975cbSSpoorthi Ravishankar Koppad 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
626302975cbSSpoorthi Ravishankar Koppad 
627302975cbSSpoorthi Ravishankar Koppad 	if (rp->status)
628302975cbSSpoorthi Ravishankar Koppad 		return;
629302975cbSSpoorthi Ravishankar Koppad 
630302975cbSSpoorthi Ravishankar Koppad 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO);
631302975cbSSpoorthi Ravishankar Koppad 	if (!sent)
632302975cbSSpoorthi Ravishankar Koppad 		return;
633302975cbSSpoorthi Ravishankar Koppad 
634302975cbSSpoorthi Ravishankar Koppad 	hci_dev_lock(hdev);
635302975cbSSpoorthi Ravishankar Koppad 
636302975cbSSpoorthi Ravishankar Koppad 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
637302975cbSSpoorthi Ravishankar Koppad 	if (conn)
638302975cbSSpoorthi Ravishankar Koppad 		conn->auth_payload_timeout = get_unaligned_le16(sent + 2);
639302975cbSSpoorthi Ravishankar Koppad 
640302975cbSSpoorthi Ravishankar Koppad 	hci_dev_unlock(hdev);
641302975cbSSpoorthi Ravishankar Koppad }
642302975cbSSpoorthi Ravishankar Koppad 
6438fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
6448fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
645a9de9248SMarcel Holtmann {
646a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
647a9de9248SMarcel Holtmann 
6489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
649a9de9248SMarcel Holtmann 
650a9de9248SMarcel Holtmann 	if (rp->status)
651a9de9248SMarcel Holtmann 		return;
652a9de9248SMarcel Holtmann 
653a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6541da177e4SLinus Torvalds 
6551da177e4SLinus Torvalds 	/* Adjust default settings according to features
6561da177e4SLinus Torvalds 	 * supported by device. */
657a9de9248SMarcel Holtmann 
658cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_3SLOT)
6591da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6601da177e4SLinus Torvalds 
661cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_5SLOT)
6621da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6631da177e4SLinus Torvalds 
664cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV2) {
6651da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6665b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6675b7f9909SMarcel Holtmann 	}
6681da177e4SLinus Torvalds 
669cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV3) {
6701da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6715b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6725b7f9909SMarcel Holtmann 	}
6735b7f9909SMarcel Holtmann 
67445db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
6755b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6765b7f9909SMarcel Holtmann 
677cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV4)
6785b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6795b7f9909SMarcel Holtmann 
680cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV5)
6815b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6821da177e4SLinus Torvalds 
683cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
684efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
685efc7688bSMarcel Holtmann 
686cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
687efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
688efc7688bSMarcel Holtmann 
689cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
690efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
6911da177e4SLinus Torvalds }
6921da177e4SLinus Torvalds 
693971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
694971e3a4bSAndre Guedes 					   struct sk_buff *skb)
695971e3a4bSAndre Guedes {
696971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
697971e3a4bSAndre Guedes 
6989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
699971e3a4bSAndre Guedes 
700971e3a4bSAndre Guedes 	if (rp->status)
70142c6b129SJohan Hedberg 		return;
702971e3a4bSAndre Guedes 
70357af75a8SMarcel Holtmann 	if (hdev->max_page < rp->max_page)
704d2c5d77fSJohan Hedberg 		hdev->max_page = rp->max_page;
705d2c5d77fSJohan Hedberg 
706cad718edSJohan Hedberg 	if (rp->page < HCI_MAX_PAGES)
707cad718edSJohan Hedberg 		memcpy(hdev->features[rp->page], rp->features, 8);
708971e3a4bSAndre Guedes }
709971e3a4bSAndre Guedes 
7101e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7111e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
7121e89cffbSAndrei Emeltchenko {
7131e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7141e89cffbSAndrei Emeltchenko 
7159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
7161e89cffbSAndrei Emeltchenko 
71745296acdSMarcel Holtmann 	if (rp->status)
71845296acdSMarcel Holtmann 		return;
71945296acdSMarcel Holtmann 
7201e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7211e89cffbSAndrei Emeltchenko }
7221e89cffbSAndrei Emeltchenko 
723a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
724a9de9248SMarcel Holtmann {
725a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
726a9de9248SMarcel Holtmann 
7279f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
728a9de9248SMarcel Holtmann 
729a9de9248SMarcel Holtmann 	if (rp->status)
730a9de9248SMarcel Holtmann 		return;
731a9de9248SMarcel Holtmann 
732a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
733a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
734a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
735a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
736da1f5198SMarcel Holtmann 
737da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
738da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
739da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
740da1f5198SMarcel Holtmann 	}
741da1f5198SMarcel Holtmann 
742da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
743da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7441da177e4SLinus Torvalds 
745807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
746807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
7471da177e4SLinus Torvalds }
7481da177e4SLinus Torvalds 
749a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
750a9de9248SMarcel Holtmann {
751a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
7521da177e4SLinus Torvalds 
7539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
754a9de9248SMarcel Holtmann 
755e30d3f5fSMarcel Holtmann 	if (rp->status)
756e30d3f5fSMarcel Holtmann 		return;
757e30d3f5fSMarcel Holtmann 
758e30d3f5fSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
759a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
760e30d3f5fSMarcel Holtmann 
761d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP))
762e30d3f5fSMarcel Holtmann 		bacpy(&hdev->setup_addr, &rp->bdaddr);
76323bb5763SJohan Hedberg }
76423bb5763SJohan Hedberg 
765a4790360SMarcel Holtmann static void hci_cc_read_local_pairing_opts(struct hci_dev *hdev,
766a4790360SMarcel Holtmann 					   struct sk_buff *skb)
767a4790360SMarcel Holtmann {
768a4790360SMarcel Holtmann 	struct hci_rp_read_local_pairing_opts *rp = (void *) skb->data;
769a4790360SMarcel Holtmann 
770a4790360SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
771a4790360SMarcel Holtmann 
772a4790360SMarcel Holtmann 	if (rp->status)
773a4790360SMarcel Holtmann 		return;
774a4790360SMarcel Holtmann 
775a4790360SMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
776a4790360SMarcel Holtmann 	    hci_dev_test_flag(hdev, HCI_CONFIG)) {
777a4790360SMarcel Holtmann 		hdev->pairing_opts = rp->pairing_opts;
778a4790360SMarcel Holtmann 		hdev->max_enc_key_size = rp->max_key_size;
779a4790360SMarcel Holtmann 	}
780a4790360SMarcel Holtmann }
781a4790360SMarcel Holtmann 
782f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
783f332ec66SJohan Hedberg 					   struct sk_buff *skb)
784f332ec66SJohan Hedberg {
785f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
786f332ec66SJohan Hedberg 
787f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
788f332ec66SJohan Hedberg 
78945296acdSMarcel Holtmann 	if (rp->status)
79045296acdSMarcel Holtmann 		return;
79145296acdSMarcel Holtmann 
79245296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags)) {
793f332ec66SJohan Hedberg 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
794f332ec66SJohan Hedberg 		hdev->page_scan_window = __le16_to_cpu(rp->window);
795f332ec66SJohan Hedberg 	}
796f332ec66SJohan Hedberg }
797f332ec66SJohan Hedberg 
7984a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
7994a3ee763SJohan Hedberg 					    struct sk_buff *skb)
8004a3ee763SJohan Hedberg {
8014a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
8024a3ee763SJohan Hedberg 	struct hci_cp_write_page_scan_activity *sent;
8034a3ee763SJohan Hedberg 
8044a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
8054a3ee763SJohan Hedberg 
8064a3ee763SJohan Hedberg 	if (status)
8074a3ee763SJohan Hedberg 		return;
8084a3ee763SJohan Hedberg 
8094a3ee763SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
8104a3ee763SJohan Hedberg 	if (!sent)
8114a3ee763SJohan Hedberg 		return;
8124a3ee763SJohan Hedberg 
8134a3ee763SJohan Hedberg 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
8144a3ee763SJohan Hedberg 	hdev->page_scan_window = __le16_to_cpu(sent->window);
8154a3ee763SJohan Hedberg }
8164a3ee763SJohan Hedberg 
817f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
818f332ec66SJohan Hedberg 					   struct sk_buff *skb)
819f332ec66SJohan Hedberg {
820f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
821f332ec66SJohan Hedberg 
822f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
823f332ec66SJohan Hedberg 
82445296acdSMarcel Holtmann 	if (rp->status)
82545296acdSMarcel Holtmann 		return;
82645296acdSMarcel Holtmann 
82745296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
828f332ec66SJohan Hedberg 		hdev->page_scan_type = rp->type;
829f332ec66SJohan Hedberg }
830f332ec66SJohan Hedberg 
8314a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
8324a3ee763SJohan Hedberg 					struct sk_buff *skb)
8334a3ee763SJohan Hedberg {
8344a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
8354a3ee763SJohan Hedberg 	u8 *type;
8364a3ee763SJohan Hedberg 
8374a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
8384a3ee763SJohan Hedberg 
8394a3ee763SJohan Hedberg 	if (status)
8404a3ee763SJohan Hedberg 		return;
8414a3ee763SJohan Hedberg 
8424a3ee763SJohan Hedberg 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
8434a3ee763SJohan Hedberg 	if (type)
8444a3ee763SJohan Hedberg 		hdev->page_scan_type = *type;
8454a3ee763SJohan Hedberg }
8464a3ee763SJohan Hedberg 
847350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
848350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
849350ee4cfSAndrei Emeltchenko {
850350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
851350ee4cfSAndrei Emeltchenko 
8529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
853350ee4cfSAndrei Emeltchenko 
854350ee4cfSAndrei Emeltchenko 	if (rp->status)
855350ee4cfSAndrei Emeltchenko 		return;
856350ee4cfSAndrei Emeltchenko 
857350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
858350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
859350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
860350ee4cfSAndrei Emeltchenko 
861350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
862350ee4cfSAndrei Emeltchenko 
863350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
864350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
865350ee4cfSAndrei Emeltchenko }
866350ee4cfSAndrei Emeltchenko 
86733f35721SJohan Hedberg static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb)
86833f35721SJohan Hedberg {
86933f35721SJohan Hedberg 	struct hci_rp_read_clock *rp = (void *) skb->data;
87033f35721SJohan Hedberg 	struct hci_cp_read_clock *cp;
87133f35721SJohan Hedberg 	struct hci_conn *conn;
87233f35721SJohan Hedberg 
87333f35721SJohan Hedberg 	BT_DBG("%s", hdev->name);
87433f35721SJohan Hedberg 
87533f35721SJohan Hedberg 	if (skb->len < sizeof(*rp))
87633f35721SJohan Hedberg 		return;
87733f35721SJohan Hedberg 
87833f35721SJohan Hedberg 	if (rp->status)
87933f35721SJohan Hedberg 		return;
88033f35721SJohan Hedberg 
88133f35721SJohan Hedberg 	hci_dev_lock(hdev);
88233f35721SJohan Hedberg 
88333f35721SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
88433f35721SJohan Hedberg 	if (!cp)
88533f35721SJohan Hedberg 		goto unlock;
88633f35721SJohan Hedberg 
88733f35721SJohan Hedberg 	if (cp->which == 0x00) {
88833f35721SJohan Hedberg 		hdev->clock = le32_to_cpu(rp->clock);
88933f35721SJohan Hedberg 		goto unlock;
89033f35721SJohan Hedberg 	}
89133f35721SJohan Hedberg 
89233f35721SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
89333f35721SJohan Hedberg 	if (conn) {
89433f35721SJohan Hedberg 		conn->clock = le32_to_cpu(rp->clock);
89533f35721SJohan Hedberg 		conn->clock_accuracy = le16_to_cpu(rp->accuracy);
89633f35721SJohan Hedberg 	}
89733f35721SJohan Hedberg 
89833f35721SJohan Hedberg unlock:
89933f35721SJohan Hedberg 	hci_dev_unlock(hdev);
90033f35721SJohan Hedberg }
90133f35721SJohan Hedberg 
902928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
903928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
904928abaa7SAndrei Emeltchenko {
905928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
906928abaa7SAndrei Emeltchenko 
9079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
908928abaa7SAndrei Emeltchenko 
909928abaa7SAndrei Emeltchenko 	if (rp->status)
91083927882SArron Wang 		return;
911928abaa7SAndrei Emeltchenko 
912928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
913928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
914928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
915928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
916928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
917928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
918928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
919928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
920928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
921928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
922928abaa7SAndrei Emeltchenko }
923928abaa7SAndrei Emeltchenko 
924d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
925d5859e22SJohan Hedberg 					 struct sk_buff *skb)
926d5859e22SJohan Hedberg {
92791c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
928d5859e22SJohan Hedberg 
9299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
930d5859e22SJohan Hedberg 
93145296acdSMarcel Holtmann 	if (rp->status)
93245296acdSMarcel Holtmann 		return;
93345296acdSMarcel Holtmann 
93491c4e9b1SMarcel Holtmann 	hdev->inq_tx_power = rp->tx_power;
935d5859e22SJohan Hedberg }
936d5859e22SJohan Hedberg 
93700bce3fbSAlain Michaud static void hci_cc_read_def_err_data_reporting(struct hci_dev *hdev,
93800bce3fbSAlain Michaud 					       struct sk_buff *skb)
93900bce3fbSAlain Michaud {
94000bce3fbSAlain Michaud 	struct hci_rp_read_def_err_data_reporting *rp = (void *)skb->data;
94100bce3fbSAlain Michaud 
94200bce3fbSAlain Michaud 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
94300bce3fbSAlain Michaud 
94400bce3fbSAlain Michaud 	if (rp->status)
94500bce3fbSAlain Michaud 		return;
94600bce3fbSAlain Michaud 
94700bce3fbSAlain Michaud 	hdev->err_data_reporting = rp->err_data_reporting;
94800bce3fbSAlain Michaud }
94900bce3fbSAlain Michaud 
95000bce3fbSAlain Michaud static void hci_cc_write_def_err_data_reporting(struct hci_dev *hdev,
95100bce3fbSAlain Michaud 						struct sk_buff *skb)
95200bce3fbSAlain Michaud {
95300bce3fbSAlain Michaud 	__u8 status = *((__u8 *)skb->data);
95400bce3fbSAlain Michaud 	struct hci_cp_write_def_err_data_reporting *cp;
95500bce3fbSAlain Michaud 
95600bce3fbSAlain Michaud 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
95700bce3fbSAlain Michaud 
95800bce3fbSAlain Michaud 	if (status)
95900bce3fbSAlain Michaud 		return;
96000bce3fbSAlain Michaud 
96100bce3fbSAlain Michaud 	cp = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING);
96200bce3fbSAlain Michaud 	if (!cp)
96300bce3fbSAlain Michaud 		return;
96400bce3fbSAlain Michaud 
96500bce3fbSAlain Michaud 	hdev->err_data_reporting = cp->err_data_reporting;
96600bce3fbSAlain Michaud }
96700bce3fbSAlain Michaud 
968980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
969980e1a53SJohan Hedberg {
970980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
971980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
972980e1a53SJohan Hedberg 	struct hci_conn *conn;
973980e1a53SJohan Hedberg 
9749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
975980e1a53SJohan Hedberg 
97656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
97756e5cb86SJohan Hedberg 
978d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
979744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
980980e1a53SJohan Hedberg 
981fa1bd918SMikel Astiz 	if (rp->status)
98256e5cb86SJohan Hedberg 		goto unlock;
983980e1a53SJohan Hedberg 
984980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
985980e1a53SJohan Hedberg 	if (!cp)
98656e5cb86SJohan Hedberg 		goto unlock;
987980e1a53SJohan Hedberg 
988980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
989980e1a53SJohan Hedberg 	if (conn)
990980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
99156e5cb86SJohan Hedberg 
99256e5cb86SJohan Hedberg unlock:
99356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
994980e1a53SJohan Hedberg }
995980e1a53SJohan Hedberg 
996980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
997980e1a53SJohan Hedberg {
998980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
999980e1a53SJohan Hedberg 
10009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1001980e1a53SJohan Hedberg 
100256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
100356e5cb86SJohan Hedberg 
1004d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
1005744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
1006980e1a53SJohan Hedberg 						 rp->status);
100756e5cb86SJohan Hedberg 
100856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1009980e1a53SJohan Hedberg }
101056e5cb86SJohan Hedberg 
10116ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
10126ed58ec5SVille Tervo 				       struct sk_buff *skb)
10136ed58ec5SVille Tervo {
10146ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
10156ed58ec5SVille Tervo 
10169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10176ed58ec5SVille Tervo 
10186ed58ec5SVille Tervo 	if (rp->status)
10196ed58ec5SVille Tervo 		return;
10206ed58ec5SVille Tervo 
10216ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
10226ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
10236ed58ec5SVille Tervo 
10246ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
10256ed58ec5SVille Tervo 
10266ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
10276ed58ec5SVille Tervo }
1028980e1a53SJohan Hedberg 
102960e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
103060e77321SJohan Hedberg 					  struct sk_buff *skb)
103160e77321SJohan Hedberg {
103260e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
103360e77321SJohan Hedberg 
103460e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
103560e77321SJohan Hedberg 
103645296acdSMarcel Holtmann 	if (rp->status)
103745296acdSMarcel Holtmann 		return;
103845296acdSMarcel Holtmann 
103960e77321SJohan Hedberg 	memcpy(hdev->le_features, rp->features, 8);
104060e77321SJohan Hedberg }
104160e77321SJohan Hedberg 
10428fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
10438fa19098SJohan Hedberg 					struct sk_buff *skb)
10448fa19098SJohan Hedberg {
10458fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
10468fa19098SJohan Hedberg 
10478fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10488fa19098SJohan Hedberg 
104945296acdSMarcel Holtmann 	if (rp->status)
105045296acdSMarcel Holtmann 		return;
105145296acdSMarcel Holtmann 
10528fa19098SJohan Hedberg 	hdev->adv_tx_power = rp->tx_power;
10538fa19098SJohan Hedberg }
10548fa19098SJohan Hedberg 
1055a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1056a5c29683SJohan Hedberg {
1057a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1058a5c29683SJohan Hedberg 
10599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1060a5c29683SJohan Hedberg 
106156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
106256e5cb86SJohan Hedberg 
1063d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
106404124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
106504124681SGustavo F. Padovan 						 rp->status);
106656e5cb86SJohan Hedberg 
106756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1068a5c29683SJohan Hedberg }
1069a5c29683SJohan Hedberg 
1070a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
1071a5c29683SJohan Hedberg 					  struct sk_buff *skb)
1072a5c29683SJohan Hedberg {
1073a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1074a5c29683SJohan Hedberg 
10759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1076a5c29683SJohan Hedberg 
107756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
107856e5cb86SJohan Hedberg 
1079d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
1080744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
108104124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
108256e5cb86SJohan Hedberg 
108356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1084a5c29683SJohan Hedberg }
1085a5c29683SJohan Hedberg 
10861143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
10871143d458SBrian Gix {
10881143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10891143d458SBrian Gix 
10909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10911143d458SBrian Gix 
10921143d458SBrian Gix 	hci_dev_lock(hdev);
10931143d458SBrian Gix 
1094d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
1095272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1096272d90dfSJohan Hedberg 						 0, rp->status);
10971143d458SBrian Gix 
10981143d458SBrian Gix 	hci_dev_unlock(hdev);
10991143d458SBrian Gix }
11001143d458SBrian Gix 
11011143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
11021143d458SBrian Gix 					  struct sk_buff *skb)
11031143d458SBrian Gix {
11041143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
11051143d458SBrian Gix 
11069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
11071143d458SBrian Gix 
11081143d458SBrian Gix 	hci_dev_lock(hdev);
11091143d458SBrian Gix 
1110d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
11111143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
111204124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
11131143d458SBrian Gix 
11141143d458SBrian Gix 	hci_dev_unlock(hdev);
11151143d458SBrian Gix }
11161143d458SBrian Gix 
11174d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
1118c35938b2SSzymon Janc 				       struct sk_buff *skb)
1119c35938b2SSzymon Janc {
1120c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1121c35938b2SSzymon Janc 
11229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
11234d2d2796SMarcel Holtmann }
11244d2d2796SMarcel Holtmann 
11254d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
11264d2d2796SMarcel Holtmann 					   struct sk_buff *skb)
11274d2d2796SMarcel Holtmann {
11284d2d2796SMarcel Holtmann 	struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
11294d2d2796SMarcel Holtmann 
11304d2d2796SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1131c35938b2SSzymon Janc }
1132c35938b2SSzymon Janc 
11337a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
11347a4cd51dSMarcel Holtmann {
11357a4cd51dSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
11367a4cd51dSMarcel Holtmann 	bdaddr_t *sent;
11377a4cd51dSMarcel Holtmann 
11387a4cd51dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
11397a4cd51dSMarcel Holtmann 
114045296acdSMarcel Holtmann 	if (status)
114145296acdSMarcel Holtmann 		return;
114245296acdSMarcel Holtmann 
11437a4cd51dSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
11447a4cd51dSMarcel Holtmann 	if (!sent)
11457a4cd51dSMarcel Holtmann 		return;
11467a4cd51dSMarcel Holtmann 
11477a4cd51dSMarcel Holtmann 	hci_dev_lock(hdev);
11487a4cd51dSMarcel Holtmann 
11497a4cd51dSMarcel Holtmann 	bacpy(&hdev->random_addr, sent);
11507a4cd51dSMarcel Holtmann 
11517a4cd51dSMarcel Holtmann 	hci_dev_unlock(hdev);
11527a4cd51dSMarcel Holtmann }
11537a4cd51dSMarcel Holtmann 
11540314f286SJaganath Kanakkassery static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
11550314f286SJaganath Kanakkassery {
11560314f286SJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
11570314f286SJaganath Kanakkassery 	struct hci_cp_le_set_default_phy *cp;
11580314f286SJaganath Kanakkassery 
11590314f286SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
11600314f286SJaganath Kanakkassery 
11610314f286SJaganath Kanakkassery 	if (status)
11620314f286SJaganath Kanakkassery 		return;
11630314f286SJaganath Kanakkassery 
11640314f286SJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY);
11650314f286SJaganath Kanakkassery 	if (!cp)
11660314f286SJaganath Kanakkassery 		return;
11670314f286SJaganath Kanakkassery 
11680314f286SJaganath Kanakkassery 	hci_dev_lock(hdev);
11690314f286SJaganath Kanakkassery 
11700314f286SJaganath Kanakkassery 	hdev->le_tx_def_phys = cp->tx_phys;
11710314f286SJaganath Kanakkassery 	hdev->le_rx_def_phys = cp->rx_phys;
11720314f286SJaganath Kanakkassery 
11730314f286SJaganath Kanakkassery 	hci_dev_unlock(hdev);
11740314f286SJaganath Kanakkassery }
11750314f286SJaganath Kanakkassery 
1176a73c046aSJaganath Kanakkassery static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
1177a73c046aSJaganath Kanakkassery                                               struct sk_buff *skb)
1178a73c046aSJaganath Kanakkassery {
1179a73c046aSJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
1180a73c046aSJaganath Kanakkassery 	struct hci_cp_le_set_adv_set_rand_addr *cp;
1181a73c046aSJaganath Kanakkassery 	struct adv_info *adv_instance;
1182a73c046aSJaganath Kanakkassery 
1183a73c046aSJaganath Kanakkassery 	if (status)
1184a73c046aSJaganath Kanakkassery 		return;
1185a73c046aSJaganath Kanakkassery 
1186a73c046aSJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR);
1187a73c046aSJaganath Kanakkassery 	if (!cp)
1188a73c046aSJaganath Kanakkassery 		return;
1189a73c046aSJaganath Kanakkassery 
1190a73c046aSJaganath Kanakkassery 	hci_dev_lock(hdev);
1191a73c046aSJaganath Kanakkassery 
1192a73c046aSJaganath Kanakkassery 	if (!hdev->cur_adv_instance) {
1193a73c046aSJaganath Kanakkassery 		/* Store in hdev for instance 0 (Set adv and Directed advs) */
1194a73c046aSJaganath Kanakkassery 		bacpy(&hdev->random_addr, &cp->bdaddr);
1195a73c046aSJaganath Kanakkassery 	} else {
1196a73c046aSJaganath Kanakkassery 		adv_instance = hci_find_adv_instance(hdev,
1197a73c046aSJaganath Kanakkassery 						     hdev->cur_adv_instance);
1198a73c046aSJaganath Kanakkassery 		if (adv_instance)
1199a73c046aSJaganath Kanakkassery 			bacpy(&adv_instance->random_addr, &cp->bdaddr);
1200a73c046aSJaganath Kanakkassery 	}
1201a73c046aSJaganath Kanakkassery 
1202a73c046aSJaganath Kanakkassery 	hci_dev_unlock(hdev);
1203a73c046aSJaganath Kanakkassery }
1204a73c046aSJaganath Kanakkassery 
1205c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1206c1d5dc4aSJohan Hedberg {
1207c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
1208c1d5dc4aSJohan Hedberg 
1209c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1210c1d5dc4aSJohan Hedberg 
121145296acdSMarcel Holtmann 	if (status)
1212c1d5dc4aSJohan Hedberg 		return;
1213c1d5dc4aSJohan Hedberg 
121445296acdSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
121545296acdSMarcel Holtmann 	if (!sent)
12163c857757SJohan Hedberg 		return;
12173c857757SJohan Hedberg 
1218c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
1219c1d5dc4aSJohan Hedberg 
122049c922bbSStephen Hemminger 	/* If we're doing connection initiation as peripheral. Set a
12213c857757SJohan Hedberg 	 * timeout in case something goes wrong.
12223c857757SJohan Hedberg 	 */
12233c857757SJohan Hedberg 	if (*sent) {
12243c857757SJohan Hedberg 		struct hci_conn *conn;
12253c857757SJohan Hedberg 
1226a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_LE_ADV);
122766c417c1SJohan Hedberg 
1228e7d9ab73SJakub Pawlowski 		conn = hci_lookup_le_connect(hdev);
12293c857757SJohan Hedberg 		if (conn)
12303c857757SJohan Hedberg 			queue_delayed_work(hdev->workqueue,
12313c857757SJohan Hedberg 					   &conn->le_conn_timeout,
123209ae260bSJohan Hedberg 					   conn->conn_timeout);
123366c417c1SJohan Hedberg 	} else {
1234a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_LE_ADV);
12353c857757SJohan Hedberg 	}
12363c857757SJohan Hedberg 
123704b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
1238c1d5dc4aSJohan Hedberg }
1239c1d5dc4aSJohan Hedberg 
1240de181e88SJaganath Kanakkassery static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
1241de181e88SJaganath Kanakkassery 					 struct sk_buff *skb)
1242de181e88SJaganath Kanakkassery {
1243de181e88SJaganath Kanakkassery 	struct hci_cp_le_set_ext_adv_enable *cp;
1244de181e88SJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
1245de181e88SJaganath Kanakkassery 
1246de181e88SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1247de181e88SJaganath Kanakkassery 
1248de181e88SJaganath Kanakkassery 	if (status)
1249de181e88SJaganath Kanakkassery 		return;
1250de181e88SJaganath Kanakkassery 
1251de181e88SJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE);
1252de181e88SJaganath Kanakkassery 	if (!cp)
1253de181e88SJaganath Kanakkassery 		return;
1254de181e88SJaganath Kanakkassery 
1255de181e88SJaganath Kanakkassery 	hci_dev_lock(hdev);
1256de181e88SJaganath Kanakkassery 
1257de181e88SJaganath Kanakkassery 	if (cp->enable) {
1258de181e88SJaganath Kanakkassery 		struct hci_conn *conn;
1259de181e88SJaganath Kanakkassery 
1260de181e88SJaganath Kanakkassery 		hci_dev_set_flag(hdev, HCI_LE_ADV);
1261de181e88SJaganath Kanakkassery 
1262de181e88SJaganath Kanakkassery 		conn = hci_lookup_le_connect(hdev);
1263de181e88SJaganath Kanakkassery 		if (conn)
1264de181e88SJaganath Kanakkassery 			queue_delayed_work(hdev->workqueue,
1265de181e88SJaganath Kanakkassery 					   &conn->le_conn_timeout,
1266de181e88SJaganath Kanakkassery 					   conn->conn_timeout);
126745b7749fSJaganath Kanakkassery 	} else {
126845b7749fSJaganath Kanakkassery 		hci_dev_clear_flag(hdev, HCI_LE_ADV);
1269de181e88SJaganath Kanakkassery 	}
1270de181e88SJaganath Kanakkassery 
1271de181e88SJaganath Kanakkassery 	hci_dev_unlock(hdev);
1272de181e88SJaganath Kanakkassery }
1273de181e88SJaganath Kanakkassery 
1274533553f8SMarcel Holtmann static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1275533553f8SMarcel Holtmann {
1276533553f8SMarcel Holtmann 	struct hci_cp_le_set_scan_param *cp;
1277533553f8SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1278533553f8SMarcel Holtmann 
1279533553f8SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1280533553f8SMarcel Holtmann 
128145296acdSMarcel Holtmann 	if (status)
128245296acdSMarcel Holtmann 		return;
128345296acdSMarcel Holtmann 
1284533553f8SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM);
1285533553f8SMarcel Holtmann 	if (!cp)
1286533553f8SMarcel Holtmann 		return;
1287533553f8SMarcel Holtmann 
1288533553f8SMarcel Holtmann 	hci_dev_lock(hdev);
1289533553f8SMarcel Holtmann 
1290533553f8SMarcel Holtmann 	hdev->le_scan_type = cp->type;
1291533553f8SMarcel Holtmann 
1292533553f8SMarcel Holtmann 	hci_dev_unlock(hdev);
1293533553f8SMarcel Holtmann }
1294533553f8SMarcel Holtmann 
1295a2344b9eSJaganath Kanakkassery static void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev,
1296a2344b9eSJaganath Kanakkassery 					 struct sk_buff *skb)
1297a2344b9eSJaganath Kanakkassery {
1298a2344b9eSJaganath Kanakkassery 	struct hci_cp_le_set_ext_scan_params *cp;
1299a2344b9eSJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
1300a2344b9eSJaganath Kanakkassery 	struct hci_cp_le_scan_phy_params *phy_param;
1301a2344b9eSJaganath Kanakkassery 
1302a2344b9eSJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1303a2344b9eSJaganath Kanakkassery 
1304a2344b9eSJaganath Kanakkassery 	if (status)
1305a2344b9eSJaganath Kanakkassery 		return;
1306a2344b9eSJaganath Kanakkassery 
1307a2344b9eSJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS);
1308a2344b9eSJaganath Kanakkassery 	if (!cp)
1309a2344b9eSJaganath Kanakkassery 		return;
1310a2344b9eSJaganath Kanakkassery 
1311a2344b9eSJaganath Kanakkassery 	phy_param = (void *)cp->data;
1312a2344b9eSJaganath Kanakkassery 
1313a2344b9eSJaganath Kanakkassery 	hci_dev_lock(hdev);
1314a2344b9eSJaganath Kanakkassery 
1315a2344b9eSJaganath Kanakkassery 	hdev->le_scan_type = phy_param->type;
1316a2344b9eSJaganath Kanakkassery 
1317a2344b9eSJaganath Kanakkassery 	hci_dev_unlock(hdev);
1318a2344b9eSJaganath Kanakkassery }
1319a2344b9eSJaganath Kanakkassery 
1320b9a6328fSJohan Hedberg static bool has_pending_adv_report(struct hci_dev *hdev)
1321b9a6328fSJohan Hedberg {
1322b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1323b9a6328fSJohan Hedberg 
1324b9a6328fSJohan Hedberg 	return bacmp(&d->last_adv_addr, BDADDR_ANY);
1325b9a6328fSJohan Hedberg }
1326b9a6328fSJohan Hedberg 
1327b9a6328fSJohan Hedberg static void clear_pending_adv_report(struct hci_dev *hdev)
1328b9a6328fSJohan Hedberg {
1329b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1330b9a6328fSJohan Hedberg 
1331b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, BDADDR_ANY);
1332b9a6328fSJohan Hedberg 	d->last_adv_data_len = 0;
1333b9a6328fSJohan Hedberg }
1334b9a6328fSJohan Hedberg 
1335b9a6328fSJohan Hedberg static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
1336c70a7e4cSMarcel Holtmann 				     u8 bdaddr_type, s8 rssi, u32 flags,
1337c70a7e4cSMarcel Holtmann 				     u8 *data, u8 len)
1338b9a6328fSJohan Hedberg {
1339b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1340b9a6328fSJohan Hedberg 
1341b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, bdaddr);
1342b9a6328fSJohan Hedberg 	d->last_adv_addr_type = bdaddr_type;
1343ff5cd29fSJohan Hedberg 	d->last_adv_rssi = rssi;
1344c70a7e4cSMarcel Holtmann 	d->last_adv_flags = flags;
1345b9a6328fSJohan Hedberg 	memcpy(d->last_adv_data, data, len);
1346b9a6328fSJohan Hedberg 	d->last_adv_data_len = len;
1347b9a6328fSJohan Hedberg }
1348b9a6328fSJohan Hedberg 
13493baef810SJaganath Kanakkassery static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable)
1350eb9d91f5SAndre Guedes {
13515c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
13525c1a4c8fSJaganath Kanakkassery 
13533baef810SJaganath Kanakkassery 	switch (enable) {
13543fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
1355a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_LE_SCAN);
1356b9a6328fSJohan Hedberg 		if (hdev->le_scan_type == LE_SCAN_ACTIVE)
1357b9a6328fSJohan Hedberg 			clear_pending_adv_report(hdev);
135868a8aea4SAndrei Emeltchenko 		break;
135968a8aea4SAndrei Emeltchenko 
136076a388beSAndre Guedes 	case LE_SCAN_DISABLE:
1361b9a6328fSJohan Hedberg 		/* We do this here instead of when setting DISCOVERY_STOPPED
1362b9a6328fSJohan Hedberg 		 * since the latter would potentially require waiting for
1363b9a6328fSJohan Hedberg 		 * inquiry to stop too.
1364b9a6328fSJohan Hedberg 		 */
1365b9a6328fSJohan Hedberg 		if (has_pending_adv_report(hdev)) {
1366b9a6328fSJohan Hedberg 			struct discovery_state *d = &hdev->discovery;
1367b9a6328fSJohan Hedberg 
1368b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
1369ab0aa433SJohan Hedberg 					  d->last_adv_addr_type, NULL,
1370c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
1371ab0aa433SJohan Hedberg 					  d->last_adv_data,
1372b9a6328fSJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
1373b9a6328fSJohan Hedberg 		}
1374b9a6328fSJohan Hedberg 
1375317ac8cbSJohan Hedberg 		/* Cancel this timer so that we don't try to disable scanning
1376317ac8cbSJohan Hedberg 		 * when it's already disabled.
1377317ac8cbSJohan Hedberg 		 */
1378317ac8cbSJohan Hedberg 		cancel_delayed_work(&hdev->le_scan_disable);
1379317ac8cbSJohan Hedberg 
1380a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_LE_SCAN);
1381e8bb6b97SJohan Hedberg 
138281ad6fd9SJohan Hedberg 		/* The HCI_LE_SCAN_INTERRUPTED flag indicates that we
138381ad6fd9SJohan Hedberg 		 * interrupted scanning due to a connect request. Mark
1384e8bb6b97SJohan Hedberg 		 * therefore discovery as stopped. If this was not
1385e8bb6b97SJohan Hedberg 		 * because of a connect request advertising might have
1386e8bb6b97SJohan Hedberg 		 * been disabled because of active scanning, so
1387e8bb6b97SJohan Hedberg 		 * re-enable it again if necessary.
138881ad6fd9SJohan Hedberg 		 */
1389a69d8927SMarcel Holtmann 		if (hci_dev_test_and_clear_flag(hdev, HCI_LE_SCAN_INTERRUPTED))
139081ad6fd9SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1391d7a5a11dSMarcel Holtmann 		else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) &&
139234722277SJohan Hedberg 			 hdev->discovery.state == DISCOVERY_FINDING)
1393f2252570SJohan Hedberg 			hci_req_reenable_advertising(hdev);
1394e8bb6b97SJohan Hedberg 
139568a8aea4SAndrei Emeltchenko 		break;
139668a8aea4SAndrei Emeltchenko 
139768a8aea4SAndrei Emeltchenko 	default:
13982064ee33SMarcel Holtmann 		bt_dev_err(hdev, "use of reserved LE_Scan_Enable param %d",
13993baef810SJaganath Kanakkassery 			   enable);
140068a8aea4SAndrei Emeltchenko 		break;
140135815085SAndre Guedes 	}
14025c1a4c8fSJaganath Kanakkassery 
14035c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
1404eb9d91f5SAndre Guedes }
1405eb9d91f5SAndre Guedes 
14063baef810SJaganath Kanakkassery static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
14073baef810SJaganath Kanakkassery 				      struct sk_buff *skb)
14083baef810SJaganath Kanakkassery {
14093baef810SJaganath Kanakkassery 	struct hci_cp_le_set_scan_enable *cp;
14103baef810SJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
14113baef810SJaganath Kanakkassery 
14123baef810SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
14133baef810SJaganath Kanakkassery 
14143baef810SJaganath Kanakkassery 	if (status)
14153baef810SJaganath Kanakkassery 		return;
14163baef810SJaganath Kanakkassery 
14173baef810SJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
14183baef810SJaganath Kanakkassery 	if (!cp)
14193baef810SJaganath Kanakkassery 		return;
14203baef810SJaganath Kanakkassery 
14213baef810SJaganath Kanakkassery 	le_set_scan_enable_complete(hdev, cp->enable);
14223baef810SJaganath Kanakkassery }
14233baef810SJaganath Kanakkassery 
1424a2344b9eSJaganath Kanakkassery static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev,
1425a2344b9eSJaganath Kanakkassery 				      struct sk_buff *skb)
1426a2344b9eSJaganath Kanakkassery {
1427a2344b9eSJaganath Kanakkassery 	struct hci_cp_le_set_ext_scan_enable *cp;
1428a2344b9eSJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
1429a2344b9eSJaganath Kanakkassery 
1430a2344b9eSJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1431a2344b9eSJaganath Kanakkassery 
1432a2344b9eSJaganath Kanakkassery 	if (status)
1433a2344b9eSJaganath Kanakkassery 		return;
1434a2344b9eSJaganath Kanakkassery 
1435a2344b9eSJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_ENABLE);
1436a2344b9eSJaganath Kanakkassery 	if (!cp)
1437a2344b9eSJaganath Kanakkassery 		return;
1438a2344b9eSJaganath Kanakkassery 
1439a2344b9eSJaganath Kanakkassery 	le_set_scan_enable_complete(hdev, cp->enable);
1440a2344b9eSJaganath Kanakkassery }
1441a2344b9eSJaganath Kanakkassery 
14426b49bcb4SJaganath Kanakkassery static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev,
14436b49bcb4SJaganath Kanakkassery 				      struct sk_buff *skb)
14446b49bcb4SJaganath Kanakkassery {
14456b49bcb4SJaganath Kanakkassery 	struct hci_rp_le_read_num_supported_adv_sets *rp = (void *) skb->data;
14466b49bcb4SJaganath Kanakkassery 
14476b49bcb4SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x No of Adv sets %u", hdev->name, rp->status,
14486b49bcb4SJaganath Kanakkassery 	       rp->num_of_sets);
14496b49bcb4SJaganath Kanakkassery 
14506b49bcb4SJaganath Kanakkassery 	if (rp->status)
14516b49bcb4SJaganath Kanakkassery 		return;
14526b49bcb4SJaganath Kanakkassery 
14536b49bcb4SJaganath Kanakkassery 	hdev->le_num_of_adv_sets = rp->num_of_sets;
14546b49bcb4SJaganath Kanakkassery }
14556b49bcb4SJaganath Kanakkassery 
1456cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1457cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
1458cf1d081fSJohan Hedberg {
1459cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1460cf1d081fSJohan Hedberg 
1461cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1462cf1d081fSJohan Hedberg 
146345296acdSMarcel Holtmann 	if (rp->status)
146445296acdSMarcel Holtmann 		return;
146545296acdSMarcel Holtmann 
1466cf1d081fSJohan Hedberg 	hdev->le_white_list_size = rp->size;
1467cf1d081fSJohan Hedberg }
1468cf1d081fSJohan Hedberg 
14690f36b589SMarcel Holtmann static void hci_cc_le_clear_white_list(struct hci_dev *hdev,
14700f36b589SMarcel Holtmann 				       struct sk_buff *skb)
14710f36b589SMarcel Holtmann {
14720f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
14730f36b589SMarcel Holtmann 
14740f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
14750f36b589SMarcel Holtmann 
147645296acdSMarcel Holtmann 	if (status)
147745296acdSMarcel Holtmann 		return;
147845296acdSMarcel Holtmann 
1479dcc36c16SJohan Hedberg 	hci_bdaddr_list_clear(&hdev->le_white_list);
14800f36b589SMarcel Holtmann }
14810f36b589SMarcel Holtmann 
14820f36b589SMarcel Holtmann static void hci_cc_le_add_to_white_list(struct hci_dev *hdev,
14830f36b589SMarcel Holtmann 					struct sk_buff *skb)
14840f36b589SMarcel Holtmann {
14850f36b589SMarcel Holtmann 	struct hci_cp_le_add_to_white_list *sent;
14860f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
14870f36b589SMarcel Holtmann 
14880f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
14890f36b589SMarcel Holtmann 
149045296acdSMarcel Holtmann 	if (status)
149145296acdSMarcel Holtmann 		return;
149245296acdSMarcel Holtmann 
14930f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST);
14940f36b589SMarcel Holtmann 	if (!sent)
14950f36b589SMarcel Holtmann 		return;
14960f36b589SMarcel Holtmann 
1497dcc36c16SJohan Hedberg 	hci_bdaddr_list_add(&hdev->le_white_list, &sent->bdaddr,
1498dcc36c16SJohan Hedberg 			   sent->bdaddr_type);
14990f36b589SMarcel Holtmann }
15000f36b589SMarcel Holtmann 
15010f36b589SMarcel Holtmann static void hci_cc_le_del_from_white_list(struct hci_dev *hdev,
15020f36b589SMarcel Holtmann 					  struct sk_buff *skb)
15030f36b589SMarcel Holtmann {
15040f36b589SMarcel Holtmann 	struct hci_cp_le_del_from_white_list *sent;
15050f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
15060f36b589SMarcel Holtmann 
15070f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15080f36b589SMarcel Holtmann 
150945296acdSMarcel Holtmann 	if (status)
151045296acdSMarcel Holtmann 		return;
151145296acdSMarcel Holtmann 
15120f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST);
15130f36b589SMarcel Holtmann 	if (!sent)
15140f36b589SMarcel Holtmann 		return;
15150f36b589SMarcel Holtmann 
1516dcc36c16SJohan Hedberg 	hci_bdaddr_list_del(&hdev->le_white_list, &sent->bdaddr,
1517dcc36c16SJohan Hedberg 			    sent->bdaddr_type);
15180f36b589SMarcel Holtmann }
15190f36b589SMarcel Holtmann 
15209b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
15219b008c04SJohan Hedberg 					    struct sk_buff *skb)
15229b008c04SJohan Hedberg {
15239b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
15249b008c04SJohan Hedberg 
15259b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
15269b008c04SJohan Hedberg 
152745296acdSMarcel Holtmann 	if (rp->status)
152845296acdSMarcel Holtmann 		return;
152945296acdSMarcel Holtmann 
15309b008c04SJohan Hedberg 	memcpy(hdev->le_states, rp->le_states, 8);
15319b008c04SJohan Hedberg }
15329b008c04SJohan Hedberg 
1533a8e1bfaaSMarcel Holtmann static void hci_cc_le_read_def_data_len(struct hci_dev *hdev,
1534a8e1bfaaSMarcel Holtmann 					struct sk_buff *skb)
1535a8e1bfaaSMarcel Holtmann {
1536a8e1bfaaSMarcel Holtmann 	struct hci_rp_le_read_def_data_len *rp = (void *) skb->data;
1537a8e1bfaaSMarcel Holtmann 
1538a8e1bfaaSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1539a8e1bfaaSMarcel Holtmann 
1540a8e1bfaaSMarcel Holtmann 	if (rp->status)
1541a8e1bfaaSMarcel Holtmann 		return;
1542a8e1bfaaSMarcel Holtmann 
1543a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_len = le16_to_cpu(rp->tx_len);
1544a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_time = le16_to_cpu(rp->tx_time);
1545a8e1bfaaSMarcel Holtmann }
1546a8e1bfaaSMarcel Holtmann 
1547a8e1bfaaSMarcel Holtmann static void hci_cc_le_write_def_data_len(struct hci_dev *hdev,
1548a8e1bfaaSMarcel Holtmann 					 struct sk_buff *skb)
1549a8e1bfaaSMarcel Holtmann {
1550a8e1bfaaSMarcel Holtmann 	struct hci_cp_le_write_def_data_len *sent;
1551a8e1bfaaSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1552a8e1bfaaSMarcel Holtmann 
1553a8e1bfaaSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1554a8e1bfaaSMarcel Holtmann 
1555a8e1bfaaSMarcel Holtmann 	if (status)
1556a8e1bfaaSMarcel Holtmann 		return;
1557a8e1bfaaSMarcel Holtmann 
1558a8e1bfaaSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN);
1559a8e1bfaaSMarcel Holtmann 	if (!sent)
1560a8e1bfaaSMarcel Holtmann 		return;
1561a8e1bfaaSMarcel Holtmann 
1562a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_len = le16_to_cpu(sent->tx_len);
1563a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_time = le16_to_cpu(sent->tx_time);
1564a8e1bfaaSMarcel Holtmann }
1565a8e1bfaaSMarcel Holtmann 
1566b950aa88SAnkit Navik static void hci_cc_le_add_to_resolv_list(struct hci_dev *hdev,
1567b950aa88SAnkit Navik 					 struct sk_buff *skb)
1568b950aa88SAnkit Navik {
1569b950aa88SAnkit Navik 	struct hci_cp_le_add_to_resolv_list *sent;
1570b950aa88SAnkit Navik 	__u8 status = *((__u8 *) skb->data);
1571b950aa88SAnkit Navik 
1572b950aa88SAnkit Navik 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1573b950aa88SAnkit Navik 
1574b950aa88SAnkit Navik 	if (status)
1575b950aa88SAnkit Navik 		return;
1576b950aa88SAnkit Navik 
1577b950aa88SAnkit Navik 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST);
1578b950aa88SAnkit Navik 	if (!sent)
1579b950aa88SAnkit Navik 		return;
1580b950aa88SAnkit Navik 
1581b950aa88SAnkit Navik 	hci_bdaddr_list_add_with_irk(&hdev->le_resolv_list, &sent->bdaddr,
1582b950aa88SAnkit Navik 				sent->bdaddr_type, sent->peer_irk,
1583b950aa88SAnkit Navik 				sent->local_irk);
1584b950aa88SAnkit Navik }
1585b950aa88SAnkit Navik 
1586b950aa88SAnkit Navik static void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev,
1587b950aa88SAnkit Navik 					  struct sk_buff *skb)
1588b950aa88SAnkit Navik {
1589b950aa88SAnkit Navik 	struct hci_cp_le_del_from_resolv_list *sent;
1590b950aa88SAnkit Navik 	__u8 status = *((__u8 *) skb->data);
1591b950aa88SAnkit Navik 
1592b950aa88SAnkit Navik 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1593b950aa88SAnkit Navik 
1594b950aa88SAnkit Navik 	if (status)
1595b950aa88SAnkit Navik 		return;
1596b950aa88SAnkit Navik 
1597b950aa88SAnkit Navik 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLV_LIST);
1598b950aa88SAnkit Navik 	if (!sent)
1599b950aa88SAnkit Navik 		return;
1600b950aa88SAnkit Navik 
1601b950aa88SAnkit Navik 	hci_bdaddr_list_del_with_irk(&hdev->le_resolv_list, &sent->bdaddr,
1602b950aa88SAnkit Navik 			    sent->bdaddr_type);
1603b950aa88SAnkit Navik }
1604b950aa88SAnkit Navik 
1605545f2596SAnkit Navik static void hci_cc_le_clear_resolv_list(struct hci_dev *hdev,
1606545f2596SAnkit Navik 				       struct sk_buff *skb)
1607545f2596SAnkit Navik {
1608545f2596SAnkit Navik 	__u8 status = *((__u8 *) skb->data);
1609545f2596SAnkit Navik 
1610545f2596SAnkit Navik 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1611545f2596SAnkit Navik 
1612545f2596SAnkit Navik 	if (status)
1613545f2596SAnkit Navik 		return;
1614545f2596SAnkit Navik 
1615545f2596SAnkit Navik 	hci_bdaddr_list_clear(&hdev->le_resolv_list);
1616545f2596SAnkit Navik }
1617545f2596SAnkit Navik 
1618cfdb0c2dSAnkit Navik static void hci_cc_le_read_resolv_list_size(struct hci_dev *hdev,
1619cfdb0c2dSAnkit Navik 					   struct sk_buff *skb)
1620cfdb0c2dSAnkit Navik {
1621cfdb0c2dSAnkit Navik 	struct hci_rp_le_read_resolv_list_size *rp = (void *) skb->data;
1622cfdb0c2dSAnkit Navik 
1623cfdb0c2dSAnkit Navik 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1624cfdb0c2dSAnkit Navik 
1625cfdb0c2dSAnkit Navik 	if (rp->status)
1626cfdb0c2dSAnkit Navik 		return;
1627cfdb0c2dSAnkit Navik 
1628cfdb0c2dSAnkit Navik 	hdev->le_resolv_list_size = rp->size;
1629cfdb0c2dSAnkit Navik }
1630cfdb0c2dSAnkit Navik 
1631aa12af77SAnkit Navik static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev,
1632aa12af77SAnkit Navik 						struct sk_buff *skb)
1633aa12af77SAnkit Navik {
1634aa12af77SAnkit Navik 	__u8 *sent, status = *((__u8 *) skb->data);
1635aa12af77SAnkit Navik 
1636aa12af77SAnkit Navik 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1637aa12af77SAnkit Navik 
1638aa12af77SAnkit Navik 	if (status)
1639aa12af77SAnkit Navik 		return;
1640aa12af77SAnkit Navik 
1641aa12af77SAnkit Navik 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE);
1642aa12af77SAnkit Navik 	if (!sent)
1643aa12af77SAnkit Navik 		return;
1644aa12af77SAnkit Navik 
1645aa12af77SAnkit Navik 	hci_dev_lock(hdev);
1646aa12af77SAnkit Navik 
1647aa12af77SAnkit Navik 	if (*sent)
1648aa12af77SAnkit Navik 		hci_dev_set_flag(hdev, HCI_LL_RPA_RESOLUTION);
1649aa12af77SAnkit Navik 	else
1650aa12af77SAnkit Navik 		hci_dev_clear_flag(hdev, HCI_LL_RPA_RESOLUTION);
1651aa12af77SAnkit Navik 
1652aa12af77SAnkit Navik 	hci_dev_unlock(hdev);
1653aa12af77SAnkit Navik }
1654aa12af77SAnkit Navik 
1655a8e1bfaaSMarcel Holtmann static void hci_cc_le_read_max_data_len(struct hci_dev *hdev,
1656a8e1bfaaSMarcel Holtmann 					struct sk_buff *skb)
1657a8e1bfaaSMarcel Holtmann {
1658a8e1bfaaSMarcel Holtmann 	struct hci_rp_le_read_max_data_len *rp = (void *) skb->data;
1659a8e1bfaaSMarcel Holtmann 
1660a8e1bfaaSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1661a8e1bfaaSMarcel Holtmann 
1662a8e1bfaaSMarcel Holtmann 	if (rp->status)
1663a8e1bfaaSMarcel Holtmann 		return;
1664a8e1bfaaSMarcel Holtmann 
1665a8e1bfaaSMarcel Holtmann 	hdev->le_max_tx_len = le16_to_cpu(rp->tx_len);
1666a8e1bfaaSMarcel Holtmann 	hdev->le_max_tx_time = le16_to_cpu(rp->tx_time);
1667a8e1bfaaSMarcel Holtmann 	hdev->le_max_rx_len = le16_to_cpu(rp->rx_len);
1668a8e1bfaaSMarcel Holtmann 	hdev->le_max_rx_time = le16_to_cpu(rp->rx_time);
1669a8e1bfaaSMarcel Holtmann }
1670a8e1bfaaSMarcel Holtmann 
16716039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1672f9b49306SAndre Guedes 					   struct sk_buff *skb)
1673f9b49306SAndre Guedes {
167406199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1675f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1676f9b49306SAndre Guedes 
16779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1678f9b49306SAndre Guedes 
167945296acdSMarcel Holtmann 	if (status)
168045296acdSMarcel Holtmann 		return;
168145296acdSMarcel Holtmann 
168206199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
16838f984dfaSJohan Hedberg 	if (!sent)
1684f9b49306SAndre Guedes 		return;
1685f9b49306SAndre Guedes 
16865c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
16875c1a4c8fSJaganath Kanakkassery 
1688416a4ae5SJohan Hedberg 	if (sent->le) {
1689cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE;
1690a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_LE_ENABLED);
1691416a4ae5SJohan Hedberg 	} else {
1692cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE;
1693a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_LE_ENABLED);
1694a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_ADVERTISING);
1695416a4ae5SJohan Hedberg 	}
169653b2caabSJohan Hedberg 
169753b2caabSJohan Hedberg 	if (sent->simul)
1698cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE_BREDR;
169953b2caabSJohan Hedberg 	else
1700cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
17015c1a4c8fSJaganath Kanakkassery 
17025c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
17038f984dfaSJohan Hedberg }
1704f9b49306SAndre Guedes 
170556ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
170656ed2cb8SJohan Hedberg {
170756ed2cb8SJohan Hedberg 	struct hci_cp_le_set_adv_param *cp;
170856ed2cb8SJohan Hedberg 	u8 status = *((u8 *) skb->data);
170956ed2cb8SJohan Hedberg 
171056ed2cb8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
171156ed2cb8SJohan Hedberg 
171256ed2cb8SJohan Hedberg 	if (status)
171356ed2cb8SJohan Hedberg 		return;
171456ed2cb8SJohan Hedberg 
171556ed2cb8SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
171656ed2cb8SJohan Hedberg 	if (!cp)
171756ed2cb8SJohan Hedberg 		return;
171856ed2cb8SJohan Hedberg 
171956ed2cb8SJohan Hedberg 	hci_dev_lock(hdev);
172056ed2cb8SJohan Hedberg 	hdev->adv_addr_type = cp->own_address_type;
172156ed2cb8SJohan Hedberg 	hci_dev_unlock(hdev);
172256ed2cb8SJohan Hedberg }
172356ed2cb8SJohan Hedberg 
1724de181e88SJaganath Kanakkassery static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
1725de181e88SJaganath Kanakkassery {
1726de181e88SJaganath Kanakkassery 	struct hci_rp_le_set_ext_adv_params *rp = (void *) skb->data;
1727de181e88SJaganath Kanakkassery 	struct hci_cp_le_set_ext_adv_params *cp;
1728de181e88SJaganath Kanakkassery 	struct adv_info *adv_instance;
1729de181e88SJaganath Kanakkassery 
1730de181e88SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1731de181e88SJaganath Kanakkassery 
1732de181e88SJaganath Kanakkassery 	if (rp->status)
1733de181e88SJaganath Kanakkassery 		return;
1734de181e88SJaganath Kanakkassery 
1735de181e88SJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS);
1736de181e88SJaganath Kanakkassery 	if (!cp)
1737de181e88SJaganath Kanakkassery 		return;
1738de181e88SJaganath Kanakkassery 
1739de181e88SJaganath Kanakkassery 	hci_dev_lock(hdev);
1740de181e88SJaganath Kanakkassery 	hdev->adv_addr_type = cp->own_addr_type;
1741de181e88SJaganath Kanakkassery 	if (!hdev->cur_adv_instance) {
1742de181e88SJaganath Kanakkassery 		/* Store in hdev for instance 0 */
1743de181e88SJaganath Kanakkassery 		hdev->adv_tx_power = rp->tx_power;
1744de181e88SJaganath Kanakkassery 	} else {
1745de181e88SJaganath Kanakkassery 		adv_instance = hci_find_adv_instance(hdev,
1746de181e88SJaganath Kanakkassery 						     hdev->cur_adv_instance);
1747de181e88SJaganath Kanakkassery 		if (adv_instance)
1748de181e88SJaganath Kanakkassery 			adv_instance->tx_power = rp->tx_power;
1749de181e88SJaganath Kanakkassery 	}
1750a0fb3726SJaganath Kanakkassery 	/* Update adv data as tx power is known now */
1751a0fb3726SJaganath Kanakkassery 	hci_req_update_adv_data(hdev, hdev->cur_adv_instance);
1752de181e88SJaganath Kanakkassery 	hci_dev_unlock(hdev);
1753de181e88SJaganath Kanakkassery }
1754de181e88SJaganath Kanakkassery 
17555ae76a94SAndrzej Kaczmarek static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
17565ae76a94SAndrzej Kaczmarek {
17575ae76a94SAndrzej Kaczmarek 	struct hci_rp_read_rssi *rp = (void *) skb->data;
17585ae76a94SAndrzej Kaczmarek 	struct hci_conn *conn;
17595ae76a94SAndrzej Kaczmarek 
17605ae76a94SAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
17615ae76a94SAndrzej Kaczmarek 
17625ae76a94SAndrzej Kaczmarek 	if (rp->status)
17635ae76a94SAndrzej Kaczmarek 		return;
17645ae76a94SAndrzej Kaczmarek 
17655ae76a94SAndrzej Kaczmarek 	hci_dev_lock(hdev);
17665ae76a94SAndrzej Kaczmarek 
17675ae76a94SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
17685ae76a94SAndrzej Kaczmarek 	if (conn)
17695ae76a94SAndrzej Kaczmarek 		conn->rssi = rp->rssi;
17705ae76a94SAndrzej Kaczmarek 
17715ae76a94SAndrzej Kaczmarek 	hci_dev_unlock(hdev);
17725ae76a94SAndrzej Kaczmarek }
17735ae76a94SAndrzej Kaczmarek 
17745a134faeSAndrzej Kaczmarek static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb)
17755a134faeSAndrzej Kaczmarek {
17765a134faeSAndrzej Kaczmarek 	struct hci_cp_read_tx_power *sent;
17775a134faeSAndrzej Kaczmarek 	struct hci_rp_read_tx_power *rp = (void *) skb->data;
17785a134faeSAndrzej Kaczmarek 	struct hci_conn *conn;
17795a134faeSAndrzej Kaczmarek 
17805a134faeSAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
17815a134faeSAndrzej Kaczmarek 
17825a134faeSAndrzej Kaczmarek 	if (rp->status)
17835a134faeSAndrzej Kaczmarek 		return;
17845a134faeSAndrzej Kaczmarek 
17855a134faeSAndrzej Kaczmarek 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
17865a134faeSAndrzej Kaczmarek 	if (!sent)
17875a134faeSAndrzej Kaczmarek 		return;
17885a134faeSAndrzej Kaczmarek 
17895a134faeSAndrzej Kaczmarek 	hci_dev_lock(hdev);
17905a134faeSAndrzej Kaczmarek 
17915a134faeSAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1792d0455ed9SAndrzej Kaczmarek 	if (!conn)
1793d0455ed9SAndrzej Kaczmarek 		goto unlock;
17945a134faeSAndrzej Kaczmarek 
1795d0455ed9SAndrzej Kaczmarek 	switch (sent->type) {
1796d0455ed9SAndrzej Kaczmarek 	case 0x00:
1797d0455ed9SAndrzej Kaczmarek 		conn->tx_power = rp->tx_power;
1798d0455ed9SAndrzej Kaczmarek 		break;
1799d0455ed9SAndrzej Kaczmarek 	case 0x01:
1800d0455ed9SAndrzej Kaczmarek 		conn->max_tx_power = rp->tx_power;
1801d0455ed9SAndrzej Kaczmarek 		break;
1802d0455ed9SAndrzej Kaczmarek 	}
1803d0455ed9SAndrzej Kaczmarek 
1804d0455ed9SAndrzej Kaczmarek unlock:
18055a134faeSAndrzej Kaczmarek 	hci_dev_unlock(hdev);
18065a134faeSAndrzej Kaczmarek }
18075a134faeSAndrzej Kaczmarek 
1808c50b33c8SMarcel Holtmann static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb)
1809c50b33c8SMarcel Holtmann {
1810c50b33c8SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
1811c50b33c8SMarcel Holtmann 	u8 *mode;
1812c50b33c8SMarcel Holtmann 
1813c50b33c8SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1814c50b33c8SMarcel Holtmann 
1815c50b33c8SMarcel Holtmann 	if (status)
1816c50b33c8SMarcel Holtmann 		return;
1817c50b33c8SMarcel Holtmann 
1818c50b33c8SMarcel Holtmann 	mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE);
1819c50b33c8SMarcel Holtmann 	if (mode)
1820c50b33c8SMarcel Holtmann 		hdev->ssp_debug_mode = *mode;
1821c50b33c8SMarcel Holtmann }
1822c50b33c8SMarcel Holtmann 
18236039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1824a9de9248SMarcel Holtmann {
18259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1826a9de9248SMarcel Holtmann 
1827a9de9248SMarcel Holtmann 	if (status) {
1828a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1829314b2381SJohan Hedberg 		return;
1830314b2381SJohan Hedberg 	}
1831314b2381SJohan Hedberg 
183289352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1833a9de9248SMarcel Holtmann }
1834a9de9248SMarcel Holtmann 
18356039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
18361da177e4SLinus Torvalds {
1837a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
18381da177e4SLinus Torvalds 	struct hci_conn *conn;
18391da177e4SLinus Torvalds 
18409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1841a9de9248SMarcel Holtmann 
1842a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
18431da177e4SLinus Torvalds 	if (!cp)
18441da177e4SLinus Torvalds 		return;
18451da177e4SLinus Torvalds 
18461da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18471da177e4SLinus Torvalds 
18481da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
18491da177e4SLinus Torvalds 
18506ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
18511da177e4SLinus Torvalds 
18521da177e4SLinus Torvalds 	if (status) {
18531da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
18544c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
18551da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
1856539c496dSJohan Hedberg 				hci_connect_cfm(conn, status);
18571da177e4SLinus Torvalds 				hci_conn_del(conn);
18584c67bc74SMarcel Holtmann 			} else
18594c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
18601da177e4SLinus Torvalds 		}
18611da177e4SLinus Torvalds 	} else {
18621da177e4SLinus Torvalds 		if (!conn) {
1863a5c4e309SJohan Hedberg 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr,
1864a5c4e309SJohan Hedberg 					    HCI_ROLE_MASTER);
1865a5c4e309SJohan Hedberg 			if (!conn)
18662064ee33SMarcel Holtmann 				bt_dev_err(hdev, "no memory for new connection");
18671da177e4SLinus Torvalds 		}
18681da177e4SLinus Torvalds 	}
18691da177e4SLinus Torvalds 
18701da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18711da177e4SLinus Torvalds }
18721da177e4SLinus Torvalds 
1873a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
18741da177e4SLinus Torvalds {
1875a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
18761da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
18771da177e4SLinus Torvalds 	__u16 handle;
18781da177e4SLinus Torvalds 
18799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1880b6a0dc82SMarcel Holtmann 
1881a9de9248SMarcel Holtmann 	if (!status)
1882a9de9248SMarcel Holtmann 		return;
1883a9de9248SMarcel Holtmann 
1884a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
18851da177e4SLinus Torvalds 	if (!cp)
1886a9de9248SMarcel Holtmann 		return;
18871da177e4SLinus Torvalds 
18881da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
18891da177e4SLinus Torvalds 
18909f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
18911da177e4SLinus Torvalds 
18921da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18931da177e4SLinus Torvalds 
18941da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
18955a08ecceSAndrei Emeltchenko 	if (acl) {
18965a08ecceSAndrei Emeltchenko 		sco = acl->link;
18975a08ecceSAndrei Emeltchenko 		if (sco) {
18981da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
18991da177e4SLinus Torvalds 
1900539c496dSJohan Hedberg 			hci_connect_cfm(sco, status);
19011da177e4SLinus Torvalds 			hci_conn_del(sco);
19021da177e4SLinus Torvalds 		}
19035a08ecceSAndrei Emeltchenko 	}
19041da177e4SLinus Torvalds 
19051da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19061da177e4SLinus Torvalds }
19071da177e4SLinus Torvalds 
1908f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1909f8558555SMarcel Holtmann {
1910f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1911f8558555SMarcel Holtmann 	struct hci_conn *conn;
1912f8558555SMarcel Holtmann 
19139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1914f8558555SMarcel Holtmann 
1915f8558555SMarcel Holtmann 	if (!status)
1916f8558555SMarcel Holtmann 		return;
1917f8558555SMarcel Holtmann 
1918f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1919f8558555SMarcel Holtmann 	if (!cp)
1920f8558555SMarcel Holtmann 		return;
1921f8558555SMarcel Holtmann 
1922f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1923f8558555SMarcel Holtmann 
1924f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1925f8558555SMarcel Holtmann 	if (conn) {
1926f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1927539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
192876a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1929f8558555SMarcel Holtmann 		}
1930f8558555SMarcel Holtmann 	}
1931f8558555SMarcel Holtmann 
1932f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1933f8558555SMarcel Holtmann }
1934f8558555SMarcel Holtmann 
1935f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1936f8558555SMarcel Holtmann {
1937f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1938f8558555SMarcel Holtmann 	struct hci_conn *conn;
1939f8558555SMarcel Holtmann 
19409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1941f8558555SMarcel Holtmann 
1942f8558555SMarcel Holtmann 	if (!status)
1943f8558555SMarcel Holtmann 		return;
1944f8558555SMarcel Holtmann 
1945f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1946f8558555SMarcel Holtmann 	if (!cp)
1947f8558555SMarcel Holtmann 		return;
1948f8558555SMarcel Holtmann 
1949f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1950f8558555SMarcel Holtmann 
1951f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1952f8558555SMarcel Holtmann 	if (conn) {
1953f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1954539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
195576a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1956f8558555SMarcel Holtmann 		}
1957f8558555SMarcel Holtmann 	}
1958f8558555SMarcel Holtmann 
1959f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1960f8558555SMarcel Holtmann }
1961f8558555SMarcel Holtmann 
1962127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1963392599b9SJohan Hedberg 				    struct hci_conn *conn)
1964392599b9SJohan Hedberg {
1965392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1966392599b9SJohan Hedberg 		return 0;
1967392599b9SJohan Hedberg 
1968765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1969392599b9SJohan Hedberg 		return 0;
1970392599b9SJohan Hedberg 
1971392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1972264b8b4eSJohan Hedberg 	 * devices with sec_level MEDIUM or HIGH or if MITM protection
1973264b8b4eSJohan Hedberg 	 * is requested.
1974264b8b4eSJohan Hedberg 	 */
1975807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
19767e3691e1SJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_FIPS &&
1977264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
1978264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
1979392599b9SJohan Hedberg 		return 0;
1980392599b9SJohan Hedberg 
1981392599b9SJohan Hedberg 	return 1;
1982392599b9SJohan Hedberg }
1983392599b9SJohan Hedberg 
19846039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
198500abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
198630dc78e1SJohan Hedberg {
198730dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
198830dc78e1SJohan Hedberg 
198930dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
199030dc78e1SJohan Hedberg 
199130dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
199230dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
199330dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
199430dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
199530dc78e1SJohan Hedberg 
199630dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
199730dc78e1SJohan Hedberg }
199830dc78e1SJohan Hedberg 
1999b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
200030dc78e1SJohan Hedberg {
200130dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
200230dc78e1SJohan Hedberg 	struct inquiry_entry *e;
200330dc78e1SJohan Hedberg 
2004b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
2005b644ba33SJohan Hedberg 		return false;
2006b644ba33SJohan Hedberg 
2007b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
2008c810089cSRam Malovany 	if (!e)
2009c810089cSRam Malovany 		return false;
2010c810089cSRam Malovany 
2011b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
2012b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
2013b644ba33SJohan Hedberg 		return true;
2014b644ba33SJohan Hedberg 	}
2015b644ba33SJohan Hedberg 
2016b644ba33SJohan Hedberg 	return false;
2017b644ba33SJohan Hedberg }
2018b644ba33SJohan Hedberg 
2019b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
2020b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
2021b644ba33SJohan Hedberg {
2022b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
2023b644ba33SJohan Hedberg 	struct inquiry_entry *e;
2024b644ba33SJohan Hedberg 
202560cb49d2SJohan Hedberg 	/* Update the mgmt connected state if necessary. Be careful with
202660cb49d2SJohan Hedberg 	 * conn objects that exist but are not (yet) connected however.
202760cb49d2SJohan Hedberg 	 * Only those in BT_CONFIG or BT_CONNECTED states can be
202860cb49d2SJohan Hedberg 	 * considered connected.
202960cb49d2SJohan Hedberg 	 */
203060cb49d2SJohan Hedberg 	if (conn &&
203160cb49d2SJohan Hedberg 	    (conn->state == BT_CONFIG || conn->state == BT_CONNECTED) &&
2032cb77c3ecSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
203348ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, name, name_len);
2034b644ba33SJohan Hedberg 
2035b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
2036b644ba33SJohan Hedberg 		return;
2037b644ba33SJohan Hedberg 
203830dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
203930dc78e1SJohan Hedberg 		goto discov_complete;
204030dc78e1SJohan Hedberg 
204130dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
204230dc78e1SJohan Hedberg 		return;
204330dc78e1SJohan Hedberg 
204430dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
20457cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
20467cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
20477cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
20487cc8380eSRam Malovany 	 * Event */
20497cc8380eSRam Malovany 	if (!e)
20507cc8380eSRam Malovany 		return;
20517cc8380eSRam Malovany 
205230dc78e1SJohan Hedberg 	list_del(&e->list);
20537cc8380eSRam Malovany 	if (name) {
20547cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
2055b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
2056b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
2057c3e7c0d9SRam Malovany 	} else {
2058c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
205930dc78e1SJohan Hedberg 	}
206030dc78e1SJohan Hedberg 
2061b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
206230dc78e1SJohan Hedberg 		return;
206330dc78e1SJohan Hedberg 
206430dc78e1SJohan Hedberg discov_complete:
206530dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
206630dc78e1SJohan Hedberg }
206730dc78e1SJohan Hedberg 
2068a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
20691da177e4SLinus Torvalds {
2070127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
2071127178d2SJohan Hedberg 	struct hci_conn *conn;
2072127178d2SJohan Hedberg 
20739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2074127178d2SJohan Hedberg 
2075127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
2076127178d2SJohan Hedberg 	 * checking for the need to do authentication */
2077127178d2SJohan Hedberg 	if (!status)
2078127178d2SJohan Hedberg 		return;
2079127178d2SJohan Hedberg 
2080127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
2081127178d2SJohan Hedberg 	if (!cp)
2082127178d2SJohan Hedberg 		return;
2083127178d2SJohan Hedberg 
2084127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2085127178d2SJohan Hedberg 
2086127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
2087b644ba33SJohan Hedberg 
2088d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
2089b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
2090b644ba33SJohan Hedberg 
209179c6c70cSJohan Hedberg 	if (!conn)
209279c6c70cSJohan Hedberg 		goto unlock;
209379c6c70cSJohan Hedberg 
209479c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
209579c6c70cSJohan Hedberg 		goto unlock;
209679c6c70cSJohan Hedberg 
209751a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2098c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
2099c1f23a2bSJohannes Berg 
2100977f8fceSJohan Hedberg 		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
2101977f8fceSJohan Hedberg 
2102c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
2103c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
2104c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
2105127178d2SJohan Hedberg 	}
2106127178d2SJohan Hedberg 
210779c6c70cSJohan Hedberg unlock:
2108127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2109a9de9248SMarcel Holtmann }
21101da177e4SLinus Torvalds 
2111769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
2112769be974SMarcel Holtmann {
2113769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
2114769be974SMarcel Holtmann 	struct hci_conn *conn;
2115769be974SMarcel Holtmann 
21169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2117769be974SMarcel Holtmann 
2118769be974SMarcel Holtmann 	if (!status)
2119769be974SMarcel Holtmann 		return;
2120769be974SMarcel Holtmann 
2121769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
2122769be974SMarcel Holtmann 	if (!cp)
2123769be974SMarcel Holtmann 		return;
2124769be974SMarcel Holtmann 
2125769be974SMarcel Holtmann 	hci_dev_lock(hdev);
2126769be974SMarcel Holtmann 
2127769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
2128769be974SMarcel Holtmann 	if (conn) {
2129769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2130539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
213176a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2132769be974SMarcel Holtmann 		}
2133769be974SMarcel Holtmann 	}
2134769be974SMarcel Holtmann 
2135769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
2136769be974SMarcel Holtmann }
2137769be974SMarcel Holtmann 
2138769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
2139769be974SMarcel Holtmann {
2140769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
2141769be974SMarcel Holtmann 	struct hci_conn *conn;
2142769be974SMarcel Holtmann 
21439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2144769be974SMarcel Holtmann 
2145769be974SMarcel Holtmann 	if (!status)
2146769be974SMarcel Holtmann 		return;
2147769be974SMarcel Holtmann 
2148769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
2149769be974SMarcel Holtmann 	if (!cp)
2150769be974SMarcel Holtmann 		return;
2151769be974SMarcel Holtmann 
2152769be974SMarcel Holtmann 	hci_dev_lock(hdev);
2153769be974SMarcel Holtmann 
2154769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
2155769be974SMarcel Holtmann 	if (conn) {
2156769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2157539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
215876a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2159769be974SMarcel Holtmann 		}
2160769be974SMarcel Holtmann 	}
2161769be974SMarcel Holtmann 
2162769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
2163769be974SMarcel Holtmann }
2164769be974SMarcel Holtmann 
2165a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
2166a9de9248SMarcel Holtmann {
2167b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
2168b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
2169b6a0dc82SMarcel Holtmann 	__u16 handle;
2170b6a0dc82SMarcel Holtmann 
21719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2172b6a0dc82SMarcel Holtmann 
2173b6a0dc82SMarcel Holtmann 	if (!status)
2174b6a0dc82SMarcel Holtmann 		return;
2175b6a0dc82SMarcel Holtmann 
2176b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
2177b6a0dc82SMarcel Holtmann 	if (!cp)
2178b6a0dc82SMarcel Holtmann 		return;
2179b6a0dc82SMarcel Holtmann 
2180b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
2181b6a0dc82SMarcel Holtmann 
21829f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
2183b6a0dc82SMarcel Holtmann 
2184b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2185b6a0dc82SMarcel Holtmann 
2186b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
21875a08ecceSAndrei Emeltchenko 	if (acl) {
21885a08ecceSAndrei Emeltchenko 		sco = acl->link;
21895a08ecceSAndrei Emeltchenko 		if (sco) {
2190b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
2191b6a0dc82SMarcel Holtmann 
2192539c496dSJohan Hedberg 			hci_connect_cfm(sco, status);
2193b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
2194b6a0dc82SMarcel Holtmann 		}
21955a08ecceSAndrei Emeltchenko 	}
2196b6a0dc82SMarcel Holtmann 
2197b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2198a9de9248SMarcel Holtmann }
2199a9de9248SMarcel Holtmann 
2200a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
2201a9de9248SMarcel Holtmann {
2202a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
220304837f64SMarcel Holtmann 	struct hci_conn *conn;
220404837f64SMarcel Holtmann 
22059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2206a9de9248SMarcel Holtmann 
2207a9de9248SMarcel Holtmann 	if (!status)
2208a9de9248SMarcel Holtmann 		return;
2209a9de9248SMarcel Holtmann 
2210a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
221104837f64SMarcel Holtmann 	if (!cp)
2212a9de9248SMarcel Holtmann 		return;
221304837f64SMarcel Holtmann 
221404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
221504837f64SMarcel Holtmann 
221604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
2217e73439d8SMarcel Holtmann 	if (conn) {
221851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
221904837f64SMarcel Holtmann 
222051a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2221e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
2222e73439d8SMarcel Holtmann 	}
2223e73439d8SMarcel Holtmann 
222404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
222504837f64SMarcel Holtmann }
222604837f64SMarcel Holtmann 
2227a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
2228a9de9248SMarcel Holtmann {
2229a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
223004837f64SMarcel Holtmann 	struct hci_conn *conn;
223104837f64SMarcel Holtmann 
22329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2233a9de9248SMarcel Holtmann 
2234a9de9248SMarcel Holtmann 	if (!status)
2235a9de9248SMarcel Holtmann 		return;
2236a9de9248SMarcel Holtmann 
2237a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
223804837f64SMarcel Holtmann 	if (!cp)
2239a9de9248SMarcel Holtmann 		return;
224004837f64SMarcel Holtmann 
224104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
224204837f64SMarcel Holtmann 
224304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
2244e73439d8SMarcel Holtmann 	if (conn) {
224551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
224604837f64SMarcel Holtmann 
224751a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2248e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
2249e73439d8SMarcel Holtmann 	}
2250e73439d8SMarcel Holtmann 
225104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
225204837f64SMarcel Holtmann }
225304837f64SMarcel Holtmann 
225488c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
225588c3df13SJohan Hedberg {
225688c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
225788c3df13SJohan Hedberg 	struct hci_conn *conn;
225888c3df13SJohan Hedberg 
225988c3df13SJohan Hedberg 	if (!status)
226088c3df13SJohan Hedberg 		return;
226188c3df13SJohan Hedberg 
226288c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
226388c3df13SJohan Hedberg 	if (!cp)
226488c3df13SJohan Hedberg 		return;
226588c3df13SJohan Hedberg 
226688c3df13SJohan Hedberg 	hci_dev_lock(hdev);
226788c3df13SJohan Hedberg 
226888c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
2269b8d29052SJoseph Hwang 	if (conn) {
2270b8d29052SJoseph Hwang 		u8 type = conn->type;
2271b8d29052SJoseph Hwang 
227288c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
227388c3df13SJohan Hedberg 				       conn->dst_type, status);
227488c3df13SJohan Hedberg 
2275b8d29052SJoseph Hwang 		/* If the disconnection failed for any reason, the upper layer
2276b8d29052SJoseph Hwang 		 * does not retry to disconnect in current implementation.
2277b8d29052SJoseph Hwang 		 * Hence, we need to do some basic cleanup here and re-enable
2278b8d29052SJoseph Hwang 		 * advertising if necessary.
2279b8d29052SJoseph Hwang 		 */
2280b8d29052SJoseph Hwang 		hci_conn_del(conn);
2281b8d29052SJoseph Hwang 		if (type == LE_LINK)
2282b8d29052SJoseph Hwang 			hci_req_reenable_advertising(hdev);
2283b8d29052SJoseph Hwang 	}
2284b8d29052SJoseph Hwang 
228588c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
228688c3df13SJohan Hedberg }
228788c3df13SJohan Hedberg 
2288d12fb056SJaganath Kanakkassery static void cs_le_create_conn(struct hci_dev *hdev, bdaddr_t *peer_addr,
2289d12fb056SJaganath Kanakkassery 			      u8 peer_addr_type, u8 own_address_type,
2290d12fb056SJaganath Kanakkassery 			      u8 filter_policy)
2291d12fb056SJaganath Kanakkassery {
2292d12fb056SJaganath Kanakkassery 	struct hci_conn *conn;
2293d12fb056SJaganath Kanakkassery 
2294d12fb056SJaganath Kanakkassery 	conn = hci_conn_hash_lookup_le(hdev, peer_addr,
2295d12fb056SJaganath Kanakkassery 				       peer_addr_type);
2296d12fb056SJaganath Kanakkassery 	if (!conn)
2297d12fb056SJaganath Kanakkassery 		return;
2298d12fb056SJaganath Kanakkassery 
2299b31bc00bSSathish Narasimman 	/* When using controller based address resolution, then the new
2300b31bc00bSSathish Narasimman 	 * address types 0x02 and 0x03 are used. These types need to be
2301b31bc00bSSathish Narasimman 	 * converted back into either public address or random address type
2302b31bc00bSSathish Narasimman 	 */
2303b31bc00bSSathish Narasimman 	if (use_ll_privacy(hdev) &&
2304b31bc00bSSathish Narasimman 	    hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION)) {
2305b31bc00bSSathish Narasimman 		switch (own_address_type) {
2306b31bc00bSSathish Narasimman 		case ADDR_LE_DEV_PUBLIC_RESOLVED:
2307b31bc00bSSathish Narasimman 			own_address_type = ADDR_LE_DEV_PUBLIC;
2308b31bc00bSSathish Narasimman 			break;
2309b31bc00bSSathish Narasimman 		case ADDR_LE_DEV_RANDOM_RESOLVED:
2310b31bc00bSSathish Narasimman 			own_address_type = ADDR_LE_DEV_RANDOM;
2311b31bc00bSSathish Narasimman 			break;
2312b31bc00bSSathish Narasimman 		}
2313b31bc00bSSathish Narasimman 	}
2314b31bc00bSSathish Narasimman 
2315d12fb056SJaganath Kanakkassery 	/* Store the initiator and responder address information which
2316d12fb056SJaganath Kanakkassery 	 * is needed for SMP. These values will not change during the
2317d12fb056SJaganath Kanakkassery 	 * lifetime of the connection.
2318d12fb056SJaganath Kanakkassery 	 */
2319d12fb056SJaganath Kanakkassery 	conn->init_addr_type = own_address_type;
2320d12fb056SJaganath Kanakkassery 	if (own_address_type == ADDR_LE_DEV_RANDOM)
2321d12fb056SJaganath Kanakkassery 		bacpy(&conn->init_addr, &hdev->random_addr);
2322d12fb056SJaganath Kanakkassery 	else
2323d12fb056SJaganath Kanakkassery 		bacpy(&conn->init_addr, &hdev->bdaddr);
2324d12fb056SJaganath Kanakkassery 
2325d12fb056SJaganath Kanakkassery 	conn->resp_addr_type = peer_addr_type;
2326d12fb056SJaganath Kanakkassery 	bacpy(&conn->resp_addr, peer_addr);
2327d12fb056SJaganath Kanakkassery 
2328d12fb056SJaganath Kanakkassery 	/* We don't want the connection attempt to stick around
2329d12fb056SJaganath Kanakkassery 	 * indefinitely since LE doesn't have a page timeout concept
2330d12fb056SJaganath Kanakkassery 	 * like BR/EDR. Set a timer for any connection that doesn't use
2331d12fb056SJaganath Kanakkassery 	 * the white list for connecting.
2332d12fb056SJaganath Kanakkassery 	 */
2333d12fb056SJaganath Kanakkassery 	if (filter_policy == HCI_LE_USE_PEER_ADDR)
2334d12fb056SJaganath Kanakkassery 		queue_delayed_work(conn->hdev->workqueue,
2335d12fb056SJaganath Kanakkassery 				   &conn->le_conn_timeout,
2336d12fb056SJaganath Kanakkassery 				   conn->conn_timeout);
2337d12fb056SJaganath Kanakkassery }
2338d12fb056SJaganath Kanakkassery 
2339cb1d68f7SJohan Hedberg static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
2340cb1d68f7SJohan Hedberg {
2341cb1d68f7SJohan Hedberg 	struct hci_cp_le_create_conn *cp;
2342cb1d68f7SJohan Hedberg 
2343cb1d68f7SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2344cb1d68f7SJohan Hedberg 
2345cb1d68f7SJohan Hedberg 	/* All connection failure handling is taken care of by the
2346cb1d68f7SJohan Hedberg 	 * hci_le_conn_failed function which is triggered by the HCI
2347cb1d68f7SJohan Hedberg 	 * request completion callbacks used for connecting.
2348cb1d68f7SJohan Hedberg 	 */
2349cb1d68f7SJohan Hedberg 	if (status)
2350cb1d68f7SJohan Hedberg 		return;
2351cb1d68f7SJohan Hedberg 
2352cb1d68f7SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
2353cb1d68f7SJohan Hedberg 	if (!cp)
2354cb1d68f7SJohan Hedberg 		return;
2355cb1d68f7SJohan Hedberg 
2356cb1d68f7SJohan Hedberg 	hci_dev_lock(hdev);
2357cb1d68f7SJohan Hedberg 
2358d12fb056SJaganath Kanakkassery 	cs_le_create_conn(hdev, &cp->peer_addr, cp->peer_addr_type,
2359d12fb056SJaganath Kanakkassery 			  cp->own_address_type, cp->filter_policy);
2360cb1d68f7SJohan Hedberg 
2361cb1d68f7SJohan Hedberg 	hci_dev_unlock(hdev);
2362cb1d68f7SJohan Hedberg }
2363cb1d68f7SJohan Hedberg 
23644d94f95dSJaganath Kanakkassery static void hci_cs_le_ext_create_conn(struct hci_dev *hdev, u8 status)
23654d94f95dSJaganath Kanakkassery {
23664d94f95dSJaganath Kanakkassery 	struct hci_cp_le_ext_create_conn *cp;
23674d94f95dSJaganath Kanakkassery 
23684d94f95dSJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
23694d94f95dSJaganath Kanakkassery 
23704d94f95dSJaganath Kanakkassery 	/* All connection failure handling is taken care of by the
23714d94f95dSJaganath Kanakkassery 	 * hci_le_conn_failed function which is triggered by the HCI
23724d94f95dSJaganath Kanakkassery 	 * request completion callbacks used for connecting.
23734d94f95dSJaganath Kanakkassery 	 */
23744d94f95dSJaganath Kanakkassery 	if (status)
23754d94f95dSJaganath Kanakkassery 		return;
23764d94f95dSJaganath Kanakkassery 
23774d94f95dSJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_EXT_CREATE_CONN);
23784d94f95dSJaganath Kanakkassery 	if (!cp)
23794d94f95dSJaganath Kanakkassery 		return;
23804d94f95dSJaganath Kanakkassery 
23814d94f95dSJaganath Kanakkassery 	hci_dev_lock(hdev);
23824d94f95dSJaganath Kanakkassery 
23834d94f95dSJaganath Kanakkassery 	cs_le_create_conn(hdev, &cp->peer_addr, cp->peer_addr_type,
23844d94f95dSJaganath Kanakkassery 			  cp->own_addr_type, cp->filter_policy);
23854d94f95dSJaganath Kanakkassery 
23864d94f95dSJaganath Kanakkassery 	hci_dev_unlock(hdev);
23874d94f95dSJaganath Kanakkassery }
23884d94f95dSJaganath Kanakkassery 
23890fe29fd1SMarcel Holtmann static void hci_cs_le_read_remote_features(struct hci_dev *hdev, u8 status)
23900fe29fd1SMarcel Holtmann {
23910fe29fd1SMarcel Holtmann 	struct hci_cp_le_read_remote_features *cp;
23920fe29fd1SMarcel Holtmann 	struct hci_conn *conn;
23930fe29fd1SMarcel Holtmann 
23940fe29fd1SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
23950fe29fd1SMarcel Holtmann 
23960fe29fd1SMarcel Holtmann 	if (!status)
23970fe29fd1SMarcel Holtmann 		return;
23980fe29fd1SMarcel Holtmann 
23990fe29fd1SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_READ_REMOTE_FEATURES);
24000fe29fd1SMarcel Holtmann 	if (!cp)
24010fe29fd1SMarcel Holtmann 		return;
24020fe29fd1SMarcel Holtmann 
24030fe29fd1SMarcel Holtmann 	hci_dev_lock(hdev);
24040fe29fd1SMarcel Holtmann 
24050fe29fd1SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
24060fe29fd1SMarcel Holtmann 	if (conn) {
24070fe29fd1SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
24080fe29fd1SMarcel Holtmann 			hci_connect_cfm(conn, status);
24090fe29fd1SMarcel Holtmann 			hci_conn_drop(conn);
24100fe29fd1SMarcel Holtmann 		}
24110fe29fd1SMarcel Holtmann 	}
24120fe29fd1SMarcel Holtmann 
24130fe29fd1SMarcel Holtmann 	hci_dev_unlock(hdev);
24140fe29fd1SMarcel Holtmann }
24150fe29fd1SMarcel Holtmann 
241681d0c8adSJohan Hedberg static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
241781d0c8adSJohan Hedberg {
241881d0c8adSJohan Hedberg 	struct hci_cp_le_start_enc *cp;
241981d0c8adSJohan Hedberg 	struct hci_conn *conn;
242081d0c8adSJohan Hedberg 
242181d0c8adSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
242281d0c8adSJohan Hedberg 
242381d0c8adSJohan Hedberg 	if (!status)
242481d0c8adSJohan Hedberg 		return;
242581d0c8adSJohan Hedberg 
242681d0c8adSJohan Hedberg 	hci_dev_lock(hdev);
242781d0c8adSJohan Hedberg 
242881d0c8adSJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC);
242981d0c8adSJohan Hedberg 	if (!cp)
243081d0c8adSJohan Hedberg 		goto unlock;
243181d0c8adSJohan Hedberg 
243281d0c8adSJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
243381d0c8adSJohan Hedberg 	if (!conn)
243481d0c8adSJohan Hedberg 		goto unlock;
243581d0c8adSJohan Hedberg 
243681d0c8adSJohan Hedberg 	if (conn->state != BT_CONNECTED)
243781d0c8adSJohan Hedberg 		goto unlock;
243881d0c8adSJohan Hedberg 
243981d0c8adSJohan Hedberg 	hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
244081d0c8adSJohan Hedberg 	hci_conn_drop(conn);
244181d0c8adSJohan Hedberg 
244281d0c8adSJohan Hedberg unlock:
244381d0c8adSJohan Hedberg 	hci_dev_unlock(hdev);
244481d0c8adSJohan Hedberg }
244581d0c8adSJohan Hedberg 
244650fc85f1SKuba Pawlak static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
244750fc85f1SKuba Pawlak {
244850fc85f1SKuba Pawlak 	struct hci_cp_switch_role *cp;
244950fc85f1SKuba Pawlak 	struct hci_conn *conn;
245050fc85f1SKuba Pawlak 
245150fc85f1SKuba Pawlak 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
245250fc85f1SKuba Pawlak 
245350fc85f1SKuba Pawlak 	if (!status)
245450fc85f1SKuba Pawlak 		return;
245550fc85f1SKuba Pawlak 
245650fc85f1SKuba Pawlak 	cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE);
245750fc85f1SKuba Pawlak 	if (!cp)
245850fc85f1SKuba Pawlak 		return;
245950fc85f1SKuba Pawlak 
246050fc85f1SKuba Pawlak 	hci_dev_lock(hdev);
246150fc85f1SKuba Pawlak 
246250fc85f1SKuba Pawlak 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
246350fc85f1SKuba Pawlak 	if (conn)
246450fc85f1SKuba Pawlak 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
246550fc85f1SKuba Pawlak 
246650fc85f1SKuba Pawlak 	hci_dev_unlock(hdev);
246750fc85f1SKuba Pawlak }
246850fc85f1SKuba Pawlak 
24696039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
24701da177e4SLinus Torvalds {
24711da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
247230dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
247330dc78e1SJohan Hedberg 	struct inquiry_entry *e;
24741da177e4SLinus Torvalds 
24759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
24761da177e4SLinus Torvalds 
2477a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
247889352e7dSAndre Guedes 
247989352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
248089352e7dSAndre Guedes 		return;
248189352e7dSAndre Guedes 
24824e857c58SPeter Zijlstra 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
24833e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
24843e13fa1eSAndre Guedes 
2485d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
248630dc78e1SJohan Hedberg 		return;
248730dc78e1SJohan Hedberg 
248856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
248930dc78e1SJohan Hedberg 
2490343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
249130dc78e1SJohan Hedberg 		goto unlock;
249230dc78e1SJohan Hedberg 
249330dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
249407d2334aSJakub Pawlowski 		/* When BR/EDR inquiry is active and no LE scanning is in
249507d2334aSJakub Pawlowski 		 * progress, then change discovery state to indicate completion.
249607d2334aSJakub Pawlowski 		 *
249707d2334aSJakub Pawlowski 		 * When running LE scanning and BR/EDR inquiry simultaneously
249807d2334aSJakub Pawlowski 		 * and the LE scan already finished, then change the discovery
249907d2334aSJakub Pawlowski 		 * state to indicate completion.
250007d2334aSJakub Pawlowski 		 */
250107d2334aSJakub Pawlowski 		if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
250207d2334aSJakub Pawlowski 		    !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
2503ff9ef578SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
250430dc78e1SJohan Hedberg 		goto unlock;
250530dc78e1SJohan Hedberg 	}
250630dc78e1SJohan Hedberg 
250730dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
250830dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
250930dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
251030dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
251130dc78e1SJohan Hedberg 	} else {
251207d2334aSJakub Pawlowski 		/* When BR/EDR inquiry is active and no LE scanning is in
251307d2334aSJakub Pawlowski 		 * progress, then change discovery state to indicate completion.
251407d2334aSJakub Pawlowski 		 *
251507d2334aSJakub Pawlowski 		 * When running LE scanning and BR/EDR inquiry simultaneously
251607d2334aSJakub Pawlowski 		 * and the LE scan already finished, then change the discovery
251707d2334aSJakub Pawlowski 		 * state to indicate completion.
251807d2334aSJakub Pawlowski 		 */
251907d2334aSJakub Pawlowski 		if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
252007d2334aSJakub Pawlowski 		    !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
252130dc78e1SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
252230dc78e1SJohan Hedberg 	}
252330dc78e1SJohan Hedberg 
252430dc78e1SJohan Hedberg unlock:
252556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
25261da177e4SLinus Torvalds }
25271da177e4SLinus Torvalds 
25286039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
25291da177e4SLinus Torvalds {
253045bb4bf0SMarcel Holtmann 	struct inquiry_data data;
2531a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
25321da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
25331da177e4SLinus Torvalds 
25341da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
25351da177e4SLinus Torvalds 
253675bbd2eaSPeilin Ye 	if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1)
253745bb4bf0SMarcel Holtmann 		return;
253845bb4bf0SMarcel Holtmann 
2539d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
25401519cc17SAndre Guedes 		return;
25411519cc17SAndre Guedes 
25421da177e4SLinus Torvalds 	hci_dev_lock(hdev);
254345bb4bf0SMarcel Holtmann 
2544e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2545af58925cSMarcel Holtmann 		u32 flags;
25463175405bSJohan Hedberg 
25471da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
25481da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
25491da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
25501da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
25511da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
25521da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
2553efb2513fSMarcel Holtmann 		data.rssi		= HCI_RSSI_INVALID;
255441a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
25553175405bSJohan Hedberg 
2556af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, false);
2557af58925cSMarcel Holtmann 
255848264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2559efb2513fSMarcel Holtmann 				  info->dev_class, HCI_RSSI_INVALID,
2560efb2513fSMarcel Holtmann 				  flags, NULL, 0, NULL, 0);
25611da177e4SLinus Torvalds 	}
256245bb4bf0SMarcel Holtmann 
25631da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
25641da177e4SLinus Torvalds }
25651da177e4SLinus Torvalds 
25666039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
25671da177e4SLinus Torvalds {
2568a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
25694f40afc6SAbhishek Pandit-Subedi 	struct inquiry_entry *ie;
2570a9de9248SMarcel Holtmann 	struct hci_conn *conn;
25711da177e4SLinus Torvalds 
2572a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
257345bb4bf0SMarcel Holtmann 
25741da177e4SLinus Torvalds 	hci_dev_lock(hdev);
257545bb4bf0SMarcel Holtmann 
2576a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
25779499237aSMarcel Holtmann 	if (!conn) {
25784f40afc6SAbhishek Pandit-Subedi 		/* Connection may not exist if auto-connected. Check the inquiry
25794f40afc6SAbhishek Pandit-Subedi 		 * cache to see if we've already discovered this bdaddr before.
25804f40afc6SAbhishek Pandit-Subedi 		 * If found and link is an ACL type, create a connection class
25814f40afc6SAbhishek Pandit-Subedi 		 * automatically.
25824f40afc6SAbhishek Pandit-Subedi 		 */
25834f40afc6SAbhishek Pandit-Subedi 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
25844f40afc6SAbhishek Pandit-Subedi 		if (ie && ev->link_type == ACL_LINK) {
25854f40afc6SAbhishek Pandit-Subedi 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
25864f40afc6SAbhishek Pandit-Subedi 					    HCI_ROLE_SLAVE);
25874f40afc6SAbhishek Pandit-Subedi 			if (!conn) {
25884f40afc6SAbhishek Pandit-Subedi 				bt_dev_err(hdev, "no memory for new conn");
25894f40afc6SAbhishek Pandit-Subedi 				goto unlock;
25904f40afc6SAbhishek Pandit-Subedi 			}
25912d186fcdSAbhishek Pandit-Subedi 		} else {
25929499237aSMarcel Holtmann 			if (ev->link_type != SCO_LINK)
25939499237aSMarcel Holtmann 				goto unlock;
25949499237aSMarcel Holtmann 
25952d186fcdSAbhishek Pandit-Subedi 			conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK,
25962d186fcdSAbhishek Pandit-Subedi 						       &ev->bdaddr);
2597a9de9248SMarcel Holtmann 			if (!conn)
2598a9de9248SMarcel Holtmann 				goto unlock;
259945bb4bf0SMarcel Holtmann 
26009499237aSMarcel Holtmann 			conn->type = SCO_LINK;
26019499237aSMarcel Holtmann 		}
26022d186fcdSAbhishek Pandit-Subedi 	}
26039499237aSMarcel Holtmann 
2604a9de9248SMarcel Holtmann 	if (!ev->status) {
2605a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2606769be974SMarcel Holtmann 
2607769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2608769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
2609769be974SMarcel Holtmann 			hci_conn_hold(conn);
2610a9ea3ed9SSzymon Janc 
2611a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
2612a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
2613a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2614a9ea3ed9SSzymon Janc 			else
2615052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2616769be974SMarcel Holtmann 		} else
2617a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
2618a9de9248SMarcel Holtmann 
261923b9ceb7SMarcel Holtmann 		hci_debugfs_create_conn(conn);
26207d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
26217d0db0a3SMarcel Holtmann 
2622a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
26234dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2624a9de9248SMarcel Holtmann 
2625a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
26264dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2627a9de9248SMarcel Holtmann 
2628a9de9248SMarcel Holtmann 		/* Get remote features */
2629a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2630a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
2631a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2632769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
2633769be974SMarcel Holtmann 				     sizeof(cp), &cp);
263422f433dcSJohan Hedberg 
263501b1cb87SJohan Hedberg 			hci_req_update_scan(hdev);
263645bb4bf0SMarcel Holtmann 		}
2637a9de9248SMarcel Holtmann 
2638a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
2639d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
2640a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
2641a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2642a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
264304124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
264404124681SGustavo F. Padovan 				     &cp);
2645a9de9248SMarcel Holtmann 		}
264617d5c04cSJohan Hedberg 	} else {
2647a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
264817d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
264964c7b77cSMarcel Holtmann 			mgmt_connect_failed(hdev, &conn->dst, conn->type,
265048264f06SJohan Hedberg 					    conn->dst_type, ev->status);
265117d5c04cSJohan Hedberg 	}
265245bb4bf0SMarcel Holtmann 
2653e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
2654e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
265545bb4bf0SMarcel Holtmann 
2656769be974SMarcel Holtmann 	if (ev->status) {
2657539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
2658a9de9248SMarcel Holtmann 		hci_conn_del(conn);
26591f8330eaSSathish Narsimman 	} else if (ev->link_type == SCO_LINK) {
26601f8330eaSSathish Narsimman 		switch (conn->setting & SCO_AIRMODE_MASK) {
26611f8330eaSSathish Narsimman 		case SCO_AIRMODE_CVSD:
26621f8330eaSSathish Narsimman 			if (hdev->notify)
26631f8330eaSSathish Narsimman 				hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD);
26641f8330eaSSathish Narsimman 			break;
26651f8330eaSSathish Narsimman 		}
26661f8330eaSSathish Narsimman 
2667539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
26681f8330eaSSathish Narsimman 	}
2669a9de9248SMarcel Holtmann 
2670a9de9248SMarcel Holtmann unlock:
26711da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
2672a9de9248SMarcel Holtmann 
2673a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
26741da177e4SLinus Torvalds }
26751da177e4SLinus Torvalds 
267670c46425SJohan Hedberg static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr)
267770c46425SJohan Hedberg {
267870c46425SJohan Hedberg 	struct hci_cp_reject_conn_req cp;
267970c46425SJohan Hedberg 
268070c46425SJohan Hedberg 	bacpy(&cp.bdaddr, bdaddr);
268170c46425SJohan Hedberg 	cp.reason = HCI_ERROR_REJ_BAD_ADDR;
268270c46425SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
268370c46425SJohan Hedberg }
268470c46425SJohan Hedberg 
26856039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26861da177e4SLinus Torvalds {
2687a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
26881da177e4SLinus Torvalds 	int mask = hdev->link_mode;
268970c46425SJohan Hedberg 	struct inquiry_entry *ie;
269070c46425SJohan Hedberg 	struct hci_conn *conn;
269120714bfeSFrédéric Dalleau 	__u8 flags = 0;
26921da177e4SLinus Torvalds 
26936ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
2694807deac2SGustavo Padovan 	       ev->link_type);
26951da177e4SLinus Torvalds 
269620714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
269720714bfeSFrédéric Dalleau 				      &flags);
26981da177e4SLinus Torvalds 
269970c46425SJohan Hedberg 	if (!(mask & HCI_LM_ACCEPT)) {
270070c46425SJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
270170c46425SJohan Hedberg 		return;
270270c46425SJohan Hedberg 	}
270370c46425SJohan Hedberg 
2704a55bd29dSJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr,
2705dcc36c16SJohan Hedberg 				   BDADDR_BREDR)) {
270670c46425SJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
270770c46425SJohan Hedberg 		return;
270870c46425SJohan Hedberg 	}
270946c4c941SJohan Hedberg 
27106a8fc95cSJohan Hedberg 	/* Require HCI_CONNECTABLE or a whitelist entry to accept the
27116a8fc95cSJohan Hedberg 	 * connection. These features are only touched through mgmt so
27126a8fc95cSJohan Hedberg 	 * only do the checks if HCI_MGMT is set.
27136a8fc95cSJohan Hedberg 	 */
2714d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT) &&
2715d7a5a11dSMarcel Holtmann 	    !hci_dev_test_flag(hdev, HCI_CONNECTABLE) &&
27168baaa403SAbhishek Pandit-Subedi 	    !hci_bdaddr_list_lookup_with_flags(&hdev->whitelist, &ev->bdaddr,
2717a55bd29dSJohan Hedberg 					       BDADDR_BREDR)) {
2718a55bd29dSJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
2719a55bd29dSJohan Hedberg 		return;
2720a55bd29dSJohan Hedberg 	}
272170c46425SJohan Hedberg 
27221da177e4SLinus Torvalds 	/* Connection accepted */
27231da177e4SLinus Torvalds 
27241da177e4SLinus Torvalds 	hci_dev_lock(hdev);
2725b6a0dc82SMarcel Holtmann 
2726cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2727cc11b9c1SAndrei Emeltchenko 	if (ie)
2728c7bdd502SMarcel Holtmann 		memcpy(ie->data.dev_class, ev->dev_class, 3);
2729c7bdd502SMarcel Holtmann 
27308fc9ced3SGustavo Padovan 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
27318fc9ced3SGustavo Padovan 			&ev->bdaddr);
27321da177e4SLinus Torvalds 	if (!conn) {
2733a5c4e309SJohan Hedberg 		conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
2734a5c4e309SJohan Hedberg 				    HCI_ROLE_SLAVE);
2735cc11b9c1SAndrei Emeltchenko 		if (!conn) {
27362064ee33SMarcel Holtmann 			bt_dev_err(hdev, "no memory for new connection");
27371da177e4SLinus Torvalds 			hci_dev_unlock(hdev);
27381da177e4SLinus Torvalds 			return;
27391da177e4SLinus Torvalds 		}
27401da177e4SLinus Torvalds 	}
2741b6a0dc82SMarcel Holtmann 
27421da177e4SLinus Torvalds 	memcpy(conn->dev_class, ev->dev_class, 3);
2743b6a0dc82SMarcel Holtmann 
27441da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27451da177e4SLinus Torvalds 
274620714bfeSFrédéric Dalleau 	if (ev->link_type == ACL_LINK ||
274720714bfeSFrédéric Dalleau 	    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
2748b6a0dc82SMarcel Holtmann 		struct hci_cp_accept_conn_req cp;
274920714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT;
2750b6a0dc82SMarcel Holtmann 
27511da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
27521da177e4SLinus Torvalds 
27531da177e4SLinus Torvalds 		if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
27541da177e4SLinus Torvalds 			cp.role = 0x00; /* Become master */
27551da177e4SLinus Torvalds 		else
27561da177e4SLinus Torvalds 			cp.role = 0x01; /* Remain slave */
27571da177e4SLinus Torvalds 
275870c46425SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
275920714bfeSFrédéric Dalleau 	} else if (!(flags & HCI_PROTO_DEFER)) {
2760b6a0dc82SMarcel Holtmann 		struct hci_cp_accept_sync_conn_req cp;
276120714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT;
2762b6a0dc82SMarcel Holtmann 
2763b6a0dc82SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
2764a8746417SMarcel Holtmann 		cp.pkt_type = cpu_to_le16(conn->pkt_type);
2765b6a0dc82SMarcel Holtmann 
2766dcf4adbfSJoe Perches 		cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
2767dcf4adbfSJoe Perches 		cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
2768dcf4adbfSJoe Perches 		cp.max_latency    = cpu_to_le16(0xffff);
2769b6a0dc82SMarcel Holtmann 		cp.content_format = cpu_to_le16(hdev->voice_setting);
2770b6a0dc82SMarcel Holtmann 		cp.retrans_effort = 0xff;
2771b6a0dc82SMarcel Holtmann 
277270c46425SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(cp),
277370c46425SJohan Hedberg 			     &cp);
277420714bfeSFrédéric Dalleau 	} else {
277520714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT2;
2776539c496dSJohan Hedberg 		hci_connect_cfm(conn, 0);
2777b6a0dc82SMarcel Holtmann 	}
27781da177e4SLinus Torvalds }
27791da177e4SLinus Torvalds 
2780f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2781f0d6a0eaSMikel Astiz {
2782f0d6a0eaSMikel Astiz 	switch (err) {
2783f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2784f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2785f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2786f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2787f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2788f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2789f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2790f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2791f0d6a0eaSMikel Astiz 	default:
2792f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2793f0d6a0eaSMikel Astiz 	}
2794f0d6a0eaSMikel Astiz }
2795f0d6a0eaSMikel Astiz 
27966039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
27971da177e4SLinus Torvalds {
2798a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
2799160b9251SSzymon Janc 	u8 reason;
28009fcb18efSAndre Guedes 	struct hci_conn_params *params;
280104837f64SMarcel Holtmann 	struct hci_conn *conn;
280212d4a3b2SJohan Hedberg 	bool mgmt_connected;
28033846220bSAndre Guedes 	u8 type;
28041da177e4SLinus Torvalds 
28059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
28061da177e4SLinus Torvalds 
28071da177e4SLinus Torvalds 	hci_dev_lock(hdev);
28081da177e4SLinus Torvalds 
280904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2810f7520543SJohan Hedberg 	if (!conn)
2811f7520543SJohan Hedberg 		goto unlock;
2812f7520543SJohan Hedberg 
2813f0d6a0eaSMikel Astiz 	if (ev->status) {
281488c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
281588c3df13SJohan Hedberg 				       conn->dst_type, ev->status);
2816abf54a50SAndre Guedes 		goto unlock;
2817abf54a50SAndre Guedes 	}
2818f0d6a0eaSMikel Astiz 
28193846220bSAndre Guedes 	conn->state = BT_CLOSED;
28203846220bSAndre Guedes 
282112d4a3b2SJohan Hedberg 	mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
2822160b9251SSzymon Janc 
2823160b9251SSzymon Janc 	if (test_bit(HCI_CONN_AUTH_FAILURE, &conn->flags))
2824160b9251SSzymon Janc 		reason = MGMT_DEV_DISCONN_AUTH_FAILURE;
2825160b9251SSzymon Janc 	else
2826160b9251SSzymon Janc 		reason = hci_to_mgmt_reason(ev->reason);
2827160b9251SSzymon Janc 
282812d4a3b2SJohan Hedberg 	mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
282912d4a3b2SJohan Hedberg 				reason, mgmt_connected);
2830f7520543SJohan Hedberg 
283122f433dcSJohan Hedberg 	if (conn->type == ACL_LINK) {
283222f433dcSJohan Hedberg 		if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
28336ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
28343846220bSAndre Guedes 
283501b1cb87SJohan Hedberg 		hci_req_update_scan(hdev);
283622f433dcSJohan Hedberg 	}
283722f433dcSJohan Hedberg 
28389fcb18efSAndre Guedes 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
28399fcb18efSAndre Guedes 	if (params) {
28409fcb18efSAndre Guedes 		switch (params->auto_connect) {
28419fcb18efSAndre Guedes 		case HCI_AUTO_CONN_LINK_LOSS:
28429fcb18efSAndre Guedes 			if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
28439fcb18efSAndre Guedes 				break;
284419186c7bSGustavo A. R. Silva 			fallthrough;
28459fcb18efSAndre Guedes 
28464b9e7e75SMarcel Holtmann 		case HCI_AUTO_CONN_DIRECT:
28479fcb18efSAndre Guedes 		case HCI_AUTO_CONN_ALWAYS:
2848418025d1SJohan Hedberg 			list_del_init(&params->action);
2849418025d1SJohan Hedberg 			list_add(&params->action, &hdev->pend_le_conns);
2850418025d1SJohan Hedberg 			hci_update_background_scan(hdev);
28519fcb18efSAndre Guedes 			break;
28529fcb18efSAndre Guedes 
28539fcb18efSAndre Guedes 		default:
28549fcb18efSAndre Guedes 			break;
28559fcb18efSAndre Guedes 		}
28569fcb18efSAndre Guedes 	}
28579fcb18efSAndre Guedes 
28583846220bSAndre Guedes 	type = conn->type;
28593846220bSAndre Guedes 
28603a6d576bSJohan Hedberg 	hci_disconn_cfm(conn, ev->reason);
28611da177e4SLinus Torvalds 	hci_conn_del(conn);
28622210246cSJohan Hedberg 
28634f40afc6SAbhishek Pandit-Subedi 	/* The suspend notifier is waiting for all devices to disconnect so
28644f40afc6SAbhishek Pandit-Subedi 	 * clear the bit from pending tasks and inform the wait queue.
28654f40afc6SAbhishek Pandit-Subedi 	 */
28664f40afc6SAbhishek Pandit-Subedi 	if (list_empty(&hdev->conn_hash.list) &&
28674f40afc6SAbhishek Pandit-Subedi 	    test_and_clear_bit(SUSPEND_DISCONNECTING, hdev->suspend_tasks)) {
28684f40afc6SAbhishek Pandit-Subedi 		wake_up(&hdev->suspend_wait_q);
28694f40afc6SAbhishek Pandit-Subedi 	}
28704f40afc6SAbhishek Pandit-Subedi 
28712210246cSJohan Hedberg 	/* Re-enable advertising if necessary, since it might
28722210246cSJohan Hedberg 	 * have been disabled by the connection. From the
28732210246cSJohan Hedberg 	 * HCI_LE_Set_Advertise_Enable command description in
28742210246cSJohan Hedberg 	 * the core specification (v4.0):
28752210246cSJohan Hedberg 	 * "The Controller shall continue advertising until the Host
28762210246cSJohan Hedberg 	 * issues an LE_Set_Advertise_Enable command with
28772210246cSJohan Hedberg 	 * Advertising_Enable set to 0x00 (Advertising is disabled)
28782210246cSJohan Hedberg 	 * or until a connection is created or until the Advertising
28792210246cSJohan Hedberg 	 * is timed out due to Directed Advertising."
28802210246cSJohan Hedberg 	 */
28812210246cSJohan Hedberg 	if (type == LE_LINK)
2882f2252570SJohan Hedberg 		hci_req_reenable_advertising(hdev);
28831da177e4SLinus Torvalds 
2884f7520543SJohan Hedberg unlock:
28851da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
28861da177e4SLinus Torvalds }
28871da177e4SLinus Torvalds 
28886039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2889a9de9248SMarcel Holtmann {
2890a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2891a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2892a9de9248SMarcel Holtmann 
28939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2894a9de9248SMarcel Holtmann 
2895a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2896a9de9248SMarcel Holtmann 
2897a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2898d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2899d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2900d7556e20SWaldemar Rymarkiewicz 
2901765c2a96SJohan Hedberg 	if (!ev->status) {
2902160b9251SSzymon Janc 		clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
2903160b9251SSzymon Janc 
2904aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
290551a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
29062064ee33SMarcel Holtmann 			bt_dev_info(hdev, "re-auth of legacy device is not possible.");
290719f8def0SWaldemar Rymarkiewicz 		} else {
29084dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2909765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
291019f8def0SWaldemar Rymarkiewicz 		}
29112a611692SJohan Hedberg 	} else {
2912160b9251SSzymon Janc 		if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
2913160b9251SSzymon Janc 			set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
2914160b9251SSzymon Janc 
2915e1e930f5SJohan Hedberg 		mgmt_auth_failed(conn, ev->status);
29162a611692SJohan Hedberg 	}
2917a9de9248SMarcel Holtmann 
291851a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
291951a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2920a9de9248SMarcel Holtmann 
2921f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2922aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2923f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2924f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2925f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2926d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2927d7556e20SWaldemar Rymarkiewicz 				     &cp);
2928f8558555SMarcel Holtmann 		} else {
2929f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2930539c496dSJohan Hedberg 			hci_connect_cfm(conn, ev->status);
293176a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2932f8558555SMarcel Holtmann 		}
2933052b30b0SMarcel Holtmann 	} else {
2934a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2935a9de9248SMarcel Holtmann 
2936052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2937052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
293876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2939052b30b0SMarcel Holtmann 	}
2940052b30b0SMarcel Holtmann 
294151a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2942a9de9248SMarcel Holtmann 		if (!ev->status) {
2943a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2944f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2945f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2946d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2947d7556e20SWaldemar Rymarkiewicz 				     &cp);
2948a9de9248SMarcel Holtmann 		} else {
294951a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
29503ca44c16SLuiz Augusto von Dentz 			hci_encrypt_cfm(conn, ev->status);
2951a9de9248SMarcel Holtmann 		}
2952a9de9248SMarcel Holtmann 	}
2953a9de9248SMarcel Holtmann 
2954d7556e20SWaldemar Rymarkiewicz unlock:
2955a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2956a9de9248SMarcel Holtmann }
2957a9de9248SMarcel Holtmann 
29586039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2959a9de9248SMarcel Holtmann {
2960127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2961127178d2SJohan Hedberg 	struct hci_conn *conn;
2962127178d2SJohan Hedberg 
2963a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2964a9de9248SMarcel Holtmann 
2965a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2966127178d2SJohan Hedberg 
2967127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2968127178d2SJohan Hedberg 
2969127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2970b644ba33SJohan Hedberg 
2971d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
2972b644ba33SJohan Hedberg 		goto check_auth;
2973b644ba33SJohan Hedberg 
2974b644ba33SJohan Hedberg 	if (ev->status == 0)
2975b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2976b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2977b644ba33SJohan Hedberg 	else
2978b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2979b644ba33SJohan Hedberg 
2980b644ba33SJohan Hedberg check_auth:
298179c6c70cSJohan Hedberg 	if (!conn)
298279c6c70cSJohan Hedberg 		goto unlock;
298379c6c70cSJohan Hedberg 
298479c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
298579c6c70cSJohan Hedberg 		goto unlock;
298679c6c70cSJohan Hedberg 
298751a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2988127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2989977f8fceSJohan Hedberg 
2990977f8fceSJohan Hedberg 		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
2991977f8fceSJohan Hedberg 
2992127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2993127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2994127178d2SJohan Hedberg 	}
2995127178d2SJohan Hedberg 
299679c6c70cSJohan Hedberg unlock:
2997127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2998a9de9248SMarcel Holtmann }
2999a9de9248SMarcel Holtmann 
3000821f3766SJohan Hedberg static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status,
3001821f3766SJohan Hedberg 				       u16 opcode, struct sk_buff *skb)
3002821f3766SJohan Hedberg {
3003821f3766SJohan Hedberg 	const struct hci_rp_read_enc_key_size *rp;
3004821f3766SJohan Hedberg 	struct hci_conn *conn;
3005821f3766SJohan Hedberg 	u16 handle;
3006821f3766SJohan Hedberg 
3007821f3766SJohan Hedberg 	BT_DBG("%s status 0x%02x", hdev->name, status);
3008821f3766SJohan Hedberg 
3009821f3766SJohan Hedberg 	if (!skb || skb->len < sizeof(*rp)) {
30102064ee33SMarcel Holtmann 		bt_dev_err(hdev, "invalid read key size response");
3011821f3766SJohan Hedberg 		return;
3012821f3766SJohan Hedberg 	}
3013821f3766SJohan Hedberg 
3014821f3766SJohan Hedberg 	rp = (void *)skb->data;
3015821f3766SJohan Hedberg 	handle = le16_to_cpu(rp->handle);
3016821f3766SJohan Hedberg 
3017821f3766SJohan Hedberg 	hci_dev_lock(hdev);
3018821f3766SJohan Hedberg 
3019821f3766SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, handle);
3020821f3766SJohan Hedberg 	if (!conn)
3021821f3766SJohan Hedberg 		goto unlock;
3022821f3766SJohan Hedberg 
302332b50729SAlain Michaud 	/* While unexpected, the read_enc_key_size command may fail. The most
302432b50729SAlain Michaud 	 * secure approach is to then assume the key size is 0 to force a
302532b50729SAlain Michaud 	 * disconnection.
3026821f3766SJohan Hedberg 	 */
3027821f3766SJohan Hedberg 	if (rp->status) {
30282064ee33SMarcel Holtmann 		bt_dev_err(hdev, "failed to read key size for handle %u",
3029821f3766SJohan Hedberg 			   handle);
303032b50729SAlain Michaud 		conn->enc_key_size = 0;
3031821f3766SJohan Hedberg 	} else {
3032821f3766SJohan Hedberg 		conn->enc_key_size = rp->key_size;
3033821f3766SJohan Hedberg 	}
3034821f3766SJohan Hedberg 
30353ca44c16SLuiz Augusto von Dentz 	hci_encrypt_cfm(conn, 0);
3036821f3766SJohan Hedberg 
3037821f3766SJohan Hedberg unlock:
3038821f3766SJohan Hedberg 	hci_dev_unlock(hdev);
3039821f3766SJohan Hedberg }
3040821f3766SJohan Hedberg 
30416039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3042a9de9248SMarcel Holtmann {
3043a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
3044a9de9248SMarcel Holtmann 	struct hci_conn *conn;
3045a9de9248SMarcel Holtmann 
30469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3047a9de9248SMarcel Holtmann 
3048a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3049a9de9248SMarcel Holtmann 
3050a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3051dc8357ccSMarcel Holtmann 	if (!conn)
3052dc8357ccSMarcel Holtmann 		goto unlock;
3053dc8357ccSMarcel Holtmann 
3054a9de9248SMarcel Holtmann 	if (!ev->status) {
3055ae293196SMarcel Holtmann 		if (ev->encrypt) {
3056ae293196SMarcel Holtmann 			/* Encryption implies authentication */
30574dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
30584dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
3059da85e5e5SVinicius Costa Gomes 			conn->sec_level = conn->pending_sec_level;
3060abf76badSMarcel Holtmann 
3061914a6ffeSMarcel Holtmann 			/* P-256 authentication key implies FIPS */
3062914a6ffeSMarcel Holtmann 			if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
30634dae2798SJohan Hedberg 				set_bit(HCI_CONN_FIPS, &conn->flags);
3064914a6ffeSMarcel Holtmann 
3065abf76badSMarcel Holtmann 			if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
3066abf76badSMarcel Holtmann 			    conn->type == LE_LINK)
3067abf76badSMarcel Holtmann 				set_bit(HCI_CONN_AES_CCM, &conn->flags);
3068abf76badSMarcel Holtmann 		} else {
30694dae2798SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
3070abf76badSMarcel Holtmann 			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
3071abf76badSMarcel Holtmann 		}
3072a9de9248SMarcel Holtmann 	}
3073a9de9248SMarcel Holtmann 
30747ed3fa20SJohan Hedberg 	/* We should disregard the current RPA and generate a new one
30757ed3fa20SJohan Hedberg 	 * whenever the encryption procedure fails.
30767ed3fa20SJohan Hedberg 	 */
3077a73c046aSJaganath Kanakkassery 	if (ev->status && conn->type == LE_LINK) {
3078a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
3079a73c046aSJaganath Kanakkassery 		hci_adv_instances_set_rpa_expired(hdev, true);
3080a73c046aSJaganath Kanakkassery 	}
30817ed3fa20SJohan Hedberg 
308251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
3083a9de9248SMarcel Holtmann 
30848746f135SLuiz Augusto von Dentz 	/* Check link security requirements are met */
30858746f135SLuiz Augusto von Dentz 	if (!hci_conn_check_link_mode(conn))
30868746f135SLuiz Augusto von Dentz 		ev->status = HCI_ERROR_AUTH_FAILURE;
30878746f135SLuiz Augusto von Dentz 
3088a7d7723aSGustavo Padovan 	if (ev->status && conn->state == BT_CONNECTED) {
3089160b9251SSzymon Janc 		if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
3090160b9251SSzymon Janc 			set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
3091160b9251SSzymon Janc 
30928746f135SLuiz Augusto von Dentz 		/* Notify upper layers so they can cleanup before
30938746f135SLuiz Augusto von Dentz 		 * disconnecting.
309440b552aaSMarcel Holtmann 		 */
30958746f135SLuiz Augusto von Dentz 		hci_encrypt_cfm(conn, ev->status);
30968746f135SLuiz Augusto von Dentz 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
309740b552aaSMarcel Holtmann 		hci_conn_drop(conn);
309840b552aaSMarcel Holtmann 		goto unlock;
309940b552aaSMarcel Holtmann 	}
310040b552aaSMarcel Holtmann 
3101821f3766SJohan Hedberg 	/* Try reading the encryption key size for encrypted ACL links */
3102821f3766SJohan Hedberg 	if (!ev->status && ev->encrypt && conn->type == ACL_LINK) {
3103821f3766SJohan Hedberg 		struct hci_cp_read_enc_key_size cp;
3104821f3766SJohan Hedberg 		struct hci_request req;
3105821f3766SJohan Hedberg 
3106821f3766SJohan Hedberg 		/* Only send HCI_Read_Encryption_Key_Size if the
3107821f3766SJohan Hedberg 		 * controller really supports it. If it doesn't, assume
3108821f3766SJohan Hedberg 		 * the default size (16).
3109821f3766SJohan Hedberg 		 */
3110821f3766SJohan Hedberg 		if (!(hdev->commands[20] & 0x10)) {
3111821f3766SJohan Hedberg 			conn->enc_key_size = HCI_LINK_KEY_SIZE;
3112821f3766SJohan Hedberg 			goto notify;
3113821f3766SJohan Hedberg 		}
3114821f3766SJohan Hedberg 
3115821f3766SJohan Hedberg 		hci_req_init(&req, hdev);
3116821f3766SJohan Hedberg 
3117821f3766SJohan Hedberg 		cp.handle = cpu_to_le16(conn->handle);
3118821f3766SJohan Hedberg 		hci_req_add(&req, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp);
3119821f3766SJohan Hedberg 
3120821f3766SJohan Hedberg 		if (hci_req_run_skb(&req, read_enc_key_size_complete)) {
31212064ee33SMarcel Holtmann 			bt_dev_err(hdev, "sending read key size failed");
3122821f3766SJohan Hedberg 			conn->enc_key_size = HCI_LINK_KEY_SIZE;
3123821f3766SJohan Hedberg 			goto notify;
3124821f3766SJohan Hedberg 		}
3125821f3766SJohan Hedberg 
3126821f3766SJohan Hedberg 		goto unlock;
3127821f3766SJohan Hedberg 	}
3128821f3766SJohan Hedberg 
3129302975cbSSpoorthi Ravishankar Koppad 	/* Set the default Authenticated Payload Timeout after
3130302975cbSSpoorthi Ravishankar Koppad 	 * an LE Link is established. As per Core Spec v5.0, Vol 2, Part B
3131302975cbSSpoorthi Ravishankar Koppad 	 * Section 3.3, the HCI command WRITE_AUTH_PAYLOAD_TIMEOUT should be
3132302975cbSSpoorthi Ravishankar Koppad 	 * sent when the link is active and Encryption is enabled, the conn
3133302975cbSSpoorthi Ravishankar Koppad 	 * type can be either LE or ACL and controller must support LMP Ping.
3134302975cbSSpoorthi Ravishankar Koppad 	 * Ensure for AES-CCM encryption as well.
3135302975cbSSpoorthi Ravishankar Koppad 	 */
3136302975cbSSpoorthi Ravishankar Koppad 	if (test_bit(HCI_CONN_ENCRYPT, &conn->flags) &&
3137302975cbSSpoorthi Ravishankar Koppad 	    test_bit(HCI_CONN_AES_CCM, &conn->flags) &&
3138302975cbSSpoorthi Ravishankar Koppad 	    ((conn->type == ACL_LINK && lmp_ping_capable(hdev)) ||
3139302975cbSSpoorthi Ravishankar Koppad 	     (conn->type == LE_LINK && (hdev->le_features[0] & HCI_LE_PING)))) {
3140302975cbSSpoorthi Ravishankar Koppad 		struct hci_cp_write_auth_payload_to cp;
3141302975cbSSpoorthi Ravishankar Koppad 
3142302975cbSSpoorthi Ravishankar Koppad 		cp.handle = cpu_to_le16(conn->handle);
3143302975cbSSpoorthi Ravishankar Koppad 		cp.timeout = cpu_to_le16(hdev->auth_payload_timeout);
3144302975cbSSpoorthi Ravishankar Koppad 		hci_send_cmd(conn->hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO,
3145302975cbSSpoorthi Ravishankar Koppad 			     sizeof(cp), &cp);
3146302975cbSSpoorthi Ravishankar Koppad 	}
3147302975cbSSpoorthi Ravishankar Koppad 
3148821f3766SJohan Hedberg notify:
31493ca44c16SLuiz Augusto von Dentz 	hci_encrypt_cfm(conn, ev->status);
3150a9de9248SMarcel Holtmann 
3151a7d7723aSGustavo Padovan unlock:
3152a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3153a9de9248SMarcel Holtmann }
3154a9de9248SMarcel Holtmann 
31556039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
3156807deac2SGustavo Padovan 					     struct sk_buff *skb)
3157a9de9248SMarcel Holtmann {
3158a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
3159a9de9248SMarcel Holtmann 	struct hci_conn *conn;
3160a9de9248SMarcel Holtmann 
31619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3162a9de9248SMarcel Holtmann 
3163a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3164a9de9248SMarcel Holtmann 
3165a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3166a9de9248SMarcel Holtmann 	if (conn) {
3167a9de9248SMarcel Holtmann 		if (!ev->status)
31684dae2798SJohan Hedberg 			set_bit(HCI_CONN_SECURE, &conn->flags);
3169a9de9248SMarcel Holtmann 
317051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
3171a9de9248SMarcel Holtmann 
3172a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
3173a9de9248SMarcel Holtmann 	}
3174a9de9248SMarcel Holtmann 
3175a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3176a9de9248SMarcel Holtmann }
3177a9de9248SMarcel Holtmann 
31786039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
3179807deac2SGustavo Padovan 				    struct sk_buff *skb)
3180a9de9248SMarcel Holtmann {
3181a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
3182a9de9248SMarcel Holtmann 	struct hci_conn *conn;
3183a9de9248SMarcel Holtmann 
31849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3185a9de9248SMarcel Holtmann 
3186a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3187a9de9248SMarcel Holtmann 
3188a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3189ccd556feSJohan Hedberg 	if (!conn)
3190ccd556feSJohan Hedberg 		goto unlock;
3191ccd556feSJohan Hedberg 
3192769be974SMarcel Holtmann 	if (!ev->status)
3193cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
3194a9de9248SMarcel Holtmann 
3195ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3196ccd556feSJohan Hedberg 		goto unlock;
3197ccd556feSJohan Hedberg 
3198ac363cf9SSzymon Janc 	if (!ev->status && lmp_ext_feat_capable(hdev) &&
3199ac363cf9SSzymon Janc 	    lmp_ext_feat_capable(conn)) {
3200769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
3201769be974SMarcel Holtmann 		cp.handle = ev->handle;
3202769be974SMarcel Holtmann 		cp.page = 0x01;
3203ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
3204769be974SMarcel Holtmann 			     sizeof(cp), &cp);
3205392599b9SJohan Hedberg 		goto unlock;
3206392599b9SJohan Hedberg 	}
3207392599b9SJohan Hedberg 
3208671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3209127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3210127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3211127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3212127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3213127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3214b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
321548ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
3216392599b9SJohan Hedberg 
3217127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3218769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3219539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
322076a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3221769be974SMarcel Holtmann 	}
3222769be974SMarcel Holtmann 
3223ccd556feSJohan Hedberg unlock:
3224a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3225a9de9248SMarcel Holtmann }
3226a9de9248SMarcel Holtmann 
3227e6214487SJohan Hedberg static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
3228e6214487SJohan Hedberg 				 u16 *opcode, u8 *status,
3229e6214487SJohan Hedberg 				 hci_req_complete_t *req_complete,
3230e6214487SJohan Hedberg 				 hci_req_complete_skb_t *req_complete_skb)
3231a9de9248SMarcel Holtmann {
3232a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
3233e6214487SJohan Hedberg 
3234e6214487SJohan Hedberg 	*opcode = __le16_to_cpu(ev->opcode);
3235e6214487SJohan Hedberg 	*status = skb->data[sizeof(*ev)];
3236a9de9248SMarcel Holtmann 
3237a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
3238a9de9248SMarcel Holtmann 
3239e6214487SJohan Hedberg 	switch (*opcode) {
3240a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
3241adf1d692SSonny Sasaka 		hci_cc_inquiry_cancel(hdev, skb, status);
3242a9de9248SMarcel Holtmann 		break;
3243a9de9248SMarcel Holtmann 
32444d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
32454d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
32464d93483bSAndre Guedes 		break;
32474d93483bSAndre Guedes 
3248a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
3249a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
3250a9de9248SMarcel Holtmann 		break;
3251a9de9248SMarcel Holtmann 
3252a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
3253a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
3254a9de9248SMarcel Holtmann 		break;
3255a9de9248SMarcel Holtmann 
3256a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
3257a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
3258a9de9248SMarcel Holtmann 		break;
3259a9de9248SMarcel Holtmann 
3260e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
3261e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
3262e4e8e37cSMarcel Holtmann 		break;
3263e4e8e37cSMarcel Holtmann 
3264a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
3265a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
3266a9de9248SMarcel Holtmann 		break;
3267a9de9248SMarcel Holtmann 
3268e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
3269e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
3270e4e8e37cSMarcel Holtmann 		break;
3271e4e8e37cSMarcel Holtmann 
3272e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
3273e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
3274e4e8e37cSMarcel Holtmann 		break;
3275e4e8e37cSMarcel Holtmann 
3276a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
3277a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
3278a9de9248SMarcel Holtmann 		break;
3279a9de9248SMarcel Holtmann 
3280c2f0f979SMarcel Holtmann 	case HCI_OP_READ_STORED_LINK_KEY:
3281c2f0f979SMarcel Holtmann 		hci_cc_read_stored_link_key(hdev, skb);
3282c2f0f979SMarcel Holtmann 		break;
3283c2f0f979SMarcel Holtmann 
3284a9366120SMarcel Holtmann 	case HCI_OP_DELETE_STORED_LINK_KEY:
3285a9366120SMarcel Holtmann 		hci_cc_delete_stored_link_key(hdev, skb);
3286a9366120SMarcel Holtmann 		break;
3287a9366120SMarcel Holtmann 
3288a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
3289a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
3290a9de9248SMarcel Holtmann 		break;
3291a9de9248SMarcel Holtmann 
3292a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
3293a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
3294a9de9248SMarcel Holtmann 		break;
3295a9de9248SMarcel Holtmann 
3296a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
3297a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
3298a9de9248SMarcel Holtmann 		break;
3299a9de9248SMarcel Holtmann 
3300a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
3301a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
3302a9de9248SMarcel Holtmann 		break;
3303a9de9248SMarcel Holtmann 
3304a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
3305a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
3306a9de9248SMarcel Holtmann 		break;
3307a9de9248SMarcel Holtmann 
3308a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
3309a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
3310a9de9248SMarcel Holtmann 		break;
3311a9de9248SMarcel Holtmann 
3312a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
3313a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
3314a9de9248SMarcel Holtmann 		break;
3315a9de9248SMarcel Holtmann 
3316a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
3317a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
3318a9de9248SMarcel Holtmann 		break;
3319a9de9248SMarcel Holtmann 
3320a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
3321a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
3322a9de9248SMarcel Holtmann 		break;
3323a9de9248SMarcel Holtmann 
3324b4cb9fb2SMarcel Holtmann 	case HCI_OP_READ_NUM_SUPPORTED_IAC:
3325b4cb9fb2SMarcel Holtmann 		hci_cc_read_num_supported_iac(hdev, skb);
3326b4cb9fb2SMarcel Holtmann 		break;
3327b4cb9fb2SMarcel Holtmann 
3328333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
3329333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
3330333140b5SMarcel Holtmann 		break;
3331333140b5SMarcel Holtmann 
3332eac83dc6SMarcel Holtmann 	case HCI_OP_WRITE_SC_SUPPORT:
3333eac83dc6SMarcel Holtmann 		hci_cc_write_sc_support(hdev, skb);
3334eac83dc6SMarcel Holtmann 		break;
3335eac83dc6SMarcel Holtmann 
3336302975cbSSpoorthi Ravishankar Koppad 	case HCI_OP_READ_AUTH_PAYLOAD_TO:
3337302975cbSSpoorthi Ravishankar Koppad 		hci_cc_read_auth_payload_timeout(hdev, skb);
3338302975cbSSpoorthi Ravishankar Koppad 		break;
3339302975cbSSpoorthi Ravishankar Koppad 
3340302975cbSSpoorthi Ravishankar Koppad 	case HCI_OP_WRITE_AUTH_PAYLOAD_TO:
3341302975cbSSpoorthi Ravishankar Koppad 		hci_cc_write_auth_payload_timeout(hdev, skb);
3342302975cbSSpoorthi Ravishankar Koppad 		break;
3343302975cbSSpoorthi Ravishankar Koppad 
3344a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
3345a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
3346a9de9248SMarcel Holtmann 		break;
3347a9de9248SMarcel Holtmann 
3348a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
3349a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
3350a9de9248SMarcel Holtmann 		break;
3351a9de9248SMarcel Holtmann 
3352a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
3353a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
3354a9de9248SMarcel Holtmann 		break;
3355a9de9248SMarcel Holtmann 
3356971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
3357971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
3358971e3a4bSAndre Guedes 		break;
3359971e3a4bSAndre Guedes 
3360a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
3361a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
3362a9de9248SMarcel Holtmann 		break;
3363a9de9248SMarcel Holtmann 
3364a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
3365a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
3366a9de9248SMarcel Holtmann 		break;
3367a9de9248SMarcel Holtmann 
3368a4790360SMarcel Holtmann 	case HCI_OP_READ_LOCAL_PAIRING_OPTS:
3369a4790360SMarcel Holtmann 		hci_cc_read_local_pairing_opts(hdev, skb);
3370a4790360SMarcel Holtmann 		break;
3371a4790360SMarcel Holtmann 
3372f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
3373f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
3374f332ec66SJohan Hedberg 		break;
3375f332ec66SJohan Hedberg 
33764a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
33774a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
33784a3ee763SJohan Hedberg 		break;
33794a3ee763SJohan Hedberg 
3380f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
3381f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
3382f332ec66SJohan Hedberg 		break;
3383f332ec66SJohan Hedberg 
33844a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
33854a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
33864a3ee763SJohan Hedberg 		break;
33874a3ee763SJohan Hedberg 
3388350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
3389350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
3390350ee4cfSAndrei Emeltchenko 		break;
3391350ee4cfSAndrei Emeltchenko 
33921e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
33931e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
33941e89cffbSAndrei Emeltchenko 		break;
33951e89cffbSAndrei Emeltchenko 
3396928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
3397928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
3398928abaa7SAndrei Emeltchenko 		break;
3399928abaa7SAndrei Emeltchenko 
340033f35721SJohan Hedberg 	case HCI_OP_READ_CLOCK:
340133f35721SJohan Hedberg 		hci_cc_read_clock(hdev, skb);
340233f35721SJohan Hedberg 		break;
340333f35721SJohan Hedberg 
3404d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
3405d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
3406d5859e22SJohan Hedberg 		break;
3407d5859e22SJohan Hedberg 
340800bce3fbSAlain Michaud 	case HCI_OP_READ_DEF_ERR_DATA_REPORTING:
340900bce3fbSAlain Michaud 		hci_cc_read_def_err_data_reporting(hdev, skb);
341000bce3fbSAlain Michaud 		break;
341100bce3fbSAlain Michaud 
341200bce3fbSAlain Michaud 	case HCI_OP_WRITE_DEF_ERR_DATA_REPORTING:
341300bce3fbSAlain Michaud 		hci_cc_write_def_err_data_reporting(hdev, skb);
341400bce3fbSAlain Michaud 		break;
341500bce3fbSAlain Michaud 
3416980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
3417980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
3418980e1a53SJohan Hedberg 		break;
3419980e1a53SJohan Hedberg 
3420980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
3421980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
3422980e1a53SJohan Hedberg 		break;
3423980e1a53SJohan Hedberg 
3424c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
34254d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_data(hdev, skb);
34264d2d2796SMarcel Holtmann 		break;
34274d2d2796SMarcel Holtmann 
34284d2d2796SMarcel Holtmann 	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
34294d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_ext_data(hdev, skb);
3430c35938b2SSzymon Janc 		break;
3431c35938b2SSzymon Janc 
34326ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
34336ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
34346ed58ec5SVille Tervo 		break;
34356ed58ec5SVille Tervo 
343660e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
343760e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
343860e77321SJohan Hedberg 		break;
343960e77321SJohan Hedberg 
34408fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
34418fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
34428fa19098SJohan Hedberg 		break;
34438fa19098SJohan Hedberg 
3444a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
3445a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
3446a5c29683SJohan Hedberg 		break;
3447a5c29683SJohan Hedberg 
3448a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
3449a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
3450a5c29683SJohan Hedberg 		break;
3451a5c29683SJohan Hedberg 
34521143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
34531143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
34541143d458SBrian Gix 		break;
34551143d458SBrian Gix 
34561143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
34571143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
345816cde993SSzymon Janc 		break;
345907f7fa5dSAndre Guedes 
34607a4cd51dSMarcel Holtmann 	case HCI_OP_LE_SET_RANDOM_ADDR:
34617a4cd51dSMarcel Holtmann 		hci_cc_le_set_random_addr(hdev, skb);
34627a4cd51dSMarcel Holtmann 		break;
34637a4cd51dSMarcel Holtmann 
3464c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
3465c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
3466c1d5dc4aSJohan Hedberg 		break;
3467c1d5dc4aSJohan Hedberg 
3468533553f8SMarcel Holtmann 	case HCI_OP_LE_SET_SCAN_PARAM:
3469533553f8SMarcel Holtmann 		hci_cc_le_set_scan_param(hdev, skb);
3470533553f8SMarcel Holtmann 		break;
3471533553f8SMarcel Holtmann 
3472eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
3473eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
3474eb9d91f5SAndre Guedes 		break;
3475eb9d91f5SAndre Guedes 
3476cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
3477cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
3478cf1d081fSJohan Hedberg 		break;
3479cf1d081fSJohan Hedberg 
34800f36b589SMarcel Holtmann 	case HCI_OP_LE_CLEAR_WHITE_LIST:
34810f36b589SMarcel Holtmann 		hci_cc_le_clear_white_list(hdev, skb);
34820f36b589SMarcel Holtmann 		break;
34830f36b589SMarcel Holtmann 
34840f36b589SMarcel Holtmann 	case HCI_OP_LE_ADD_TO_WHITE_LIST:
34850f36b589SMarcel Holtmann 		hci_cc_le_add_to_white_list(hdev, skb);
34860f36b589SMarcel Holtmann 		break;
34870f36b589SMarcel Holtmann 
34880f36b589SMarcel Holtmann 	case HCI_OP_LE_DEL_FROM_WHITE_LIST:
34890f36b589SMarcel Holtmann 		hci_cc_le_del_from_white_list(hdev, skb);
34900f36b589SMarcel Holtmann 		break;
34910f36b589SMarcel Holtmann 
34929b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
34939b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
34949b008c04SJohan Hedberg 		break;
34959b008c04SJohan Hedberg 
3496a8e1bfaaSMarcel Holtmann 	case HCI_OP_LE_READ_DEF_DATA_LEN:
3497a8e1bfaaSMarcel Holtmann 		hci_cc_le_read_def_data_len(hdev, skb);
3498a8e1bfaaSMarcel Holtmann 		break;
3499a8e1bfaaSMarcel Holtmann 
3500a8e1bfaaSMarcel Holtmann 	case HCI_OP_LE_WRITE_DEF_DATA_LEN:
3501a8e1bfaaSMarcel Holtmann 		hci_cc_le_write_def_data_len(hdev, skb);
3502a8e1bfaaSMarcel Holtmann 		break;
3503a8e1bfaaSMarcel Holtmann 
3504b950aa88SAnkit Navik 	case HCI_OP_LE_ADD_TO_RESOLV_LIST:
3505b950aa88SAnkit Navik 		hci_cc_le_add_to_resolv_list(hdev, skb);
3506b950aa88SAnkit Navik 		break;
3507b950aa88SAnkit Navik 
3508b950aa88SAnkit Navik 	case HCI_OP_LE_DEL_FROM_RESOLV_LIST:
3509b950aa88SAnkit Navik 		hci_cc_le_del_from_resolv_list(hdev, skb);
3510b950aa88SAnkit Navik 		break;
3511b950aa88SAnkit Navik 
3512545f2596SAnkit Navik 	case HCI_OP_LE_CLEAR_RESOLV_LIST:
3513545f2596SAnkit Navik 		hci_cc_le_clear_resolv_list(hdev, skb);
3514545f2596SAnkit Navik 		break;
3515545f2596SAnkit Navik 
3516cfdb0c2dSAnkit Navik 	case HCI_OP_LE_READ_RESOLV_LIST_SIZE:
3517cfdb0c2dSAnkit Navik 		hci_cc_le_read_resolv_list_size(hdev, skb);
3518cfdb0c2dSAnkit Navik 		break;
3519cfdb0c2dSAnkit Navik 
3520aa12af77SAnkit Navik 	case HCI_OP_LE_SET_ADDR_RESOLV_ENABLE:
3521aa12af77SAnkit Navik 		hci_cc_le_set_addr_resolution_enable(hdev, skb);
3522aa12af77SAnkit Navik 		break;
3523aa12af77SAnkit Navik 
3524a8e1bfaaSMarcel Holtmann 	case HCI_OP_LE_READ_MAX_DATA_LEN:
3525a8e1bfaaSMarcel Holtmann 		hci_cc_le_read_max_data_len(hdev, skb);
3526a8e1bfaaSMarcel Holtmann 		break;
3527a8e1bfaaSMarcel Holtmann 
3528f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
3529f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
3530f9b49306SAndre Guedes 		break;
3531f9b49306SAndre Guedes 
353256ed2cb8SJohan Hedberg 	case HCI_OP_LE_SET_ADV_PARAM:
353356ed2cb8SJohan Hedberg 		hci_cc_set_adv_param(hdev, skb);
353456ed2cb8SJohan Hedberg 		break;
353556ed2cb8SJohan Hedberg 
35365ae76a94SAndrzej Kaczmarek 	case HCI_OP_READ_RSSI:
35375ae76a94SAndrzej Kaczmarek 		hci_cc_read_rssi(hdev, skb);
35385ae76a94SAndrzej Kaczmarek 		break;
35395ae76a94SAndrzej Kaczmarek 
35405a134faeSAndrzej Kaczmarek 	case HCI_OP_READ_TX_POWER:
35415a134faeSAndrzej Kaczmarek 		hci_cc_read_tx_power(hdev, skb);
35425a134faeSAndrzej Kaczmarek 		break;
35435a134faeSAndrzej Kaczmarek 
3544c50b33c8SMarcel Holtmann 	case HCI_OP_WRITE_SSP_DEBUG_MODE:
3545c50b33c8SMarcel Holtmann 		hci_cc_write_ssp_debug_mode(hdev, skb);
3546c50b33c8SMarcel Holtmann 		break;
3547c50b33c8SMarcel Holtmann 
3548a2344b9eSJaganath Kanakkassery 	case HCI_OP_LE_SET_EXT_SCAN_PARAMS:
3549a2344b9eSJaganath Kanakkassery 		hci_cc_le_set_ext_scan_param(hdev, skb);
3550a2344b9eSJaganath Kanakkassery 		break;
3551a2344b9eSJaganath Kanakkassery 
3552a2344b9eSJaganath Kanakkassery 	case HCI_OP_LE_SET_EXT_SCAN_ENABLE:
3553a2344b9eSJaganath Kanakkassery 		hci_cc_le_set_ext_scan_enable(hdev, skb);
3554a2344b9eSJaganath Kanakkassery 		break;
3555a2344b9eSJaganath Kanakkassery 
35560314f286SJaganath Kanakkassery 	case HCI_OP_LE_SET_DEFAULT_PHY:
35570314f286SJaganath Kanakkassery 		hci_cc_le_set_default_phy(hdev, skb);
35580314f286SJaganath Kanakkassery 		break;
35590314f286SJaganath Kanakkassery 
35606b49bcb4SJaganath Kanakkassery 	case HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS:
35616b49bcb4SJaganath Kanakkassery 		hci_cc_le_read_num_adv_sets(hdev, skb);
35626b49bcb4SJaganath Kanakkassery 		break;
35636b49bcb4SJaganath Kanakkassery 
3564de181e88SJaganath Kanakkassery 	case HCI_OP_LE_SET_EXT_ADV_PARAMS:
3565de181e88SJaganath Kanakkassery 		hci_cc_set_ext_adv_param(hdev, skb);
3566de181e88SJaganath Kanakkassery 		break;
3567de181e88SJaganath Kanakkassery 
3568de181e88SJaganath Kanakkassery 	case HCI_OP_LE_SET_EXT_ADV_ENABLE:
3569de181e88SJaganath Kanakkassery 		hci_cc_le_set_ext_adv_enable(hdev, skb);
3570de181e88SJaganath Kanakkassery 		break;
3571de181e88SJaganath Kanakkassery 
3572a73c046aSJaganath Kanakkassery 	case HCI_OP_LE_SET_ADV_SET_RAND_ADDR:
3573a73c046aSJaganath Kanakkassery 		hci_cc_le_set_adv_set_random_addr(hdev, skb);
3574a73c046aSJaganath Kanakkassery 		break;
3575a73c046aSJaganath Kanakkassery 
3576a9de9248SMarcel Holtmann 	default:
3577e6214487SJohan Hedberg 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
3578a9de9248SMarcel Holtmann 		break;
3579a9de9248SMarcel Holtmann 	}
3580a9de9248SMarcel Holtmann 
3581e6214487SJohan Hedberg 	if (*opcode != HCI_OP_NOP)
358265cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
35836bd32326SVille Tervo 
3584600b2150SJohan Hedberg 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags))
3585600b2150SJohan Hedberg 		atomic_set(&hdev->cmd_cnt, 1);
3586600b2150SJohan Hedberg 
3587e6214487SJohan Hedberg 	hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
3588e6214487SJohan Hedberg 			     req_complete_skb);
35899238f36aSJohan Hedberg 
3590f80c5dadSJoão Paulo Rechi Vita 	if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
3591f80c5dadSJoão Paulo Rechi Vita 		bt_dev_err(hdev,
3592f80c5dadSJoão Paulo Rechi Vita 			   "unexpected event for opcode 0x%4.4x", *opcode);
3593f80c5dadSJoão Paulo Rechi Vita 		return;
3594f80c5dadSJoão Paulo Rechi Vita 	}
3595f80c5dadSJoão Paulo Rechi Vita 
3596600b2150SJohan Hedberg 	if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
3597c347b765SGustavo F. Padovan 		queue_work(hdev->workqueue, &hdev->cmd_work);
3598a9de9248SMarcel Holtmann }
3599a9de9248SMarcel Holtmann 
3600e6214487SJohan Hedberg static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
3601e6214487SJohan Hedberg 			       u16 *opcode, u8 *status,
3602e6214487SJohan Hedberg 			       hci_req_complete_t *req_complete,
3603e6214487SJohan Hedberg 			       hci_req_complete_skb_t *req_complete_skb)
3604a9de9248SMarcel Holtmann {
3605a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
3606a9de9248SMarcel Holtmann 
3607a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
3608a9de9248SMarcel Holtmann 
3609e6214487SJohan Hedberg 	*opcode = __le16_to_cpu(ev->opcode);
3610e6214487SJohan Hedberg 	*status = ev->status;
3611a9de9248SMarcel Holtmann 
3612e6214487SJohan Hedberg 	switch (*opcode) {
3613a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
3614a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
3615a9de9248SMarcel Holtmann 		break;
3616a9de9248SMarcel Holtmann 
3617a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
3618a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
3619a9de9248SMarcel Holtmann 		break;
3620a9de9248SMarcel Holtmann 
36219645c76cSKuba Pawlak 	case HCI_OP_DISCONNECT:
36229645c76cSKuba Pawlak 		hci_cs_disconnect(hdev, ev->status);
36239645c76cSKuba Pawlak 		break;
36249645c76cSKuba Pawlak 
3625a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
3626a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
3627a9de9248SMarcel Holtmann 		break;
3628a9de9248SMarcel Holtmann 
3629f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
3630f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
3631f8558555SMarcel Holtmann 		break;
3632f8558555SMarcel Holtmann 
3633f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
3634f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
3635f8558555SMarcel Holtmann 		break;
3636f8558555SMarcel Holtmann 
3637a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
3638a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
3639a9de9248SMarcel Holtmann 		break;
3640a9de9248SMarcel Holtmann 
3641769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
3642769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
3643769be974SMarcel Holtmann 		break;
3644769be974SMarcel Holtmann 
3645769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
3646769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
3647769be974SMarcel Holtmann 		break;
3648769be974SMarcel Holtmann 
3649a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
3650a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
3651a9de9248SMarcel Holtmann 		break;
3652a9de9248SMarcel Holtmann 
3653a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
3654a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
3655a9de9248SMarcel Holtmann 		break;
3656a9de9248SMarcel Holtmann 
3657a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
3658a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
3659a9de9248SMarcel Holtmann 		break;
3660a9de9248SMarcel Holtmann 
366150fc85f1SKuba Pawlak 	case HCI_OP_SWITCH_ROLE:
366250fc85f1SKuba Pawlak 		hci_cs_switch_role(hdev, ev->status);
366350fc85f1SKuba Pawlak 		break;
366450fc85f1SKuba Pawlak 
3665cb1d68f7SJohan Hedberg 	case HCI_OP_LE_CREATE_CONN:
3666cb1d68f7SJohan Hedberg 		hci_cs_le_create_conn(hdev, ev->status);
3667cb1d68f7SJohan Hedberg 		break;
3668cb1d68f7SJohan Hedberg 
36690fe29fd1SMarcel Holtmann 	case HCI_OP_LE_READ_REMOTE_FEATURES:
36700fe29fd1SMarcel Holtmann 		hci_cs_le_read_remote_features(hdev, ev->status);
36710fe29fd1SMarcel Holtmann 		break;
36720fe29fd1SMarcel Holtmann 
367381d0c8adSJohan Hedberg 	case HCI_OP_LE_START_ENC:
367481d0c8adSJohan Hedberg 		hci_cs_le_start_enc(hdev, ev->status);
367581d0c8adSJohan Hedberg 		break;
367681d0c8adSJohan Hedberg 
36774d94f95dSJaganath Kanakkassery 	case HCI_OP_LE_EXT_CREATE_CONN:
36784d94f95dSJaganath Kanakkassery 		hci_cs_le_ext_create_conn(hdev, ev->status);
36794d94f95dSJaganath Kanakkassery 		break;
36804d94f95dSJaganath Kanakkassery 
3681a9de9248SMarcel Holtmann 	default:
3682e6214487SJohan Hedberg 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
3683a9de9248SMarcel Holtmann 		break;
3684a9de9248SMarcel Holtmann 	}
3685a9de9248SMarcel Holtmann 
3686e6214487SJohan Hedberg 	if (*opcode != HCI_OP_NOP)
368765cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
36886bd32326SVille Tervo 
3689600b2150SJohan Hedberg 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags))
3690600b2150SJohan Hedberg 		atomic_set(&hdev->cmd_cnt, 1);
3691600b2150SJohan Hedberg 
3692444c6dd5SJohan Hedberg 	/* Indicate request completion if the command failed. Also, if
3693444c6dd5SJohan Hedberg 	 * we're not waiting for a special event and we get a success
3694444c6dd5SJohan Hedberg 	 * command status we should try to flag the request as completed
3695444c6dd5SJohan Hedberg 	 * (since for this kind of commands there will not be a command
3696444c6dd5SJohan Hedberg 	 * complete event).
3697444c6dd5SJohan Hedberg 	 */
369802350a72SJohan Hedberg 	if (ev->status ||
3699242c0ebdSMarcel Holtmann 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->hci.req_event))
3700e6214487SJohan Hedberg 		hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
3701e6214487SJohan Hedberg 				     req_complete_skb);
37029238f36aSJohan Hedberg 
3703f80c5dadSJoão Paulo Rechi Vita 	if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
3704f80c5dadSJoão Paulo Rechi Vita 		bt_dev_err(hdev,
3705f80c5dadSJoão Paulo Rechi Vita 			   "unexpected event for opcode 0x%4.4x", *opcode);
3706f80c5dadSJoão Paulo Rechi Vita 		return;
3707f80c5dadSJoão Paulo Rechi Vita 	}
3708f80c5dadSJoão Paulo Rechi Vita 
3709600b2150SJohan Hedberg 	if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
3710c347b765SGustavo F. Padovan 		queue_work(hdev->workqueue, &hdev->cmd_work);
3711a9de9248SMarcel Holtmann }
3712a9de9248SMarcel Holtmann 
371324dfa343SMarcel Holtmann static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
371424dfa343SMarcel Holtmann {
371524dfa343SMarcel Holtmann 	struct hci_ev_hardware_error *ev = (void *) skb->data;
371624dfa343SMarcel Holtmann 
3717c7741d16SMarcel Holtmann 	hdev->hw_error_code = ev->code;
3718c7741d16SMarcel Holtmann 
3719c7741d16SMarcel Holtmann 	queue_work(hdev->req_workqueue, &hdev->error_reset);
372024dfa343SMarcel Holtmann }
372124dfa343SMarcel Holtmann 
37226039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3723a9de9248SMarcel Holtmann {
3724a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
3725a9de9248SMarcel Holtmann 	struct hci_conn *conn;
3726a9de9248SMarcel Holtmann 
37279f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3728a9de9248SMarcel Holtmann 
3729a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3730a9de9248SMarcel Holtmann 
3731a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3732a9de9248SMarcel Holtmann 	if (conn) {
373340bef302SJohan Hedberg 		if (!ev->status)
373440bef302SJohan Hedberg 			conn->role = ev->role;
3735a9de9248SMarcel Holtmann 
373651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
3737a9de9248SMarcel Holtmann 
3738a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
3739a9de9248SMarcel Holtmann 	}
3740a9de9248SMarcel Holtmann 
3741a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3742a9de9248SMarcel Holtmann }
3743a9de9248SMarcel Holtmann 
37446039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
37451da177e4SLinus Torvalds {
3746a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
37471da177e4SLinus Torvalds 	int i;
37481da177e4SLinus Torvalds 
374932ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
37502064ee33SMarcel Holtmann 		bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
375132ac5b9bSAndrei Emeltchenko 		return;
375232ac5b9bSAndrei Emeltchenko 	}
375332ac5b9bSAndrei Emeltchenko 
375416e18342SGustavo A. R. Silva 	if (skb->len < sizeof(*ev) ||
375516e18342SGustavo A. R. Silva 	    skb->len < struct_size(ev, handles, ev->num_hndl)) {
37561da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
37571da177e4SLinus Torvalds 		return;
37581da177e4SLinus Torvalds 	}
37591da177e4SLinus Torvalds 
3760c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
3761c5993de8SAndrei Emeltchenko 
3762613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
3763613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
37641da177e4SLinus Torvalds 		struct hci_conn *conn;
37651da177e4SLinus Torvalds 		__u16  handle, count;
37661da177e4SLinus Torvalds 
3767613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
3768613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
37691da177e4SLinus Torvalds 
37701da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
3771f4280918SAndrei Emeltchenko 		if (!conn)
3772f4280918SAndrei Emeltchenko 			continue;
3773f4280918SAndrei Emeltchenko 
37741da177e4SLinus Torvalds 		conn->sent -= count;
37751da177e4SLinus Torvalds 
3776f4280918SAndrei Emeltchenko 		switch (conn->type) {
3777f4280918SAndrei Emeltchenko 		case ACL_LINK:
377870f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
377970f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
37801da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
3781f4280918SAndrei Emeltchenko 			break;
3782f4280918SAndrei Emeltchenko 
3783f4280918SAndrei Emeltchenko 		case LE_LINK:
37846ed58ec5SVille Tervo 			if (hdev->le_pkts) {
37856ed58ec5SVille Tervo 				hdev->le_cnt += count;
37866ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
37876ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
37886ed58ec5SVille Tervo 			} else {
37896ed58ec5SVille Tervo 				hdev->acl_cnt += count;
37906ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
37916ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
37926ed58ec5SVille Tervo 			}
3793f4280918SAndrei Emeltchenko 			break;
3794f4280918SAndrei Emeltchenko 
3795f4280918SAndrei Emeltchenko 		case SCO_LINK:
379670f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
379770f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
37985b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
3799f4280918SAndrei Emeltchenko 			break;
3800f4280918SAndrei Emeltchenko 
3801f4280918SAndrei Emeltchenko 		default:
38022064ee33SMarcel Holtmann 			bt_dev_err(hdev, "unknown type %d conn %p",
38032064ee33SMarcel Holtmann 				   conn->type, conn);
3804f4280918SAndrei Emeltchenko 			break;
38051da177e4SLinus Torvalds 		}
38061da177e4SLinus Torvalds 	}
3807a9de9248SMarcel Holtmann 
38083eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
38091da177e4SLinus Torvalds }
38101da177e4SLinus Torvalds 
381176ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
381276ef7cf7SAndrei Emeltchenko 						 __u16 handle)
381376ef7cf7SAndrei Emeltchenko {
381476ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
381576ef7cf7SAndrei Emeltchenko 
381676ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
3817ca8bee5dSMarcel Holtmann 	case HCI_PRIMARY:
381876ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
381976ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
382076ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
382176ef7cf7SAndrei Emeltchenko 		if (chan)
382276ef7cf7SAndrei Emeltchenko 			return chan->conn;
382376ef7cf7SAndrei Emeltchenko 		break;
382476ef7cf7SAndrei Emeltchenko 	default:
38252064ee33SMarcel Holtmann 		bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type);
382676ef7cf7SAndrei Emeltchenko 		break;
382776ef7cf7SAndrei Emeltchenko 	}
382876ef7cf7SAndrei Emeltchenko 
382976ef7cf7SAndrei Emeltchenko 	return NULL;
383076ef7cf7SAndrei Emeltchenko }
383176ef7cf7SAndrei Emeltchenko 
38326039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
383325e89e99SAndrei Emeltchenko {
383425e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
383525e89e99SAndrei Emeltchenko 	int i;
383625e89e99SAndrei Emeltchenko 
383725e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
38382064ee33SMarcel Holtmann 		bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
383925e89e99SAndrei Emeltchenko 		return;
384025e89e99SAndrei Emeltchenko 	}
384125e89e99SAndrei Emeltchenko 
384216e18342SGustavo A. R. Silva 	if (skb->len < sizeof(*ev) ||
384316e18342SGustavo A. R. Silva 	    skb->len < struct_size(ev, handles, ev->num_hndl)) {
384425e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
384525e89e99SAndrei Emeltchenko 		return;
384625e89e99SAndrei Emeltchenko 	}
384725e89e99SAndrei Emeltchenko 
384825e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
384925e89e99SAndrei Emeltchenko 	       ev->num_hndl);
385025e89e99SAndrei Emeltchenko 
385125e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
385225e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
385376ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
385425e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
385525e89e99SAndrei Emeltchenko 
385625e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
385725e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
385825e89e99SAndrei Emeltchenko 
385976ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
386025e89e99SAndrei Emeltchenko 		if (!conn)
386125e89e99SAndrei Emeltchenko 			continue;
386225e89e99SAndrei Emeltchenko 
386325e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
386425e89e99SAndrei Emeltchenko 
386525e89e99SAndrei Emeltchenko 		switch (conn->type) {
386625e89e99SAndrei Emeltchenko 		case ACL_LINK:
3867bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
386825e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
386925e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
387025e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
387125e89e99SAndrei Emeltchenko 			break;
387225e89e99SAndrei Emeltchenko 
387325e89e99SAndrei Emeltchenko 		default:
38742064ee33SMarcel Holtmann 			bt_dev_err(hdev, "unknown type %d conn %p",
38752064ee33SMarcel Holtmann 				   conn->type, conn);
387625e89e99SAndrei Emeltchenko 			break;
387725e89e99SAndrei Emeltchenko 		}
387825e89e99SAndrei Emeltchenko 	}
387925e89e99SAndrei Emeltchenko 
388025e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
388125e89e99SAndrei Emeltchenko }
388225e89e99SAndrei Emeltchenko 
38836039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
38841da177e4SLinus Torvalds {
3885a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
388604837f64SMarcel Holtmann 	struct hci_conn *conn;
38871da177e4SLinus Torvalds 
38889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
38891da177e4SLinus Torvalds 
38901da177e4SLinus Torvalds 	hci_dev_lock(hdev);
38911da177e4SLinus Torvalds 
389204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
389304837f64SMarcel Holtmann 	if (conn) {
389404837f64SMarcel Holtmann 		conn->mode = ev->mode;
389504837f64SMarcel Holtmann 
38968fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
38978fc9ced3SGustavo Padovan 					&conn->flags)) {
389804837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
389958a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
390004837f64SMarcel Holtmann 			else
390158a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
390204837f64SMarcel Holtmann 		}
3903e73439d8SMarcel Holtmann 
390451a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
3905e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
390604837f64SMarcel Holtmann 	}
390704837f64SMarcel Holtmann 
390804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
390904837f64SMarcel Holtmann }
391004837f64SMarcel Holtmann 
39116039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
39121da177e4SLinus Torvalds {
3913052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
3914052b30b0SMarcel Holtmann 	struct hci_conn *conn;
3915052b30b0SMarcel Holtmann 
3916a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3917052b30b0SMarcel Holtmann 
3918052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3919052b30b0SMarcel Holtmann 
3920052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3921b6f98044SWaldemar Rymarkiewicz 	if (!conn)
3922b6f98044SWaldemar Rymarkiewicz 		goto unlock;
3923b6f98044SWaldemar Rymarkiewicz 
3924b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
3925052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3926052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
392776a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3928052b30b0SMarcel Holtmann 	}
3929052b30b0SMarcel Holtmann 
3930d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
39312f407f0aSJohan Hedberg 	    !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) {
393203b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
393303b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
3934d7a5a11dSMarcel Holtmann 	} else if (hci_dev_test_flag(hdev, HCI_MGMT)) {
3935a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
3936a770bb5aSWaldemar Rymarkiewicz 
3937a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
3938a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
3939a770bb5aSWaldemar Rymarkiewicz 		else
3940a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
3941a770bb5aSWaldemar Rymarkiewicz 
3942744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
3943a770bb5aSWaldemar Rymarkiewicz 	}
3944980e1a53SJohan Hedberg 
3945b6f98044SWaldemar Rymarkiewicz unlock:
3946052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
39471da177e4SLinus Torvalds }
39481da177e4SLinus Torvalds 
3949cb6f3f7aSJohan Hedberg static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
3950cb6f3f7aSJohan Hedberg {
3951cb6f3f7aSJohan Hedberg 	if (key_type == HCI_LK_CHANGED_COMBINATION)
3952cb6f3f7aSJohan Hedberg 		return;
3953cb6f3f7aSJohan Hedberg 
3954cb6f3f7aSJohan Hedberg 	conn->pin_length = pin_len;
3955cb6f3f7aSJohan Hedberg 	conn->key_type = key_type;
3956cb6f3f7aSJohan Hedberg 
3957cb6f3f7aSJohan Hedberg 	switch (key_type) {
3958cb6f3f7aSJohan Hedberg 	case HCI_LK_LOCAL_UNIT:
3959cb6f3f7aSJohan Hedberg 	case HCI_LK_REMOTE_UNIT:
3960cb6f3f7aSJohan Hedberg 	case HCI_LK_DEBUG_COMBINATION:
3961cb6f3f7aSJohan Hedberg 		return;
3962cb6f3f7aSJohan Hedberg 	case HCI_LK_COMBINATION:
3963cb6f3f7aSJohan Hedberg 		if (pin_len == 16)
3964cb6f3f7aSJohan Hedberg 			conn->pending_sec_level = BT_SECURITY_HIGH;
3965cb6f3f7aSJohan Hedberg 		else
3966cb6f3f7aSJohan Hedberg 			conn->pending_sec_level = BT_SECURITY_MEDIUM;
3967cb6f3f7aSJohan Hedberg 		break;
3968cb6f3f7aSJohan Hedberg 	case HCI_LK_UNAUTH_COMBINATION_P192:
3969cb6f3f7aSJohan Hedberg 	case HCI_LK_UNAUTH_COMBINATION_P256:
3970cb6f3f7aSJohan Hedberg 		conn->pending_sec_level = BT_SECURITY_MEDIUM;
3971cb6f3f7aSJohan Hedberg 		break;
3972cb6f3f7aSJohan Hedberg 	case HCI_LK_AUTH_COMBINATION_P192:
3973cb6f3f7aSJohan Hedberg 		conn->pending_sec_level = BT_SECURITY_HIGH;
3974cb6f3f7aSJohan Hedberg 		break;
3975cb6f3f7aSJohan Hedberg 	case HCI_LK_AUTH_COMBINATION_P256:
3976cb6f3f7aSJohan Hedberg 		conn->pending_sec_level = BT_SECURITY_FIPS;
3977cb6f3f7aSJohan Hedberg 		break;
3978cb6f3f7aSJohan Hedberg 	}
3979cb6f3f7aSJohan Hedberg }
3980cb6f3f7aSJohan Hedberg 
39816039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
39821da177e4SLinus Torvalds {
398355ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
398455ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
398555ed8ca1SJohan Hedberg 	struct hci_conn *conn;
398655ed8ca1SJohan Hedberg 	struct link_key *key;
398755ed8ca1SJohan Hedberg 
3988a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
398955ed8ca1SJohan Hedberg 
3990d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
399155ed8ca1SJohan Hedberg 		return;
399255ed8ca1SJohan Hedberg 
399355ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
399455ed8ca1SJohan Hedberg 
399555ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
399655ed8ca1SJohan Hedberg 	if (!key) {
39976ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
39986ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
399955ed8ca1SJohan Hedberg 		goto not_found;
400055ed8ca1SJohan Hedberg 	}
400155ed8ca1SJohan Hedberg 
40026ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
40036ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
400455ed8ca1SJohan Hedberg 
400555ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
400660b83f57SWaldemar Rymarkiewicz 	if (conn) {
4007fe8bc5acSJohan Hedberg 		clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
4008fe8bc5acSJohan Hedberg 
400966138ce8SMarcel Holtmann 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
401066138ce8SMarcel Holtmann 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
4011807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
401255ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
401355ed8ca1SJohan Hedberg 			goto not_found;
401455ed8ca1SJohan Hedberg 		}
401555ed8ca1SJohan Hedberg 
401660b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
4017f3fb0b58SJohan Hedberg 		    (conn->pending_sec_level == BT_SECURITY_HIGH ||
4018f3fb0b58SJohan Hedberg 		     conn->pending_sec_level == BT_SECURITY_FIPS)) {
40198fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
40208fc9ced3SGustavo Padovan 			       hdev->name);
402160b83f57SWaldemar Rymarkiewicz 			goto not_found;
402260b83f57SWaldemar Rymarkiewicz 		}
402360b83f57SWaldemar Rymarkiewicz 
4024cb6f3f7aSJohan Hedberg 		conn_set_key(conn, key->type, key->pin_len);
402560b83f57SWaldemar Rymarkiewicz 	}
402660b83f57SWaldemar Rymarkiewicz 
402755ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
40289b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
402955ed8ca1SJohan Hedberg 
403055ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
403155ed8ca1SJohan Hedberg 
403255ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
403355ed8ca1SJohan Hedberg 
403455ed8ca1SJohan Hedberg 	return;
403555ed8ca1SJohan Hedberg 
403655ed8ca1SJohan Hedberg not_found:
403755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
403855ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
40391da177e4SLinus Torvalds }
40401da177e4SLinus Torvalds 
40416039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
40421da177e4SLinus Torvalds {
4043052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
4044052b30b0SMarcel Holtmann 	struct hci_conn *conn;
40457652ff6aSJohan Hedberg 	struct link_key *key;
40467652ff6aSJohan Hedberg 	bool persistent;
404755ed8ca1SJohan Hedberg 	u8 pin_len = 0;
4048052b30b0SMarcel Holtmann 
4049a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
4050052b30b0SMarcel Holtmann 
4051052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
4052052b30b0SMarcel Holtmann 
4053052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
405482c13d42SJohan Hedberg 	if (!conn)
405582c13d42SJohan Hedberg 		goto unlock;
405682c13d42SJohan Hedberg 
4057052b30b0SMarcel Holtmann 	hci_conn_hold(conn);
4058052b30b0SMarcel Holtmann 	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
405976a68ba0SDavid Herrmann 	hci_conn_drop(conn);
406082c13d42SJohan Hedberg 
4061fe8bc5acSJohan Hedberg 	set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
4062cb6f3f7aSJohan Hedberg 	conn_set_key(conn, ev->key_type, conn->pin_length);
4063052b30b0SMarcel Holtmann 
4064d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
40657652ff6aSJohan Hedberg 		goto unlock;
406655ed8ca1SJohan Hedberg 
40677652ff6aSJohan Hedberg 	key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key,
40687652ff6aSJohan Hedberg 			        ev->key_type, pin_len, &persistent);
40697652ff6aSJohan Hedberg 	if (!key)
40707652ff6aSJohan Hedberg 		goto unlock;
40717652ff6aSJohan Hedberg 
4072cb6f3f7aSJohan Hedberg 	/* Update connection information since adding the key will have
4073cb6f3f7aSJohan Hedberg 	 * fixed up the type in the case of changed combination keys.
4074cb6f3f7aSJohan Hedberg 	 */
4075cb6f3f7aSJohan Hedberg 	if (ev->key_type == HCI_LK_CHANGED_COMBINATION)
4076cb6f3f7aSJohan Hedberg 		conn_set_key(conn, key->type, key->pin_len);
4077cb6f3f7aSJohan Hedberg 
40787652ff6aSJohan Hedberg 	mgmt_new_link_key(hdev, key, persistent);
40797652ff6aSJohan Hedberg 
40806d5650c4SJohan Hedberg 	/* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
40816d5650c4SJohan Hedberg 	 * is set. If it's not set simply remove the key from the kernel
40826d5650c4SJohan Hedberg 	 * list (we've still notified user space about it but with
40836d5650c4SJohan Hedberg 	 * store_hint being 0).
40846d5650c4SJohan Hedberg 	 */
40856d5650c4SJohan Hedberg 	if (key->type == HCI_LK_DEBUG_COMBINATION &&
4086d7a5a11dSMarcel Holtmann 	    !hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS)) {
40870378b597SJohan Hedberg 		list_del_rcu(&key->list);
40880378b597SJohan Hedberg 		kfree_rcu(key, rcu);
408982c13d42SJohan Hedberg 		goto unlock;
409082c13d42SJohan Hedberg 	}
409182c13d42SJohan Hedberg 
4092af6a9c32SJohan Hedberg 	if (persistent)
4093af6a9c32SJohan Hedberg 		clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
4094af6a9c32SJohan Hedberg 	else
4095af6a9c32SJohan Hedberg 		set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
40967652ff6aSJohan Hedberg 
40977652ff6aSJohan Hedberg unlock:
4098052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
40991da177e4SLinus Torvalds }
41001da177e4SLinus Torvalds 
41016039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
410204837f64SMarcel Holtmann {
4103a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
410404837f64SMarcel Holtmann 	struct hci_conn *conn;
410504837f64SMarcel Holtmann 
41069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
410704837f64SMarcel Holtmann 
410804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
410904837f64SMarcel Holtmann 
411004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
41111da177e4SLinus Torvalds 	if (conn && !ev->status) {
41121da177e4SLinus Torvalds 		struct inquiry_entry *ie;
41131da177e4SLinus Torvalds 
4114cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
4115cc11b9c1SAndrei Emeltchenko 		if (ie) {
41161da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
41171da177e4SLinus Torvalds 			ie->timestamp = jiffies;
41181da177e4SLinus Torvalds 		}
41191da177e4SLinus Torvalds 	}
41201da177e4SLinus Torvalds 
41211da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
41221da177e4SLinus Torvalds }
41231da177e4SLinus Torvalds 
41246039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
4125a8746417SMarcel Holtmann {
4126a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
4127a8746417SMarcel Holtmann 	struct hci_conn *conn;
4128a8746417SMarcel Holtmann 
41299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
4130a8746417SMarcel Holtmann 
4131a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
4132a8746417SMarcel Holtmann 
4133a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
4134a8746417SMarcel Holtmann 	if (conn && !ev->status)
4135a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
4136a8746417SMarcel Holtmann 
4137a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
4138a8746417SMarcel Holtmann }
4139a8746417SMarcel Holtmann 
41406039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
414185a1e930SMarcel Holtmann {
4142a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
414385a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
414485a1e930SMarcel Holtmann 
414585a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
414685a1e930SMarcel Holtmann 
414785a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
414885a1e930SMarcel Holtmann 
4149cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
4150cc11b9c1SAndrei Emeltchenko 	if (ie) {
415185a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
415285a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
415385a1e930SMarcel Holtmann 	}
415485a1e930SMarcel Holtmann 
415585a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
415685a1e930SMarcel Holtmann }
415785a1e930SMarcel Holtmann 
41586039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
4159807deac2SGustavo Padovan 					     struct sk_buff *skb)
4160a9de9248SMarcel Holtmann {
4161a9de9248SMarcel Holtmann 	struct inquiry_data data;
4162a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
4163a9de9248SMarcel Holtmann 
4164a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
4165a9de9248SMarcel Holtmann 
4166a9de9248SMarcel Holtmann 	if (!num_rsp)
4167a9de9248SMarcel Holtmann 		return;
4168a9de9248SMarcel Holtmann 
4169d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
41701519cc17SAndre Guedes 		return;
41711519cc17SAndre Guedes 
4172a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
4173a9de9248SMarcel Holtmann 
4174a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
4175138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
4176138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
4177a9de9248SMarcel Holtmann 
4178629b49c8SPeilin Ye 		if (skb->len < num_rsp * sizeof(*info) + 1)
4179629b49c8SPeilin Ye 			goto unlock;
4180629b49c8SPeilin Ye 
4181e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
4182af58925cSMarcel Holtmann 			u32 flags;
4183af58925cSMarcel Holtmann 
4184a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
4185a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
4186a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
4187a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
4188a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
4189a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
4190a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
419141a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
41923175405bSJohan Hedberg 
4193af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
4194af58925cSMarcel Holtmann 
419548264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
4196e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
4197af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
4198a9de9248SMarcel Holtmann 		}
4199a9de9248SMarcel Holtmann 	} else {
4200a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
4201a9de9248SMarcel Holtmann 
4202629b49c8SPeilin Ye 		if (skb->len < num_rsp * sizeof(*info) + 1)
4203629b49c8SPeilin Ye 			goto unlock;
4204629b49c8SPeilin Ye 
4205e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
4206af58925cSMarcel Holtmann 			u32 flags;
4207af58925cSMarcel Holtmann 
4208a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
4209a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
4210a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
4211a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
4212a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
4213a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
4214a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
421541a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
4216af58925cSMarcel Holtmann 
4217af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
4218af58925cSMarcel Holtmann 
421948264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
4220e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
4221af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
4222a9de9248SMarcel Holtmann 		}
4223a9de9248SMarcel Holtmann 	}
4224a9de9248SMarcel Holtmann 
4225629b49c8SPeilin Ye unlock:
4226a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
4227a9de9248SMarcel Holtmann }
4228a9de9248SMarcel Holtmann 
42296039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
4230807deac2SGustavo Padovan 					struct sk_buff *skb)
4231a9de9248SMarcel Holtmann {
423241a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
423341a96212SMarcel Holtmann 	struct hci_conn *conn;
423441a96212SMarcel Holtmann 
4235a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
423641a96212SMarcel Holtmann 
423741a96212SMarcel Holtmann 	hci_dev_lock(hdev);
423841a96212SMarcel Holtmann 
423941a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
4240ccd556feSJohan Hedberg 	if (!conn)
4241ccd556feSJohan Hedberg 		goto unlock;
4242ccd556feSJohan Hedberg 
4243cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
4244cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
4245cad718edSJohan Hedberg 
4246769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
424741a96212SMarcel Holtmann 		struct inquiry_entry *ie;
424841a96212SMarcel Holtmann 
4249cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
4250cc11b9c1SAndrei Emeltchenko 		if (ie)
425102b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
425241a96212SMarcel Holtmann 
4253bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
425458a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
4255bbb0eadaSJaganath Kanakkassery 		} else {
4256bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
4257bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
4258bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
4259bbb0eadaSJaganath Kanakkassery 			 * this.
4260bbb0eadaSJaganath Kanakkassery 			 *
4261bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
4262bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
4263bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
4264bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
4265bbb0eadaSJaganath Kanakkassery 		}
4266eb9a8f3fSMarcel Holtmann 
4267eb9a8f3fSMarcel Holtmann 		if (ev->features[0] & LMP_HOST_SC)
4268eb9a8f3fSMarcel Holtmann 			set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
426941a96212SMarcel Holtmann 	}
427041a96212SMarcel Holtmann 
4271ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
4272ccd556feSJohan Hedberg 		goto unlock;
4273ccd556feSJohan Hedberg 
4274671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
4275127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
4276127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
4277127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
4278127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
4279127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
4280b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
428148ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
4282392599b9SJohan Hedberg 
4283127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
4284769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
4285539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
428676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
4287769be974SMarcel Holtmann 	}
4288769be974SMarcel Holtmann 
4289ccd556feSJohan Hedberg unlock:
429041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
4291a9de9248SMarcel Holtmann }
4292a9de9248SMarcel Holtmann 
42936039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
4294807deac2SGustavo Padovan 				       struct sk_buff *skb)
4295a9de9248SMarcel Holtmann {
4296b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
4297b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
4298b6a0dc82SMarcel Holtmann 
42999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
4300b6a0dc82SMarcel Holtmann 
4301b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
4302b6a0dc82SMarcel Holtmann 
4303b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
43049dc0a3afSMarcel Holtmann 	if (!conn) {
43059dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
43069dc0a3afSMarcel Holtmann 			goto unlock;
43079dc0a3afSMarcel Holtmann 
4308618353b1SKuba Pawlak 		/* When the link type in the event indicates SCO connection
4309618353b1SKuba Pawlak 		 * and lookup of the connection object fails, then check
4310618353b1SKuba Pawlak 		 * if an eSCO connection object exists.
4311618353b1SKuba Pawlak 		 *
4312618353b1SKuba Pawlak 		 * The core limits the synchronous connections to either
4313618353b1SKuba Pawlak 		 * SCO or eSCO. The eSCO connection is preferred and tried
4314618353b1SKuba Pawlak 		 * to be setup first and until successfully established,
4315618353b1SKuba Pawlak 		 * the link type will be hinted as eSCO.
4316618353b1SKuba Pawlak 		 */
43179dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
4318b6a0dc82SMarcel Holtmann 		if (!conn)
4319b6a0dc82SMarcel Holtmann 			goto unlock;
43209dc0a3afSMarcel Holtmann 	}
43219dc0a3afSMarcel Holtmann 
4322732547f9SMarcel Holtmann 	switch (ev->status) {
4323732547f9SMarcel Holtmann 	case 0x00:
4324732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
4325732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
4326618353b1SKuba Pawlak 		conn->type   = ev->link_type;
4327732547f9SMarcel Holtmann 
432823b9ceb7SMarcel Holtmann 		hci_debugfs_create_conn(conn);
4329732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
4330732547f9SMarcel Holtmann 		break;
4331732547f9SMarcel Holtmann 
433281218d20SNick Pelly 	case 0x10:	/* Connection Accept Timeout */
43331a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
4334705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
4335732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
43361038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
433756b5453aSHsin-Yu Chao 	case 0x1e:	/* Invalid LMP Parameters */
4338732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
433927539bc4SAndrew Earl 	case 0x20:	/* Unsupported LMP Parameter value */
43402dea632fSFrédéric Dalleau 		if (conn->out) {
4341efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
4342efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
43432dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
4344efc7688bSMarcel Holtmann 				goto unlock;
4345efc7688bSMarcel Holtmann 		}
434619186c7bSGustavo A. R. Silva 		fallthrough;
4347efc7688bSMarcel Holtmann 
4348732547f9SMarcel Holtmann 	default:
4349b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
4350732547f9SMarcel Holtmann 		break;
4351732547f9SMarcel Holtmann 	}
4352b6a0dc82SMarcel Holtmann 
43531f8330eaSSathish Narsimman 	bt_dev_dbg(hdev, "SCO connected with air mode: %02x", ev->air_mode);
43541f8330eaSSathish Narsimman 
43551f8330eaSSathish Narsimman 	switch (conn->setting & SCO_AIRMODE_MASK) {
43561f8330eaSSathish Narsimman 	case SCO_AIRMODE_CVSD:
43571f8330eaSSathish Narsimman 		if (hdev->notify)
43581f8330eaSSathish Narsimman 			hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD);
43591f8330eaSSathish Narsimman 		break;
43601f8330eaSSathish Narsimman 	case SCO_AIRMODE_TRANSP:
43611f8330eaSSathish Narsimman 		if (hdev->notify)
43621f8330eaSSathish Narsimman 			hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_TRANSP);
43631f8330eaSSathish Narsimman 		break;
43641f8330eaSSathish Narsimman 	}
43651f8330eaSSathish Narsimman 
4366539c496dSJohan Hedberg 	hci_connect_cfm(conn, ev->status);
4367b6a0dc82SMarcel Holtmann 	if (ev->status)
4368b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
4369b6a0dc82SMarcel Holtmann 
4370b6a0dc82SMarcel Holtmann unlock:
4371b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
4372a9de9248SMarcel Holtmann }
4373a9de9248SMarcel Holtmann 
4374efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len)
4375efdcf8e3SMarcel Holtmann {
4376efdcf8e3SMarcel Holtmann 	size_t parsed = 0;
4377efdcf8e3SMarcel Holtmann 
4378efdcf8e3SMarcel Holtmann 	while (parsed < eir_len) {
4379efdcf8e3SMarcel Holtmann 		u8 field_len = eir[0];
4380efdcf8e3SMarcel Holtmann 
4381efdcf8e3SMarcel Holtmann 		if (field_len == 0)
4382efdcf8e3SMarcel Holtmann 			return parsed;
4383efdcf8e3SMarcel Holtmann 
4384efdcf8e3SMarcel Holtmann 		parsed += field_len + 1;
4385efdcf8e3SMarcel Holtmann 		eir += field_len + 1;
4386efdcf8e3SMarcel Holtmann 	}
4387efdcf8e3SMarcel Holtmann 
4388efdcf8e3SMarcel Holtmann 	return eir_len;
4389efdcf8e3SMarcel Holtmann }
4390efdcf8e3SMarcel Holtmann 
43916039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
4392807deac2SGustavo Padovan 					    struct sk_buff *skb)
4393a9de9248SMarcel Holtmann {
4394a9de9248SMarcel Holtmann 	struct inquiry_data data;
4395a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
4396a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
43979d939d94SVishal Agarwal 	size_t eir_len;
4398a9de9248SMarcel Holtmann 
4399a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
4400a9de9248SMarcel Holtmann 
440151c19bf3SPeilin Ye 	if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1)
4402a9de9248SMarcel Holtmann 		return;
4403a9de9248SMarcel Holtmann 
4404d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
44051519cc17SAndre Guedes 		return;
44061519cc17SAndre Guedes 
4407a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
4408a9de9248SMarcel Holtmann 
4409e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
4410af58925cSMarcel Holtmann 		u32 flags;
4411af58925cSMarcel Holtmann 		bool name_known;
4412561aafbcSJohan Hedberg 
4413a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
4414a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
4415a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
4416a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
4417a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
4418a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
4419a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
442041a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
4421561aafbcSJohan Hedberg 
4422d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_MGMT))
44230d3b7f64SJohan Hedberg 			name_known = eir_get_data(info->data,
44244ddb1930SJohan Hedberg 						  sizeof(info->data),
44250d3b7f64SJohan Hedberg 						  EIR_NAME_COMPLETE, NULL);
4426561aafbcSJohan Hedberg 		else
4427561aafbcSJohan Hedberg 			name_known = true;
4428561aafbcSJohan Hedberg 
4429af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, name_known);
4430af58925cSMarcel Holtmann 
44319d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
4432af58925cSMarcel Holtmann 
443348264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
4434af58925cSMarcel Holtmann 				  info->dev_class, info->rssi,
4435af58925cSMarcel Holtmann 				  flags, info->data, eir_len, NULL, 0);
4436a9de9248SMarcel Holtmann 	}
4437a9de9248SMarcel Holtmann 
4438a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
4439a9de9248SMarcel Holtmann }
4440a9de9248SMarcel Holtmann 
44411c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
44421c2e0041SJohan Hedberg 					 struct sk_buff *skb)
44431c2e0041SJohan Hedberg {
44441c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
44451c2e0041SJohan Hedberg 	struct hci_conn *conn;
44461c2e0041SJohan Hedberg 
44479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
44481c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
44491c2e0041SJohan Hedberg 
44501c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
44511c2e0041SJohan Hedberg 
44521c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
44531c2e0041SJohan Hedberg 	if (!conn)
44541c2e0041SJohan Hedberg 		goto unlock;
44551c2e0041SJohan Hedberg 
44569eb1fbfaSJohan Hedberg 	/* For BR/EDR the necessary steps are taken through the
44579eb1fbfaSJohan Hedberg 	 * auth_complete event.
44589eb1fbfaSJohan Hedberg 	 */
44599eb1fbfaSJohan Hedberg 	if (conn->type != LE_LINK)
44609eb1fbfaSJohan Hedberg 		goto unlock;
44619eb1fbfaSJohan Hedberg 
44621c2e0041SJohan Hedberg 	if (!ev->status)
44631c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
44641c2e0041SJohan Hedberg 
44651c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
44661c2e0041SJohan Hedberg 
44671c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
4468bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
446976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
44701c2e0041SJohan Hedberg 		goto unlock;
44711c2e0041SJohan Hedberg 	}
44721c2e0041SJohan Hedberg 
44731c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
44741c2e0041SJohan Hedberg 		if (!ev->status)
44751c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
44761c2e0041SJohan Hedberg 
4477539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
447876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
44791c2e0041SJohan Hedberg 	} else {
44801c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
44811c2e0041SJohan Hedberg 
44821c2e0041SJohan Hedberg 		hci_conn_hold(conn);
44831c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
448476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
44851c2e0041SJohan Hedberg 	}
44861c2e0041SJohan Hedberg 
44871c2e0041SJohan Hedberg unlock:
44881c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
44891c2e0041SJohan Hedberg }
44901c2e0041SJohan Hedberg 
44916039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
449217fa4b9dSJohan Hedberg {
449317fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
4494acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
4495acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
449658797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
449717fa4b9dSJohan Hedberg 
4498b7f94c88SMikel Astiz 	/* If both remote and local have enough IO capabilities, require
4499b7f94c88SMikel Astiz 	 * MITM protection
4500b7f94c88SMikel Astiz 	 */
4501b7f94c88SMikel Astiz 	if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT &&
4502b7f94c88SMikel Astiz 	    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT)
4503b7f94c88SMikel Astiz 		return conn->remote_auth | 0x01;
4504b7f94c88SMikel Astiz 
45057e74170aSTimo Mueller 	/* No MITM protection possible so ignore remote requirement */
45067e74170aSTimo Mueller 	return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01);
450717fa4b9dSJohan Hedberg }
450817fa4b9dSJohan Hedberg 
4509a83ed81eSMarcel Holtmann static u8 bredr_oob_data_present(struct hci_conn *conn)
4510a83ed81eSMarcel Holtmann {
4511a83ed81eSMarcel Holtmann 	struct hci_dev *hdev = conn->hdev;
4512a83ed81eSMarcel Holtmann 	struct oob_data *data;
4513a83ed81eSMarcel Holtmann 
4514a83ed81eSMarcel Holtmann 	data = hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR);
4515a83ed81eSMarcel Holtmann 	if (!data)
4516a83ed81eSMarcel Holtmann 		return 0x00;
4517a83ed81eSMarcel Holtmann 
4518bf21d793SMarcel Holtmann 	if (bredr_sc_enabled(hdev)) {
4519bf21d793SMarcel Holtmann 		/* When Secure Connections is enabled, then just
4520bf21d793SMarcel Holtmann 		 * return the present value stored with the OOB
4521bf21d793SMarcel Holtmann 		 * data. The stored value contains the right present
4522bf21d793SMarcel Holtmann 		 * information. However it can only be trusted when
4523bf21d793SMarcel Holtmann 		 * not in Secure Connection Only mode.
4524aa5b0345SMarcel Holtmann 		 */
4525d7a5a11dSMarcel Holtmann 		if (!hci_dev_test_flag(hdev, HCI_SC_ONLY))
4526bf21d793SMarcel Holtmann 			return data->present;
4527bf21d793SMarcel Holtmann 
4528bf21d793SMarcel Holtmann 		/* When Secure Connections Only mode is enabled, then
4529bf21d793SMarcel Holtmann 		 * the P-256 values are required. If they are not
4530bf21d793SMarcel Holtmann 		 * available, then do not declare that OOB data is
4531bf21d793SMarcel Holtmann 		 * present.
4532bf21d793SMarcel Holtmann 		 */
4533bf21d793SMarcel Holtmann 		if (!memcmp(data->rand256, ZERO_KEY, 16) ||
4534bf21d793SMarcel Holtmann 		    !memcmp(data->hash256, ZERO_KEY, 16))
4535aa5b0345SMarcel Holtmann 			return 0x00;
4536aa5b0345SMarcel Holtmann 
4537bf21d793SMarcel Holtmann 		return 0x02;
4538bf21d793SMarcel Holtmann 	}
4539659c7fb0SMarcel Holtmann 
4540659c7fb0SMarcel Holtmann 	/* When Secure Connections is not enabled or actually
4541659c7fb0SMarcel Holtmann 	 * not supported by the hardware, then check that if
4542659c7fb0SMarcel Holtmann 	 * P-192 data values are present.
4543659c7fb0SMarcel Holtmann 	 */
4544659c7fb0SMarcel Holtmann 	if (!memcmp(data->rand192, ZERO_KEY, 16) ||
4545659c7fb0SMarcel Holtmann 	    !memcmp(data->hash192, ZERO_KEY, 16))
4546659c7fb0SMarcel Holtmann 		return 0x00;
4547659c7fb0SMarcel Holtmann 
4548a83ed81eSMarcel Holtmann 	return 0x01;
4549659c7fb0SMarcel Holtmann }
4550a83ed81eSMarcel Holtmann 
45516039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
45520493684eSMarcel Holtmann {
45530493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
45540493684eSMarcel Holtmann 	struct hci_conn *conn;
45550493684eSMarcel Holtmann 
45560493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
45570493684eSMarcel Holtmann 
45580493684eSMarcel Holtmann 	hci_dev_lock(hdev);
45590493684eSMarcel Holtmann 
45600493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
456103b555e1SJohan Hedberg 	if (!conn)
456203b555e1SJohan Hedberg 		goto unlock;
456303b555e1SJohan Hedberg 
45640493684eSMarcel Holtmann 	hci_conn_hold(conn);
45650493684eSMarcel Holtmann 
4566d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
456703b555e1SJohan Hedberg 		goto unlock;
456803b555e1SJohan Hedberg 
45692f407f0aSJohan Hedberg 	/* Allow pairing if we're pairable, the initiators of the
45702f407f0aSJohan Hedberg 	 * pairing or if the remote is not requesting bonding.
45712f407f0aSJohan Hedberg 	 */
4572d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_BONDABLE) ||
45732f407f0aSJohan Hedberg 	    test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) ||
457403b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
457517fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
457617fa4b9dSJohan Hedberg 
457717fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
45787a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
45797a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
45807a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
4581a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
4582b7f94c88SMikel Astiz 
4583b7f94c88SMikel Astiz 		/* If we are initiators, there is no remote information yet */
4584b7f94c88SMikel Astiz 		if (conn->remote_auth == 0xff) {
4585b16c6604SMikel Astiz 			/* Request MITM protection if our IO caps allow it
45864ad51a75SJohan Hedberg 			 * except for the no-bonding case.
4587b16c6604SMikel Astiz 			 */
45886fd6b915SMikel Astiz 			if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
45899f743d74SJohan Hedberg 			    conn->auth_type != HCI_AT_NO_BONDING)
45906c53823aSJohan Hedberg 				conn->auth_type |= 0x01;
4591b7f94c88SMikel Astiz 		} else {
45927cbc9bd9SJohan Hedberg 			conn->auth_type = hci_get_auth_req(conn);
4593b7f94c88SMikel Astiz 		}
459417fa4b9dSJohan Hedberg 
459582c295b1SJohan Hedberg 		/* If we're not bondable, force one of the non-bondable
459682c295b1SJohan Hedberg 		 * authentication requirement values.
459782c295b1SJohan Hedberg 		 */
4598d7a5a11dSMarcel Holtmann 		if (!hci_dev_test_flag(hdev, HCI_BONDABLE))
459982c295b1SJohan Hedberg 			conn->auth_type &= HCI_AT_NO_BONDING_MITM;
460082c295b1SJohan Hedberg 
460182c295b1SJohan Hedberg 		cp.authentication = conn->auth_type;
4602a83ed81eSMarcel Holtmann 		cp.oob_data = bredr_oob_data_present(conn);
4603ce85ee13SSzymon Janc 
460417fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
460517fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
460603b555e1SJohan Hedberg 	} else {
460703b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
460803b555e1SJohan Hedberg 
460903b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
46109f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
461103b555e1SJohan Hedberg 
461203b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
461303b555e1SJohan Hedberg 			     sizeof(cp), &cp);
461403b555e1SJohan Hedberg 	}
461503b555e1SJohan Hedberg 
461603b555e1SJohan Hedberg unlock:
461703b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
461803b555e1SJohan Hedberg }
461903b555e1SJohan Hedberg 
46206039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
462103b555e1SJohan Hedberg {
462203b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
462303b555e1SJohan Hedberg 	struct hci_conn *conn;
462403b555e1SJohan Hedberg 
462503b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
462603b555e1SJohan Hedberg 
462703b555e1SJohan Hedberg 	hci_dev_lock(hdev);
462803b555e1SJohan Hedberg 
462903b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
463003b555e1SJohan Hedberg 	if (!conn)
463103b555e1SJohan Hedberg 		goto unlock;
463203b555e1SJohan Hedberg 
463303b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
463403b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
463503b555e1SJohan Hedberg 
463603b555e1SJohan Hedberg unlock:
46370493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
46380493684eSMarcel Holtmann }
46390493684eSMarcel Holtmann 
46406039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
4641a5c29683SJohan Hedberg 					 struct sk_buff *skb)
4642a5c29683SJohan Hedberg {
4643a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
464455bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
46457a828908SJohan Hedberg 	struct hci_conn *conn;
4646a5c29683SJohan Hedberg 
4647a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
4648a5c29683SJohan Hedberg 
4649a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
4650a5c29683SJohan Hedberg 
4651d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
46527a828908SJohan Hedberg 		goto unlock;
46537a828908SJohan Hedberg 
46547a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
46557a828908SJohan Hedberg 	if (!conn)
46567a828908SJohan Hedberg 		goto unlock;
46577a828908SJohan Hedberg 
46587a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
46597a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
46607a828908SJohan Hedberg 
46617a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
46626c53823aSJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
46636c53823aSJohan Hedberg 	 * request. We check the security level here since it doesn't
46646c53823aSJohan Hedberg 	 * necessarily match conn->auth_type.
46656fd6b915SMikel Astiz 	 */
46666c53823aSJohan Hedberg 	if (conn->pending_sec_level > BT_SECURITY_MEDIUM &&
46676c53823aSJohan Hedberg 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
46687a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
46697a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
46707a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
46717a828908SJohan Hedberg 		goto unlock;
46727a828908SJohan Hedberg 	}
46737a828908SJohan Hedberg 
46747a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
4675a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
4676a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
467755bc1a37SJohan Hedberg 
467855bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
467955bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
4680ba15a58bSJohan Hedberg 		 * confirm_hint set to 1). The exception is if neither
468102f3e254SJohan Hedberg 		 * side had MITM or if the local IO capability is
468202f3e254SJohan Hedberg 		 * NoInputNoOutput, in which case we do auto-accept
4683ba15a58bSJohan Hedberg 		 */
4684ba15a58bSJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
468502f3e254SJohan Hedberg 		    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
4686ba15a58bSJohan Hedberg 		    (loc_mitm || rem_mitm)) {
468755bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
468855bc1a37SJohan Hedberg 			confirm_hint = 1;
468955bc1a37SJohan Hedberg 			goto confirm;
469055bc1a37SJohan Hedberg 		}
469155bc1a37SJohan Hedberg 
4692cee5f20fSHoward Chung 		/* If there already exists link key in local host, leave the
4693cee5f20fSHoward Chung 		 * decision to user space since the remote device could be
4694cee5f20fSHoward Chung 		 * legitimate or malicious.
4695cee5f20fSHoward Chung 		 */
4696cee5f20fSHoward Chung 		if (hci_find_link_key(hdev, &ev->bdaddr)) {
4697cee5f20fSHoward Chung 			bt_dev_dbg(hdev, "Local host already has link key");
4698cee5f20fSHoward Chung 			confirm_hint = 1;
4699cee5f20fSHoward Chung 			goto confirm;
4700cee5f20fSHoward Chung 		}
4701cee5f20fSHoward Chung 
47029f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
47039f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
47049f61656aSJohan Hedberg 
47059f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
47069f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
47077bc18d9dSJohan Hedberg 			queue_delayed_work(conn->hdev->workqueue,
47087bc18d9dSJohan Hedberg 					   &conn->auto_accept_work, delay);
47099f61656aSJohan Hedberg 			goto unlock;
47109f61656aSJohan Hedberg 		}
47119f61656aSJohan Hedberg 
47127a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
47137a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
47147a828908SJohan Hedberg 		goto unlock;
47157a828908SJohan Hedberg 	}
47167a828908SJohan Hedberg 
471755bc1a37SJohan Hedberg confirm:
471839adbffeSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0,
471939adbffeSJohan Hedberg 				  le32_to_cpu(ev->passkey), confirm_hint);
4720a5c29683SJohan Hedberg 
47217a828908SJohan Hedberg unlock:
4722a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
4723a5c29683SJohan Hedberg }
4724a5c29683SJohan Hedberg 
47256039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
47261143d458SBrian Gix 					 struct sk_buff *skb)
47271143d458SBrian Gix {
47281143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
47291143d458SBrian Gix 
47301143d458SBrian Gix 	BT_DBG("%s", hdev->name);
47311143d458SBrian Gix 
4732d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
4733272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
47341143d458SBrian Gix }
47351143d458SBrian Gix 
473692a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
473792a25256SJohan Hedberg 					struct sk_buff *skb)
473892a25256SJohan Hedberg {
473992a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
474092a25256SJohan Hedberg 	struct hci_conn *conn;
474192a25256SJohan Hedberg 
474292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
474392a25256SJohan Hedberg 
474492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
474592a25256SJohan Hedberg 	if (!conn)
474692a25256SJohan Hedberg 		return;
474792a25256SJohan Hedberg 
474892a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
474992a25256SJohan Hedberg 	conn->passkey_entered = 0;
475092a25256SJohan Hedberg 
4751d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
475292a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
475392a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
475492a25256SJohan Hedberg 					 conn->passkey_entered);
475592a25256SJohan Hedberg }
475692a25256SJohan Hedberg 
475792a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
475892a25256SJohan Hedberg {
475992a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
476092a25256SJohan Hedberg 	struct hci_conn *conn;
476192a25256SJohan Hedberg 
476292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
476392a25256SJohan Hedberg 
476492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
476592a25256SJohan Hedberg 	if (!conn)
476692a25256SJohan Hedberg 		return;
476792a25256SJohan Hedberg 
476892a25256SJohan Hedberg 	switch (ev->type) {
476992a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
477092a25256SJohan Hedberg 		conn->passkey_entered = 0;
477192a25256SJohan Hedberg 		return;
477292a25256SJohan Hedberg 
477392a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
477492a25256SJohan Hedberg 		conn->passkey_entered++;
477592a25256SJohan Hedberg 		break;
477692a25256SJohan Hedberg 
477792a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
477892a25256SJohan Hedberg 		conn->passkey_entered--;
477992a25256SJohan Hedberg 		break;
478092a25256SJohan Hedberg 
478192a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
478292a25256SJohan Hedberg 		conn->passkey_entered = 0;
478392a25256SJohan Hedberg 		break;
478492a25256SJohan Hedberg 
478592a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
478692a25256SJohan Hedberg 		return;
478792a25256SJohan Hedberg 	}
478892a25256SJohan Hedberg 
4789d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
479092a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
479192a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
479292a25256SJohan Hedberg 					 conn->passkey_entered);
479392a25256SJohan Hedberg }
479492a25256SJohan Hedberg 
47956039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
4796807deac2SGustavo Padovan 					 struct sk_buff *skb)
47970493684eSMarcel Holtmann {
47980493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
47990493684eSMarcel Holtmann 	struct hci_conn *conn;
48000493684eSMarcel Holtmann 
48010493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
48020493684eSMarcel Holtmann 
48030493684eSMarcel Holtmann 	hci_dev_lock(hdev);
48040493684eSMarcel Holtmann 
48050493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
48062a611692SJohan Hedberg 	if (!conn)
48072a611692SJohan Hedberg 		goto unlock;
48082a611692SJohan Hedberg 
4809c1d4fa7aSJohan Hedberg 	/* Reset the authentication requirement to unknown */
4810c1d4fa7aSJohan Hedberg 	conn->remote_auth = 0xff;
4811c1d4fa7aSJohan Hedberg 
48122a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
48132a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
48142a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
48152a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
48162a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
4817fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
4818e1e930f5SJohan Hedberg 		mgmt_auth_failed(conn, ev->status);
48192a611692SJohan Hedberg 
482076a68ba0SDavid Herrmann 	hci_conn_drop(conn);
48210493684eSMarcel Holtmann 
48222a611692SJohan Hedberg unlock:
48230493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
48240493684eSMarcel Holtmann }
48250493684eSMarcel Holtmann 
48266039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
4827807deac2SGustavo Padovan 					 struct sk_buff *skb)
482841a96212SMarcel Holtmann {
482941a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
483041a96212SMarcel Holtmann 	struct inquiry_entry *ie;
4831cad718edSJohan Hedberg 	struct hci_conn *conn;
483241a96212SMarcel Holtmann 
483341a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
483441a96212SMarcel Holtmann 
483541a96212SMarcel Holtmann 	hci_dev_lock(hdev);
483641a96212SMarcel Holtmann 
4837cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
4838cad718edSJohan Hedberg 	if (conn)
4839cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
4840cad718edSJohan Hedberg 
4841cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
4842cc11b9c1SAndrei Emeltchenko 	if (ie)
484302b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
484441a96212SMarcel Holtmann 
484541a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
484641a96212SMarcel Holtmann }
484741a96212SMarcel Holtmann 
48486039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
48492763eda6SSzymon Janc 					    struct sk_buff *skb)
48502763eda6SSzymon Janc {
48512763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
48522763eda6SSzymon Janc 	struct oob_data *data;
48532763eda6SSzymon Janc 
48542763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
48552763eda6SSzymon Janc 
48562763eda6SSzymon Janc 	hci_dev_lock(hdev);
48572763eda6SSzymon Janc 
4858d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
4859e1ba1f15SSzymon Janc 		goto unlock;
4860e1ba1f15SSzymon Janc 
48616928a924SJohan Hedberg 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR);
48626665d057SMarcel Holtmann 	if (!data) {
48636665d057SMarcel Holtmann 		struct hci_cp_remote_oob_data_neg_reply cp;
48646665d057SMarcel Holtmann 
48656665d057SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
48666665d057SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
48676665d057SMarcel Holtmann 			     sizeof(cp), &cp);
48686665d057SMarcel Holtmann 		goto unlock;
48696665d057SMarcel Holtmann 	}
48706665d057SMarcel Holtmann 
4871710f11c0SJohan Hedberg 	if (bredr_sc_enabled(hdev)) {
4872519ca9d0SMarcel Holtmann 		struct hci_cp_remote_oob_ext_data_reply cp;
4873519ca9d0SMarcel Holtmann 
4874519ca9d0SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
4875d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
48766665d057SMarcel Holtmann 			memset(cp.hash192, 0, sizeof(cp.hash192));
48776665d057SMarcel Holtmann 			memset(cp.rand192, 0, sizeof(cp.rand192));
48786665d057SMarcel Holtmann 		} else {
4879519ca9d0SMarcel Holtmann 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
488038da1703SJohan Hedberg 			memcpy(cp.rand192, data->rand192, sizeof(cp.rand192));
48816665d057SMarcel Holtmann 		}
4882519ca9d0SMarcel Holtmann 		memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
488338da1703SJohan Hedberg 		memcpy(cp.rand256, data->rand256, sizeof(cp.rand256));
4884519ca9d0SMarcel Holtmann 
4885519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
4886519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
4887519ca9d0SMarcel Holtmann 	} else {
48882763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
48892763eda6SSzymon Janc 
48902763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
4891519ca9d0SMarcel Holtmann 		memcpy(cp.hash, data->hash192, sizeof(cp.hash));
489238da1703SJohan Hedberg 		memcpy(cp.rand, data->rand192, sizeof(cp.rand));
48932763eda6SSzymon Janc 
4894519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
4895519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
4896519ca9d0SMarcel Holtmann 	}
48972763eda6SSzymon Janc 
4898e1ba1f15SSzymon Janc unlock:
48992763eda6SSzymon Janc 	hci_dev_unlock(hdev);
49002763eda6SSzymon Janc }
49012763eda6SSzymon Janc 
4902a77a6a14SArron Wang #if IS_ENABLED(CONFIG_BT_HS)
4903a77a6a14SArron Wang static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
4904a77a6a14SArron Wang {
4905a77a6a14SArron Wang 	struct hci_ev_channel_selected *ev = (void *)skb->data;
4906a77a6a14SArron Wang 	struct hci_conn *hcon;
4907a77a6a14SArron Wang 
4908a77a6a14SArron Wang 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
4909a77a6a14SArron Wang 
4910a77a6a14SArron Wang 	skb_pull(skb, sizeof(*ev));
4911a77a6a14SArron Wang 
4912a77a6a14SArron Wang 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
4913a77a6a14SArron Wang 	if (!hcon)
4914a77a6a14SArron Wang 		return;
4915a77a6a14SArron Wang 
4916a77a6a14SArron Wang 	amp_read_loc_assoc_final_data(hdev, hcon);
4917a77a6a14SArron Wang }
4918a77a6a14SArron Wang 
4919d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
4920d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
4921d5e91192SAndrei Emeltchenko {
4922d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
4923d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
4924d5e91192SAndrei Emeltchenko 
4925d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
4926d5e91192SAndrei Emeltchenko 	       ev->status);
4927d5e91192SAndrei Emeltchenko 
4928d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
4929d5e91192SAndrei Emeltchenko 
4930d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
4931d5e91192SAndrei Emeltchenko 	if (!hcon) {
4932d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
4933d5e91192SAndrei Emeltchenko 		return;
4934d5e91192SAndrei Emeltchenko 	}
4935d5e91192SAndrei Emeltchenko 
4936d5e91192SAndrei Emeltchenko 	if (ev->status) {
4937d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
4938d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
4939d5e91192SAndrei Emeltchenko 		return;
4940d5e91192SAndrei Emeltchenko 	}
4941d5e91192SAndrei Emeltchenko 
4942d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
4943d5e91192SAndrei Emeltchenko 
4944d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
4945d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
4946d5e91192SAndrei Emeltchenko 
4947d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
4948d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
494976a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
4950d5e91192SAndrei Emeltchenko 
495123b9ceb7SMarcel Holtmann 	hci_debugfs_create_conn(hcon);
4952d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
4953d5e91192SAndrei Emeltchenko 
4954cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
4955cf70ff22SAndrei Emeltchenko 
4956d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
4957d5e91192SAndrei Emeltchenko }
4958d5e91192SAndrei Emeltchenko 
495927695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
496027695fb4SAndrei Emeltchenko {
496127695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
496227695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
496327695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
496427695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
496527695fb4SAndrei Emeltchenko 
496627695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
496727695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
496827695fb4SAndrei Emeltchenko 	       ev->status);
496927695fb4SAndrei Emeltchenko 
497027695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
497127695fb4SAndrei Emeltchenko 	if (!hcon)
497227695fb4SAndrei Emeltchenko 		return;
497327695fb4SAndrei Emeltchenko 
497427695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
497527695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
497627695fb4SAndrei Emeltchenko 	if (!hchan)
497727695fb4SAndrei Emeltchenko 		return;
497827695fb4SAndrei Emeltchenko 
497927695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
498027695fb4SAndrei Emeltchenko 
498127695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
498227695fb4SAndrei Emeltchenko 
498327695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
498427695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
498527695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
498627695fb4SAndrei Emeltchenko 
498727695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
498827695fb4SAndrei Emeltchenko 
498927695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
499027695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
499127695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
499227695fb4SAndrei Emeltchenko 
499327695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
499427695fb4SAndrei Emeltchenko 	}
499527695fb4SAndrei Emeltchenko }
499627695fb4SAndrei Emeltchenko 
4997606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
4998606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
4999606e2a10SAndrei Emeltchenko {
5000606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
5001606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
5002606e2a10SAndrei Emeltchenko 
5003606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
5004606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
5005606e2a10SAndrei Emeltchenko 
5006606e2a10SAndrei Emeltchenko 	if (ev->status)
5007606e2a10SAndrei Emeltchenko 		return;
5008606e2a10SAndrei Emeltchenko 
5009606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
5010606e2a10SAndrei Emeltchenko 
5011606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
5012606e2a10SAndrei Emeltchenko 	if (!hchan)
5013606e2a10SAndrei Emeltchenko 		goto unlock;
5014606e2a10SAndrei Emeltchenko 
5015606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
5016606e2a10SAndrei Emeltchenko 
5017606e2a10SAndrei Emeltchenko unlock:
5018606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
5019606e2a10SAndrei Emeltchenko }
5020606e2a10SAndrei Emeltchenko 
50219eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
50229eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
50239eef6b3aSAndrei Emeltchenko {
50249eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
50259eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
50269eef6b3aSAndrei Emeltchenko 
50279eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
50289eef6b3aSAndrei Emeltchenko 
50299eef6b3aSAndrei Emeltchenko 	if (ev->status)
50309eef6b3aSAndrei Emeltchenko 		return;
50319eef6b3aSAndrei Emeltchenko 
50329eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
50339eef6b3aSAndrei Emeltchenko 
50349eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
50359eef6b3aSAndrei Emeltchenko 	if (hcon) {
50369eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
50379eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
50389eef6b3aSAndrei Emeltchenko 	}
50399eef6b3aSAndrei Emeltchenko 
50409eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
50419eef6b3aSAndrei Emeltchenko }
5042a77a6a14SArron Wang #endif
50439eef6b3aSAndrei Emeltchenko 
5044d12fb056SJaganath Kanakkassery static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
5045d12fb056SJaganath Kanakkassery 			bdaddr_t *bdaddr, u8 bdaddr_type, u8 role, u16 handle,
5046d12fb056SJaganath Kanakkassery 			u16 interval, u16 latency, u16 supervision_timeout)
5047fcd89c09SVille Tervo {
5048912b42efSJohan Hedberg 	struct hci_conn_params *params;
5049fcd89c09SVille Tervo 	struct hci_conn *conn;
505068d6f6deSJohan Hedberg 	struct smp_irk *irk;
5051837d502eSJohan Hedberg 	u8 addr_type;
5052fcd89c09SVille Tervo 
5053fcd89c09SVille Tervo 	hci_dev_lock(hdev);
5054fcd89c09SVille Tervo 
5055fbd96c15SJohan Hedberg 	/* All controllers implicitly stop advertising in the event of a
5056fbd96c15SJohan Hedberg 	 * connection, so ensure that the state bit is cleared.
5057fbd96c15SJohan Hedberg 	 */
5058a358dc11SMarcel Holtmann 	hci_dev_clear_flag(hdev, HCI_LE_ADV);
5059fbd96c15SJohan Hedberg 
5060e7d9ab73SJakub Pawlowski 	conn = hci_lookup_le_connect(hdev);
5061b62f328bSVille Tervo 	if (!conn) {
5062d12fb056SJaganath Kanakkassery 		conn = hci_conn_add(hdev, LE_LINK, bdaddr, role);
5063b62f328bSVille Tervo 		if (!conn) {
50642064ee33SMarcel Holtmann 			bt_dev_err(hdev, "no memory for new connection");
5065230fd16aSAndre Guedes 			goto unlock;
5066b62f328bSVille Tervo 		}
506729b7988aSAndre Guedes 
5068d12fb056SJaganath Kanakkassery 		conn->dst_type = bdaddr_type;
5069b9b343d2SAndre Guedes 
5070cb1d68f7SJohan Hedberg 		/* If we didn't have a hci_conn object previously
5071cb1d68f7SJohan Hedberg 		 * but we're in master role this must be something
5072cb1d68f7SJohan Hedberg 		 * initiated using a white list. Since white list based
5073cb1d68f7SJohan Hedberg 		 * connections are not "first class citizens" we don't
5074cb1d68f7SJohan Hedberg 		 * have full tracking of them. Therefore, we go ahead
5075cb1d68f7SJohan Hedberg 		 * with a "best effort" approach of determining the
5076cb1d68f7SJohan Hedberg 		 * initiator address based on the HCI_PRIVACY flag.
5077cb1d68f7SJohan Hedberg 		 */
5078cb1d68f7SJohan Hedberg 		if (conn->out) {
5079d12fb056SJaganath Kanakkassery 			conn->resp_addr_type = bdaddr_type;
5080d12fb056SJaganath Kanakkassery 			bacpy(&conn->resp_addr, bdaddr);
5081d7a5a11dSMarcel Holtmann 			if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
5082cb1d68f7SJohan Hedberg 				conn->init_addr_type = ADDR_LE_DEV_RANDOM;
5083cb1d68f7SJohan Hedberg 				bacpy(&conn->init_addr, &hdev->rpa);
5084cb1d68f7SJohan Hedberg 			} else {
5085cb1d68f7SJohan Hedberg 				hci_copy_identity_address(hdev,
5086cb1d68f7SJohan Hedberg 							  &conn->init_addr,
5087cb1d68f7SJohan Hedberg 							  &conn->init_addr_type);
5088cb1d68f7SJohan Hedberg 			}
508980c24ab8SJohan Hedberg 		}
5090cb1d68f7SJohan Hedberg 	} else {
509180c24ab8SJohan Hedberg 		cancel_delayed_work(&conn->le_conn_timeout);
509280c24ab8SJohan Hedberg 	}
509380c24ab8SJohan Hedberg 
509480c24ab8SJohan Hedberg 	if (!conn->out) {
5095cb1d68f7SJohan Hedberg 		/* Set the responder (our side) address type based on
5096cb1d68f7SJohan Hedberg 		 * the advertising address type.
5097cb1d68f7SJohan Hedberg 		 */
5098cb1d68f7SJohan Hedberg 		conn->resp_addr_type = hdev->adv_addr_type;
5099acf0aeaeSJaganath Kanakkassery 		if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) {
5100acf0aeaeSJaganath Kanakkassery 			/* In case of ext adv, resp_addr will be updated in
5101acf0aeaeSJaganath Kanakkassery 			 * Adv Terminated event.
5102acf0aeaeSJaganath Kanakkassery 			 */
5103acf0aeaeSJaganath Kanakkassery 			if (!ext_adv_capable(hdev))
5104cb1d68f7SJohan Hedberg 				bacpy(&conn->resp_addr, &hdev->random_addr);
5105acf0aeaeSJaganath Kanakkassery 		} else {
5106cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &hdev->bdaddr);
5107acf0aeaeSJaganath Kanakkassery 		}
5108cb1d68f7SJohan Hedberg 
5109d12fb056SJaganath Kanakkassery 		conn->init_addr_type = bdaddr_type;
5110d12fb056SJaganath Kanakkassery 		bacpy(&conn->init_addr, bdaddr);
5111a720d735SMarcel Holtmann 
5112a720d735SMarcel Holtmann 		/* For incoming connections, set the default minimum
5113a720d735SMarcel Holtmann 		 * and maximum connection interval. They will be used
5114a720d735SMarcel Holtmann 		 * to check if the parameters are in range and if not
5115a720d735SMarcel Holtmann 		 * trigger the connection update procedure.
5116a720d735SMarcel Holtmann 		 */
5117a720d735SMarcel Holtmann 		conn->le_conn_min_interval = hdev->le_conn_min_interval;
5118a720d735SMarcel Holtmann 		conn->le_conn_max_interval = hdev->le_conn_max_interval;
5119cb1d68f7SJohan Hedberg 	}
51207be2edbbSJohan Hedberg 
5121edb4b466SMarcel Holtmann 	/* Lookup the identity address from the stored connection
5122edb4b466SMarcel Holtmann 	 * address and address type.
5123edb4b466SMarcel Holtmann 	 *
5124edb4b466SMarcel Holtmann 	 * When establishing connections to an identity address, the
5125edb4b466SMarcel Holtmann 	 * connection procedure will store the resolvable random
5126edb4b466SMarcel Holtmann 	 * address first. Now if it can be converted back into the
5127edb4b466SMarcel Holtmann 	 * identity address, start using the identity address from
5128edb4b466SMarcel Holtmann 	 * now on.
5129edb4b466SMarcel Holtmann 	 */
5130edb4b466SMarcel Holtmann 	irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
513168d6f6deSJohan Hedberg 	if (irk) {
513268d6f6deSJohan Hedberg 		bacpy(&conn->dst, &irk->bdaddr);
513368d6f6deSJohan Hedberg 		conn->dst_type = irk->addr_type;
513468d6f6deSJohan Hedberg 	}
513568d6f6deSJohan Hedberg 
5136d12fb056SJaganath Kanakkassery 	if (status) {
5137d12fb056SJaganath Kanakkassery 		hci_le_conn_failed(conn, status);
5138837d502eSJohan Hedberg 		goto unlock;
5139837d502eSJohan Hedberg 	}
5140837d502eSJohan Hedberg 
514108853f18SJohan Hedberg 	if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
514208853f18SJohan Hedberg 		addr_type = BDADDR_LE_PUBLIC;
514308853f18SJohan Hedberg 	else
514408853f18SJohan Hedberg 		addr_type = BDADDR_LE_RANDOM;
514508853f18SJohan Hedberg 
51462d3c2260SJohan Hedberg 	/* Drop the connection if the device is blocked */
51472d3c2260SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) {
51482d3c2260SJohan Hedberg 		hci_conn_drop(conn);
5149cd17decbSAndre Guedes 		goto unlock;
5150cd17decbSAndre Guedes 	}
5151cd17decbSAndre Guedes 
5152b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
515348ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
515483bc71b4SVinicius Costa Gomes 
51557b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
5156d12fb056SJaganath Kanakkassery 	conn->handle = handle;
51570fe29fd1SMarcel Holtmann 	conn->state = BT_CONFIG;
5158fcd89c09SVille Tervo 
5159d12fb056SJaganath Kanakkassery 	conn->le_conn_interval = interval;
5160d12fb056SJaganath Kanakkassery 	conn->le_conn_latency = latency;
5161d12fb056SJaganath Kanakkassery 	conn->le_supv_timeout = supervision_timeout;
5162e04fde60SMarcel Holtmann 
516323b9ceb7SMarcel Holtmann 	hci_debugfs_create_conn(conn);
5164fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
5165fcd89c09SVille Tervo 
51660fe29fd1SMarcel Holtmann 	/* The remote features procedure is defined for master
51670fe29fd1SMarcel Holtmann 	 * role only. So only in case of an initiated connection
51680fe29fd1SMarcel Holtmann 	 * request the remote features.
51690fe29fd1SMarcel Holtmann 	 *
51700fe29fd1SMarcel Holtmann 	 * If the local controller supports slave-initiated features
51710fe29fd1SMarcel Holtmann 	 * exchange, then requesting the remote features in slave
51720fe29fd1SMarcel Holtmann 	 * role is possible. Otherwise just transition into the
51730fe29fd1SMarcel Holtmann 	 * connected state without requesting the remote features.
51740fe29fd1SMarcel Holtmann 	 */
51750fe29fd1SMarcel Holtmann 	if (conn->out ||
51760fe29fd1SMarcel Holtmann 	    (hdev->le_features[0] & HCI_LE_SLAVE_FEATURES)) {
51770fe29fd1SMarcel Holtmann 		struct hci_cp_le_read_remote_features cp;
51780fe29fd1SMarcel Holtmann 
51790fe29fd1SMarcel Holtmann 		cp.handle = __cpu_to_le16(conn->handle);
51800fe29fd1SMarcel Holtmann 
51810fe29fd1SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_LE_READ_REMOTE_FEATURES,
51820fe29fd1SMarcel Holtmann 			     sizeof(cp), &cp);
51830fe29fd1SMarcel Holtmann 
51840fe29fd1SMarcel Holtmann 		hci_conn_hold(conn);
51850fe29fd1SMarcel Holtmann 	} else {
51860fe29fd1SMarcel Holtmann 		conn->state = BT_CONNECTED;
5187d12fb056SJaganath Kanakkassery 		hci_connect_cfm(conn, status);
51880fe29fd1SMarcel Holtmann 	}
5189fcd89c09SVille Tervo 
51905477610fSJohan Hedberg 	params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
51915477610fSJohan Hedberg 					   conn->dst_type);
5192f161dd41SJohan Hedberg 	if (params) {
519395305baaSJohan Hedberg 		list_del_init(&params->action);
5194f161dd41SJohan Hedberg 		if (params->conn) {
5195f161dd41SJohan Hedberg 			hci_conn_drop(params->conn);
5196f8aaf9b6SJohan Hedberg 			hci_conn_put(params->conn);
5197f161dd41SJohan Hedberg 			params->conn = NULL;
5198f161dd41SJohan Hedberg 		}
5199f161dd41SJohan Hedberg 	}
5200a4790dbdSAndre Guedes 
5201fcd89c09SVille Tervo unlock:
5202223683a5SJohan Hedberg 	hci_update_background_scan(hdev);
5203fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
5204fcd89c09SVille Tervo }
5205fcd89c09SVille Tervo 
5206d12fb056SJaganath Kanakkassery static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
5207d12fb056SJaganath Kanakkassery {
5208d12fb056SJaganath Kanakkassery 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
5209d12fb056SJaganath Kanakkassery 
5210d12fb056SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
5211d12fb056SJaganath Kanakkassery 
5212d12fb056SJaganath Kanakkassery 	le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
5213d12fb056SJaganath Kanakkassery 			     ev->role, le16_to_cpu(ev->handle),
5214d12fb056SJaganath Kanakkassery 			     le16_to_cpu(ev->interval),
5215d12fb056SJaganath Kanakkassery 			     le16_to_cpu(ev->latency),
5216d12fb056SJaganath Kanakkassery 			     le16_to_cpu(ev->supervision_timeout));
5217d12fb056SJaganath Kanakkassery }
5218d12fb056SJaganath Kanakkassery 
52194d94f95dSJaganath Kanakkassery static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
52204d94f95dSJaganath Kanakkassery 					 struct sk_buff *skb)
52214d94f95dSJaganath Kanakkassery {
52224d94f95dSJaganath Kanakkassery 	struct hci_ev_le_enh_conn_complete *ev = (void *) skb->data;
52234d94f95dSJaganath Kanakkassery 
52244d94f95dSJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
52254d94f95dSJaganath Kanakkassery 
52264d94f95dSJaganath Kanakkassery 	le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
52274d94f95dSJaganath Kanakkassery 			     ev->role, le16_to_cpu(ev->handle),
52284d94f95dSJaganath Kanakkassery 			     le16_to_cpu(ev->interval),
52294d94f95dSJaganath Kanakkassery 			     le16_to_cpu(ev->latency),
52304d94f95dSJaganath Kanakkassery 			     le16_to_cpu(ev->supervision_timeout));
52315c49bcceSSathish Narasimman 
52325c49bcceSSathish Narasimman 	if (use_ll_privacy(hdev) &&
5233cbbdfa6fSSathish Narasimman 	    hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY) &&
52345c49bcceSSathish Narasimman 	    hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION))
52355c49bcceSSathish Narasimman 		hci_req_disable_address_resolution(hdev);
52364d94f95dSJaganath Kanakkassery }
52374d94f95dSJaganath Kanakkassery 
5238acf0aeaeSJaganath Kanakkassery static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
5239acf0aeaeSJaganath Kanakkassery {
5240acf0aeaeSJaganath Kanakkassery 	struct hci_evt_le_ext_adv_set_term *ev = (void *) skb->data;
5241acf0aeaeSJaganath Kanakkassery 	struct hci_conn *conn;
5242acf0aeaeSJaganath Kanakkassery 
5243acf0aeaeSJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
5244acf0aeaeSJaganath Kanakkassery 
5245acf0aeaeSJaganath Kanakkassery 	if (ev->status)
5246acf0aeaeSJaganath Kanakkassery 		return;
5247acf0aeaeSJaganath Kanakkassery 
5248acf0aeaeSJaganath Kanakkassery 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->conn_handle));
5249acf0aeaeSJaganath Kanakkassery 	if (conn) {
5250acf0aeaeSJaganath Kanakkassery 		struct adv_info *adv_instance;
5251acf0aeaeSJaganath Kanakkassery 
5252acf0aeaeSJaganath Kanakkassery 		if (hdev->adv_addr_type != ADDR_LE_DEV_RANDOM)
5253acf0aeaeSJaganath Kanakkassery 			return;
5254acf0aeaeSJaganath Kanakkassery 
5255acf0aeaeSJaganath Kanakkassery 		if (!hdev->cur_adv_instance) {
5256acf0aeaeSJaganath Kanakkassery 			bacpy(&conn->resp_addr, &hdev->random_addr);
5257acf0aeaeSJaganath Kanakkassery 			return;
5258acf0aeaeSJaganath Kanakkassery 		}
5259acf0aeaeSJaganath Kanakkassery 
5260acf0aeaeSJaganath Kanakkassery 		adv_instance = hci_find_adv_instance(hdev, hdev->cur_adv_instance);
5261acf0aeaeSJaganath Kanakkassery 		if (adv_instance)
5262acf0aeaeSJaganath Kanakkassery 			bacpy(&conn->resp_addr, &adv_instance->random_addr);
5263acf0aeaeSJaganath Kanakkassery 	}
5264acf0aeaeSJaganath Kanakkassery }
5265acf0aeaeSJaganath Kanakkassery 
52661855d92dSMarcel Holtmann static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
52671855d92dSMarcel Holtmann 					    struct sk_buff *skb)
52681855d92dSMarcel Holtmann {
52691855d92dSMarcel Holtmann 	struct hci_ev_le_conn_update_complete *ev = (void *) skb->data;
52701855d92dSMarcel Holtmann 	struct hci_conn *conn;
52711855d92dSMarcel Holtmann 
52721855d92dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
52731855d92dSMarcel Holtmann 
52741855d92dSMarcel Holtmann 	if (ev->status)
52751855d92dSMarcel Holtmann 		return;
52761855d92dSMarcel Holtmann 
52771855d92dSMarcel Holtmann 	hci_dev_lock(hdev);
52781855d92dSMarcel Holtmann 
52791855d92dSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
52801855d92dSMarcel Holtmann 	if (conn) {
52811855d92dSMarcel Holtmann 		conn->le_conn_interval = le16_to_cpu(ev->interval);
52821855d92dSMarcel Holtmann 		conn->le_conn_latency = le16_to_cpu(ev->latency);
52831855d92dSMarcel Holtmann 		conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
52841855d92dSMarcel Holtmann 	}
52851855d92dSMarcel Holtmann 
52861855d92dSMarcel Holtmann 	hci_dev_unlock(hdev);
52871855d92dSMarcel Holtmann }
52881855d92dSMarcel Holtmann 
5289a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */
5290fd45ada9SAlfonso Acosta static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
5291fd45ada9SAlfonso Acosta 					      bdaddr_t *addr,
5292082f2300SSzymon Janc 					      u8 addr_type, u8 adv_type,
5293082f2300SSzymon Janc 					      bdaddr_t *direct_rpa)
5294a4790dbdSAndre Guedes {
5295a4790dbdSAndre Guedes 	struct hci_conn *conn;
52964b9e7e75SMarcel Holtmann 	struct hci_conn_params *params;
5297a4790dbdSAndre Guedes 
52981c1abcabSJohan Hedberg 	/* If the event is not connectable don't proceed further */
52991c1abcabSJohan Hedberg 	if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND)
5300fd45ada9SAlfonso Acosta 		return NULL;
53011c1abcabSJohan Hedberg 
53021c1abcabSJohan Hedberg 	/* Ignore if the device is blocked */
5303dcc36c16SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type))
5304fd45ada9SAlfonso Acosta 		return NULL;
53051c1abcabSJohan Hedberg 
5306f99353cfSJohan Hedberg 	/* Most controller will fail if we try to create new connections
5307f99353cfSJohan Hedberg 	 * while we have an existing one in slave role.
5308f99353cfSJohan Hedberg 	 */
53094364f2e9SAlain Michaud 	if (hdev->conn_hash.le_num_slave > 0 &&
53104364f2e9SAlain Michaud 	    (!test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) ||
53114364f2e9SAlain Michaud 	     !(hdev->le_states[3] & 0x10)))
5312fd45ada9SAlfonso Acosta 		return NULL;
5313f99353cfSJohan Hedberg 
53141c1abcabSJohan Hedberg 	/* If we're not connectable only connect devices that we have in
53151c1abcabSJohan Hedberg 	 * our pend_le_conns list.
53161c1abcabSJohan Hedberg 	 */
531749c50922SJohan Hedberg 	params = hci_pend_le_action_lookup(&hdev->pend_le_conns, addr,
531849c50922SJohan Hedberg 					   addr_type);
53194b9e7e75SMarcel Holtmann 	if (!params)
5320fd45ada9SAlfonso Acosta 		return NULL;
5321a4790dbdSAndre Guedes 
532228a667c9SJakub Pawlowski 	if (!params->explicit_connect) {
53234b9e7e75SMarcel Holtmann 		switch (params->auto_connect) {
53244b9e7e75SMarcel Holtmann 		case HCI_AUTO_CONN_DIRECT:
53254b9e7e75SMarcel Holtmann 			/* Only devices advertising with ADV_DIRECT_IND are
53264b9e7e75SMarcel Holtmann 			 * triggering a connection attempt. This is allowing
53274b9e7e75SMarcel Holtmann 			 * incoming connections from slave devices.
53284b9e7e75SMarcel Holtmann 			 */
53294b9e7e75SMarcel Holtmann 			if (adv_type != LE_ADV_DIRECT_IND)
5330fd45ada9SAlfonso Acosta 				return NULL;
53314b9e7e75SMarcel Holtmann 			break;
53324b9e7e75SMarcel Holtmann 		case HCI_AUTO_CONN_ALWAYS:
53334b9e7e75SMarcel Holtmann 			/* Devices advertising with ADV_IND or ADV_DIRECT_IND
53344b9e7e75SMarcel Holtmann 			 * are triggering a connection attempt. This means
53351e5479beSAlain Michaud 			 * that incoming connections from slave device are
53364b9e7e75SMarcel Holtmann 			 * accepted and also outgoing connections to slave
53374b9e7e75SMarcel Holtmann 			 * devices are established when found.
53384b9e7e75SMarcel Holtmann 			 */
53394b9e7e75SMarcel Holtmann 			break;
53404b9e7e75SMarcel Holtmann 		default:
5341fd45ada9SAlfonso Acosta 			return NULL;
53424b9e7e75SMarcel Holtmann 		}
534328a667c9SJakub Pawlowski 	}
53444b9e7e75SMarcel Holtmann 
5345a4790dbdSAndre Guedes 	conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
534649b020c1SAlain Michaud 			      hdev->def_le_autoconnect_timeout, HCI_ROLE_MASTER,
5347082f2300SSzymon Janc 			      direct_rpa);
5348f161dd41SJohan Hedberg 	if (!IS_ERR(conn)) {
534928a667c9SJakub Pawlowski 		/* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned
535028a667c9SJakub Pawlowski 		 * by higher layer that tried to connect, if no then
535128a667c9SJakub Pawlowski 		 * store the pointer since we don't really have any
5352f161dd41SJohan Hedberg 		 * other owner of the object besides the params that
5353f161dd41SJohan Hedberg 		 * triggered it. This way we can abort the connection if
5354f161dd41SJohan Hedberg 		 * the parameters get removed and keep the reference
5355f161dd41SJohan Hedberg 		 * count consistent once the connection is established.
5356f161dd41SJohan Hedberg 		 */
535728a667c9SJakub Pawlowski 
535828a667c9SJakub Pawlowski 		if (!params->explicit_connect)
5359f8aaf9b6SJohan Hedberg 			params->conn = hci_conn_get(conn);
536028a667c9SJakub Pawlowski 
5361fd45ada9SAlfonso Acosta 		return conn;
5362f161dd41SJohan Hedberg 	}
5363a4790dbdSAndre Guedes 
5364a4790dbdSAndre Guedes 	switch (PTR_ERR(conn)) {
5365a4790dbdSAndre Guedes 	case -EBUSY:
5366a4790dbdSAndre Guedes 		/* If hci_connect() returns -EBUSY it means there is already
5367a4790dbdSAndre Guedes 		 * an LE connection attempt going on. Since controllers don't
5368a4790dbdSAndre Guedes 		 * support more than one connection attempt at the time, we
5369a4790dbdSAndre Guedes 		 * don't consider this an error case.
5370a4790dbdSAndre Guedes 		 */
5371a4790dbdSAndre Guedes 		break;
5372a4790dbdSAndre Guedes 	default:
5373a4790dbdSAndre Guedes 		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
5374fd45ada9SAlfonso Acosta 		return NULL;
5375a4790dbdSAndre Guedes 	}
5376fd45ada9SAlfonso Acosta 
5377fd45ada9SAlfonso Acosta 	return NULL;
5378a4790dbdSAndre Guedes }
5379a4790dbdSAndre Guedes 
53804af605d8SJohan Hedberg static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
53812f010b55SMarcel Holtmann 			       u8 bdaddr_type, bdaddr_t *direct_addr,
53822f010b55SMarcel Holtmann 			       u8 direct_addr_type, s8 rssi, u8 *data, u8 len)
53834af605d8SJohan Hedberg {
5384b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
53851c1abcabSJohan Hedberg 	struct smp_irk *irk;
5386fd45ada9SAlfonso Acosta 	struct hci_conn *conn;
5387474ee066SJohan Hedberg 	bool match;
5388c70a7e4cSMarcel Holtmann 	u32 flags;
53896818375eSSzymon Janc 	u8 *ptr, real_len;
53906818375eSSzymon Janc 
539156b40fbfSJohan Hedberg 	switch (type) {
539256b40fbfSJohan Hedberg 	case LE_ADV_IND:
539356b40fbfSJohan Hedberg 	case LE_ADV_DIRECT_IND:
539456b40fbfSJohan Hedberg 	case LE_ADV_SCAN_IND:
539556b40fbfSJohan Hedberg 	case LE_ADV_NONCONN_IND:
539656b40fbfSJohan Hedberg 	case LE_ADV_SCAN_RSP:
539756b40fbfSJohan Hedberg 		break;
539856b40fbfSJohan Hedberg 	default:
53992064ee33SMarcel Holtmann 		bt_dev_err_ratelimited(hdev, "unknown advertising packet "
54002064ee33SMarcel Holtmann 				       "type: 0x%02x", type);
540156b40fbfSJohan Hedberg 		return;
540256b40fbfSJohan Hedberg 	}
540356b40fbfSJohan Hedberg 
54046818375eSSzymon Janc 	/* Find the end of the data in case the report contains padded zero
54056818375eSSzymon Janc 	 * bytes at the end causing an invalid length value.
54066818375eSSzymon Janc 	 *
54076818375eSSzymon Janc 	 * When data is NULL, len is 0 so there is no need for extra ptr
54086818375eSSzymon Janc 	 * check as 'ptr < data + 0' is already false in such case.
54096818375eSSzymon Janc 	 */
54106818375eSSzymon Janc 	for (ptr = data; ptr < data + len && *ptr; ptr += *ptr + 1) {
54116818375eSSzymon Janc 		if (ptr + 1 + *ptr > data + len)
54126818375eSSzymon Janc 			break;
54136818375eSSzymon Janc 	}
54146818375eSSzymon Janc 
54156818375eSSzymon Janc 	real_len = ptr - data;
54166818375eSSzymon Janc 
54176818375eSSzymon Janc 	/* Adjust for actual length */
54186818375eSSzymon Janc 	if (len != real_len) {
5419943d5d92SDaniels Umanovskis 		bt_dev_err_ratelimited(hdev, "advertising data len corrected %u -> %u",
5420943d5d92SDaniels Umanovskis 				       len, real_len);
54216818375eSSzymon Janc 		len = real_len;
54226818375eSSzymon Janc 	}
5423b9a6328fSJohan Hedberg 
54242f010b55SMarcel Holtmann 	/* If the direct address is present, then this report is from
54252f010b55SMarcel Holtmann 	 * a LE Direct Advertising Report event. In that case it is
54262f010b55SMarcel Holtmann 	 * important to see if the address is matching the local
54272f010b55SMarcel Holtmann 	 * controller address.
54282f010b55SMarcel Holtmann 	 */
54292f010b55SMarcel Holtmann 	if (direct_addr) {
54302f010b55SMarcel Holtmann 		/* Only resolvable random addresses are valid for these
54312f010b55SMarcel Holtmann 		 * kind of reports and others can be ignored.
54322f010b55SMarcel Holtmann 		 */
54332f010b55SMarcel Holtmann 		if (!hci_bdaddr_is_rpa(direct_addr, direct_addr_type))
54342f010b55SMarcel Holtmann 			return;
54352f010b55SMarcel Holtmann 
54362f010b55SMarcel Holtmann 		/* If the controller is not using resolvable random
54372f010b55SMarcel Holtmann 		 * addresses, then this report can be ignored.
54382f010b55SMarcel Holtmann 		 */
5439d7a5a11dSMarcel Holtmann 		if (!hci_dev_test_flag(hdev, HCI_PRIVACY))
54402f010b55SMarcel Holtmann 			return;
54412f010b55SMarcel Holtmann 
54422f010b55SMarcel Holtmann 		/* If the local IRK of the controller does not match
54432f010b55SMarcel Holtmann 		 * with the resolvable random address provided, then
54442f010b55SMarcel Holtmann 		 * this report can be ignored.
54452f010b55SMarcel Holtmann 		 */
54462f010b55SMarcel Holtmann 		if (!smp_irk_matches(hdev, hdev->irk, direct_addr))
54472f010b55SMarcel Holtmann 			return;
54482f010b55SMarcel Holtmann 	}
54492f010b55SMarcel Holtmann 
5450435a13d8SJohan Hedberg 	/* Check if we need to convert to identity address */
5451435a13d8SJohan Hedberg 	irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
5452435a13d8SJohan Hedberg 	if (irk) {
5453435a13d8SJohan Hedberg 		bdaddr = &irk->bdaddr;
5454435a13d8SJohan Hedberg 		bdaddr_type = irk->addr_type;
5455435a13d8SJohan Hedberg 	}
5456435a13d8SJohan Hedberg 
5457082f2300SSzymon Janc 	/* Check if we have been requested to connect to this device.
5458082f2300SSzymon Janc 	 *
5459082f2300SSzymon Janc 	 * direct_addr is set only for directed advertising reports (it is NULL
5460082f2300SSzymon Janc 	 * for advertising reports) and is already verified to be RPA above.
5461082f2300SSzymon Janc 	 */
5462082f2300SSzymon Janc 	conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type,
5463082f2300SSzymon Janc 								direct_addr);
5464fd45ada9SAlfonso Acosta 	if (conn && type == LE_ADV_IND) {
5465fd45ada9SAlfonso Acosta 		/* Store report for later inclusion by
5466fd45ada9SAlfonso Acosta 		 * mgmt_device_connected
5467fd45ada9SAlfonso Acosta 		 */
5468fd45ada9SAlfonso Acosta 		memcpy(conn->le_adv_data, data, len);
5469fd45ada9SAlfonso Acosta 		conn->le_adv_data_len = len;
5470fd45ada9SAlfonso Acosta 	}
547199a6768eSJohan Hedberg 
54721c1abcabSJohan Hedberg 	/* Passive scanning shouldn't trigger any device found events,
54731c1abcabSJohan Hedberg 	 * except for devices marked as CONN_REPORT for which we do send
54748208f5a9SMiao-chen Chou 	 * device found events, or advertisement monitoring requested.
54751c1abcabSJohan Hedberg 	 */
54761c1abcabSJohan Hedberg 	if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
54770d2bf134SJohan Hedberg 		if (type == LE_ADV_DIRECT_IND)
54780d2bf134SJohan Hedberg 			return;
54790d2bf134SJohan Hedberg 
54803a19b6feSJohan Hedberg 		if (!hci_pend_le_action_lookup(&hdev->pend_le_reports,
54818208f5a9SMiao-chen Chou 					       bdaddr, bdaddr_type) &&
54828208f5a9SMiao-chen Chou 		    idr_is_empty(&hdev->adv_monitors_idr))
54830d2bf134SJohan Hedberg 			return;
54840d2bf134SJohan Hedberg 
54850d2bf134SJohan Hedberg 		if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND)
54860d2bf134SJohan Hedberg 			flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
54870d2bf134SJohan Hedberg 		else
54880d2bf134SJohan Hedberg 			flags = 0;
54890d2bf134SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
54900d2bf134SJohan Hedberg 				  rssi, flags, data, len, NULL, 0);
549197bf2e99SJohan Hedberg 		return;
5492ca5c4be7SJohan Hedberg 	}
54934af605d8SJohan Hedberg 
5494c70a7e4cSMarcel Holtmann 	/* When receiving non-connectable or scannable undirected
5495c70a7e4cSMarcel Holtmann 	 * advertising reports, this means that the remote device is
5496c70a7e4cSMarcel Holtmann 	 * not connectable and then clearly indicate this in the
5497c70a7e4cSMarcel Holtmann 	 * device found event.
5498c70a7e4cSMarcel Holtmann 	 *
5499c70a7e4cSMarcel Holtmann 	 * When receiving a scan response, then there is no way to
5500c70a7e4cSMarcel Holtmann 	 * know if the remote device is connectable or not. However
5501c70a7e4cSMarcel Holtmann 	 * since scan responses are merged with a previously seen
5502c70a7e4cSMarcel Holtmann 	 * advertising report, the flags field from that report
5503c70a7e4cSMarcel Holtmann 	 * will be used.
5504c70a7e4cSMarcel Holtmann 	 *
5505c70a7e4cSMarcel Holtmann 	 * In the really unlikely case that a controller get confused
5506c70a7e4cSMarcel Holtmann 	 * and just sends a scan response event, then it is marked as
5507c70a7e4cSMarcel Holtmann 	 * not connectable as well.
5508c70a7e4cSMarcel Holtmann 	 */
5509c70a7e4cSMarcel Holtmann 	if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND ||
5510c70a7e4cSMarcel Holtmann 	    type == LE_ADV_SCAN_RSP)
5511c70a7e4cSMarcel Holtmann 		flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
5512c70a7e4cSMarcel Holtmann 	else
5513c70a7e4cSMarcel Holtmann 		flags = 0;
5514c70a7e4cSMarcel Holtmann 
5515b9a6328fSJohan Hedberg 	/* If there's nothing pending either store the data from this
5516b9a6328fSJohan Hedberg 	 * event or send an immediate device found event if the data
5517b9a6328fSJohan Hedberg 	 * should not be stored for later.
5518b9a6328fSJohan Hedberg 	 */
5519b9a6328fSJohan Hedberg 	if (!has_pending_adv_report(hdev)) {
5520b9a6328fSJohan Hedberg 		/* If the report will trigger a SCAN_REQ store it for
5521b9a6328fSJohan Hedberg 		 * later merging.
5522b9a6328fSJohan Hedberg 		 */
5523b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
5524b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
5525c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
5526b9a6328fSJohan Hedberg 			return;
5527b9a6328fSJohan Hedberg 		}
5528b9a6328fSJohan Hedberg 
5529b9a6328fSJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
5530c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
5531b9a6328fSJohan Hedberg 		return;
5532b9a6328fSJohan Hedberg 	}
5533b9a6328fSJohan Hedberg 
5534474ee066SJohan Hedberg 	/* Check if the pending report is for the same device as the new one */
5535474ee066SJohan Hedberg 	match = (!bacmp(bdaddr, &d->last_adv_addr) &&
5536474ee066SJohan Hedberg 		 bdaddr_type == d->last_adv_addr_type);
5537474ee066SJohan Hedberg 
5538b9a6328fSJohan Hedberg 	/* If the pending data doesn't match this report or this isn't a
5539b9a6328fSJohan Hedberg 	 * scan response (e.g. we got a duplicate ADV_IND) then force
5540b9a6328fSJohan Hedberg 	 * sending of the pending data.
5541b9a6328fSJohan Hedberg 	 */
5542474ee066SJohan Hedberg 	if (type != LE_ADV_SCAN_RSP || !match) {
5543474ee066SJohan Hedberg 		/* Send out whatever is in the cache, but skip duplicates */
5544474ee066SJohan Hedberg 		if (!match)
5545b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
5546ff5cd29fSJohan Hedberg 					  d->last_adv_addr_type, NULL,
5547c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
5548ff5cd29fSJohan Hedberg 					  d->last_adv_data,
5549474ee066SJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
5550b9a6328fSJohan Hedberg 
5551b9a6328fSJohan Hedberg 		/* If the new report will trigger a SCAN_REQ store it for
5552b9a6328fSJohan Hedberg 		 * later merging.
5553b9a6328fSJohan Hedberg 		 */
5554b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
5555b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
5556c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
5557b9a6328fSJohan Hedberg 			return;
5558b9a6328fSJohan Hedberg 		}
5559b9a6328fSJohan Hedberg 
5560b9a6328fSJohan Hedberg 		/* The advertising reports cannot be merged, so clear
5561b9a6328fSJohan Hedberg 		 * the pending report and send out a device found event.
5562b9a6328fSJohan Hedberg 		 */
5563b9a6328fSJohan Hedberg 		clear_pending_adv_report(hdev);
55645c5b93e4SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
5565c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
5566b9a6328fSJohan Hedberg 		return;
5567b9a6328fSJohan Hedberg 	}
5568b9a6328fSJohan Hedberg 
5569b9a6328fSJohan Hedberg 	/* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
5570b9a6328fSJohan Hedberg 	 * the new event is a SCAN_RSP. We can therefore proceed with
5571b9a6328fSJohan Hedberg 	 * sending a merged device found event.
5572b9a6328fSJohan Hedberg 	 */
5573b9a6328fSJohan Hedberg 	mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
5574c70a7e4cSMarcel Holtmann 			  d->last_adv_addr_type, NULL, rssi, d->last_adv_flags,
557542bd6a56SMarcel Holtmann 			  d->last_adv_data, d->last_adv_data_len, data, len);
5576b9a6328fSJohan Hedberg 	clear_pending_adv_report(hdev);
55774af605d8SJohan Hedberg }
55784af605d8SJohan Hedberg 
55796039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
55809aa04c91SAndre Guedes {
5581e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
5582e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
55839aa04c91SAndre Guedes 
5584a4790dbdSAndre Guedes 	hci_dev_lock(hdev);
5585a4790dbdSAndre Guedes 
5586e95beb41SAndre Guedes 	while (num_reports--) {
5587e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
55884af605d8SJohan Hedberg 		s8 rssi;
5589a4790dbdSAndre Guedes 
5590ee649346SChriz Chow 		if (ev->length <= HCI_MAX_AD_LENGTH) {
55913c9e9195SAndre Guedes 			rssi = ev->data[ev->length];
55924af605d8SJohan Hedberg 			process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
55932f010b55SMarcel Holtmann 					   ev->bdaddr_type, NULL, 0, rssi,
55942f010b55SMarcel Holtmann 					   ev->data, ev->length);
5595ee649346SChriz Chow 		} else {
5596ee649346SChriz Chow 			bt_dev_err(hdev, "Dropping invalid advertising data");
5597ee649346SChriz Chow 		}
55983c9e9195SAndre Guedes 
5599e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
56009aa04c91SAndre Guedes 	}
5601a4790dbdSAndre Guedes 
5602a4790dbdSAndre Guedes 	hci_dev_unlock(hdev);
56039aa04c91SAndre Guedes }
56049aa04c91SAndre Guedes 
5605657cc646SMarcel Holtmann static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type)
5606c215e939SJaganath Kanakkassery {
5607b2cc9761SJaganath Kanakkassery 	if (evt_type & LE_EXT_ADV_LEGACY_PDU) {
5608c215e939SJaganath Kanakkassery 		switch (evt_type) {
5609c215e939SJaganath Kanakkassery 		case LE_LEGACY_ADV_IND:
5610c215e939SJaganath Kanakkassery 			return LE_ADV_IND;
5611c215e939SJaganath Kanakkassery 		case LE_LEGACY_ADV_DIRECT_IND:
5612c215e939SJaganath Kanakkassery 			return LE_ADV_DIRECT_IND;
5613c215e939SJaganath Kanakkassery 		case LE_LEGACY_ADV_SCAN_IND:
5614c215e939SJaganath Kanakkassery 			return LE_ADV_SCAN_IND;
5615c215e939SJaganath Kanakkassery 		case LE_LEGACY_NONCONN_IND:
5616c215e939SJaganath Kanakkassery 			return LE_ADV_NONCONN_IND;
5617c215e939SJaganath Kanakkassery 		case LE_LEGACY_SCAN_RSP_ADV:
5618c215e939SJaganath Kanakkassery 		case LE_LEGACY_SCAN_RSP_ADV_SCAN:
5619c215e939SJaganath Kanakkassery 			return LE_ADV_SCAN_RSP;
5620c215e939SJaganath Kanakkassery 		}
5621c215e939SJaganath Kanakkassery 
5622657cc646SMarcel Holtmann 		goto invalid;
5623c215e939SJaganath Kanakkassery 	}
5624c215e939SJaganath Kanakkassery 
5625b2cc9761SJaganath Kanakkassery 	if (evt_type & LE_EXT_ADV_CONN_IND) {
5626b2cc9761SJaganath Kanakkassery 		if (evt_type & LE_EXT_ADV_DIRECT_IND)
5627b2cc9761SJaganath Kanakkassery 			return LE_ADV_DIRECT_IND;
5628b2cc9761SJaganath Kanakkassery 
5629b2cc9761SJaganath Kanakkassery 		return LE_ADV_IND;
5630b2cc9761SJaganath Kanakkassery 	}
5631b2cc9761SJaganath Kanakkassery 
5632b2cc9761SJaganath Kanakkassery 	if (evt_type & LE_EXT_ADV_SCAN_RSP)
5633b2cc9761SJaganath Kanakkassery 		return LE_ADV_SCAN_RSP;
5634b2cc9761SJaganath Kanakkassery 
5635b2cc9761SJaganath Kanakkassery 	if (evt_type & LE_EXT_ADV_SCAN_IND)
5636b2cc9761SJaganath Kanakkassery 		return LE_ADV_SCAN_IND;
5637b2cc9761SJaganath Kanakkassery 
5638b2cc9761SJaganath Kanakkassery 	if (evt_type == LE_EXT_ADV_NON_CONN_IND ||
5639b2cc9761SJaganath Kanakkassery 	    evt_type & LE_EXT_ADV_DIRECT_IND)
5640b2cc9761SJaganath Kanakkassery 		return LE_ADV_NONCONN_IND;
5641b2cc9761SJaganath Kanakkassery 
5642657cc646SMarcel Holtmann invalid:
5643657cc646SMarcel Holtmann 	bt_dev_err_ratelimited(hdev, "Unknown advertising packet type: 0x%02x",
5644b2cc9761SJaganath Kanakkassery 			       evt_type);
5645b2cc9761SJaganath Kanakkassery 
5646b2cc9761SJaganath Kanakkassery 	return LE_ADV_INVALID;
5647b2cc9761SJaganath Kanakkassery }
5648b2cc9761SJaganath Kanakkassery 
5649c215e939SJaganath Kanakkassery static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
5650c215e939SJaganath Kanakkassery {
5651c215e939SJaganath Kanakkassery 	u8 num_reports = skb->data[0];
5652c215e939SJaganath Kanakkassery 	void *ptr = &skb->data[1];
5653c215e939SJaganath Kanakkassery 
5654c215e939SJaganath Kanakkassery 	hci_dev_lock(hdev);
5655c215e939SJaganath Kanakkassery 
5656c215e939SJaganath Kanakkassery 	while (num_reports--) {
5657c215e939SJaganath Kanakkassery 		struct hci_ev_le_ext_adv_report *ev = ptr;
5658c215e939SJaganath Kanakkassery 		u8 legacy_evt_type;
5659c215e939SJaganath Kanakkassery 		u16 evt_type;
5660c215e939SJaganath Kanakkassery 
5661c215e939SJaganath Kanakkassery 		evt_type = __le16_to_cpu(ev->evt_type);
5662657cc646SMarcel Holtmann 		legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type);
5663c215e939SJaganath Kanakkassery 		if (legacy_evt_type != LE_ADV_INVALID) {
5664c215e939SJaganath Kanakkassery 			process_adv_report(hdev, legacy_evt_type, &ev->bdaddr,
5665c215e939SJaganath Kanakkassery 					   ev->bdaddr_type, NULL, 0, ev->rssi,
5666c215e939SJaganath Kanakkassery 					   ev->data, ev->length);
5667c215e939SJaganath Kanakkassery 		}
5668c215e939SJaganath Kanakkassery 
5669cd9151b6SJaganath Kanakkassery 		ptr += sizeof(*ev) + ev->length;
5670c215e939SJaganath Kanakkassery 	}
5671c215e939SJaganath Kanakkassery 
5672c215e939SJaganath Kanakkassery 	hci_dev_unlock(hdev);
5673c215e939SJaganath Kanakkassery }
5674c215e939SJaganath Kanakkassery 
56750fe29fd1SMarcel Holtmann static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
56760fe29fd1SMarcel Holtmann 					    struct sk_buff *skb)
56770fe29fd1SMarcel Holtmann {
56780fe29fd1SMarcel Holtmann 	struct hci_ev_le_remote_feat_complete *ev = (void *)skb->data;
56790fe29fd1SMarcel Holtmann 	struct hci_conn *conn;
56800fe29fd1SMarcel Holtmann 
56810fe29fd1SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
56820fe29fd1SMarcel Holtmann 
56830fe29fd1SMarcel Holtmann 	hci_dev_lock(hdev);
56840fe29fd1SMarcel Holtmann 
56850fe29fd1SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
56860fe29fd1SMarcel Holtmann 	if (conn) {
56870fe29fd1SMarcel Holtmann 		if (!ev->status)
56880fe29fd1SMarcel Holtmann 			memcpy(conn->features[0], ev->features, 8);
56890fe29fd1SMarcel Holtmann 
56900fe29fd1SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
56910fe29fd1SMarcel Holtmann 			__u8 status;
56920fe29fd1SMarcel Holtmann 
56930fe29fd1SMarcel Holtmann 			/* If the local controller supports slave-initiated
56940fe29fd1SMarcel Holtmann 			 * features exchange, but the remote controller does
56950fe29fd1SMarcel Holtmann 			 * not, then it is possible that the error code 0x1a
56960fe29fd1SMarcel Holtmann 			 * for unsupported remote feature gets returned.
56970fe29fd1SMarcel Holtmann 			 *
56980fe29fd1SMarcel Holtmann 			 * In this specific case, allow the connection to
56990fe29fd1SMarcel Holtmann 			 * transition into connected state and mark it as
57000fe29fd1SMarcel Holtmann 			 * successful.
57010fe29fd1SMarcel Holtmann 			 */
57020fe29fd1SMarcel Holtmann 			if ((hdev->le_features[0] & HCI_LE_SLAVE_FEATURES) &&
57030fe29fd1SMarcel Holtmann 			    !conn->out && ev->status == 0x1a)
57040fe29fd1SMarcel Holtmann 				status = 0x00;
57050fe29fd1SMarcel Holtmann 			else
57060fe29fd1SMarcel Holtmann 				status = ev->status;
57070fe29fd1SMarcel Holtmann 
57080fe29fd1SMarcel Holtmann 			conn->state = BT_CONNECTED;
57090fe29fd1SMarcel Holtmann 			hci_connect_cfm(conn, status);
57100fe29fd1SMarcel Holtmann 			hci_conn_drop(conn);
57110fe29fd1SMarcel Holtmann 		}
57120fe29fd1SMarcel Holtmann 	}
57130fe29fd1SMarcel Holtmann 
57140fe29fd1SMarcel Holtmann 	hci_dev_unlock(hdev);
57150fe29fd1SMarcel Holtmann }
57160fe29fd1SMarcel Holtmann 
57176039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
5718a7a595f6SVinicius Costa Gomes {
5719a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
5720a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
5721bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
5722a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
5723c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
5724a7a595f6SVinicius Costa Gomes 
57259f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
5726a7a595f6SVinicius Costa Gomes 
5727a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
5728a7a595f6SVinicius Costa Gomes 
5729a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
5730bea710feSVinicius Costa Gomes 	if (conn == NULL)
5731bea710feSVinicius Costa Gomes 		goto not_found;
5732a7a595f6SVinicius Costa Gomes 
5733f3a73d97SJohan Hedberg 	ltk = hci_find_ltk(hdev, &conn->dst, conn->dst_type, conn->role);
57345378bc56SJohan Hedberg 	if (!ltk)
5735bea710feSVinicius Costa Gomes 		goto not_found;
5736bea710feSVinicius Costa Gomes 
57375378bc56SJohan Hedberg 	if (smp_ltk_is_sc(ltk)) {
57385378bc56SJohan Hedberg 		/* With SC both EDiv and Rand are set to zero */
57395378bc56SJohan Hedberg 		if (ev->ediv || ev->rand)
57405378bc56SJohan Hedberg 			goto not_found;
57415378bc56SJohan Hedberg 	} else {
57425378bc56SJohan Hedberg 		/* For non-SC keys check that EDiv and Rand match */
57435378bc56SJohan Hedberg 		if (ev->ediv != ltk->ediv || ev->rand != ltk->rand)
57445378bc56SJohan Hedberg 			goto not_found;
57455378bc56SJohan Hedberg 	}
57465378bc56SJohan Hedberg 
57478b76ce34SJohan Hedberg 	memcpy(cp.ltk, ltk->val, ltk->enc_size);
57488b76ce34SJohan Hedberg 	memset(cp.ltk + ltk->enc_size, 0, sizeof(cp.ltk) - ltk->enc_size);
5749a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
5750c9839a11SVinicius Costa Gomes 
5751a6f7833cSJohan Hedberg 	conn->pending_sec_level = smp_ltk_sec_level(ltk);
5752a7a595f6SVinicius Costa Gomes 
575389cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
5754a7a595f6SVinicius Costa Gomes 
5755a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
5756a7a595f6SVinicius Costa Gomes 
57575981a882SClaudio Takahasi 	/* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a
57585981a882SClaudio Takahasi 	 * temporary key used to encrypt a connection following
57595981a882SClaudio Takahasi 	 * pairing. It is used during the Encrypted Session Setup to
57605981a882SClaudio Takahasi 	 * distribute the keys. Later, security can be re-established
57615981a882SClaudio Takahasi 	 * using a distributed LTK.
57625981a882SClaudio Takahasi 	 */
57632ceba539SJohan Hedberg 	if (ltk->type == SMP_STK) {
5764fe59a05fSJohan Hedberg 		set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
5765970d0f1bSJohan Hedberg 		list_del_rcu(&ltk->list);
5766970d0f1bSJohan Hedberg 		kfree_rcu(ltk, rcu);
5767fe59a05fSJohan Hedberg 	} else {
5768fe59a05fSJohan Hedberg 		clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
5769c9839a11SVinicius Costa Gomes 	}
5770c9839a11SVinicius Costa Gomes 
5771a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
5772bea710feSVinicius Costa Gomes 
5773bea710feSVinicius Costa Gomes 	return;
5774bea710feSVinicius Costa Gomes 
5775bea710feSVinicius Costa Gomes not_found:
5776bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
5777bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
5778bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
5779a7a595f6SVinicius Costa Gomes }
5780a7a595f6SVinicius Costa Gomes 
57818e75b46aSAndre Guedes static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
57828e75b46aSAndre Guedes 				      u8 reason)
57838e75b46aSAndre Guedes {
57848e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_neg_reply cp;
57858e75b46aSAndre Guedes 
57868e75b46aSAndre Guedes 	cp.handle = cpu_to_le16(handle);
57878e75b46aSAndre Guedes 	cp.reason = reason;
57888e75b46aSAndre Guedes 
57898e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp),
57908e75b46aSAndre Guedes 		     &cp);
57918e75b46aSAndre Guedes }
57928e75b46aSAndre Guedes 
57938e75b46aSAndre Guedes static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
57948e75b46aSAndre Guedes 					     struct sk_buff *skb)
57958e75b46aSAndre Guedes {
57968e75b46aSAndre Guedes 	struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data;
57978e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_reply cp;
57988e75b46aSAndre Guedes 	struct hci_conn *hcon;
57998e75b46aSAndre Guedes 	u16 handle, min, max, latency, timeout;
58008e75b46aSAndre Guedes 
58018e75b46aSAndre Guedes 	handle = le16_to_cpu(ev->handle);
58028e75b46aSAndre Guedes 	min = le16_to_cpu(ev->interval_min);
58038e75b46aSAndre Guedes 	max = le16_to_cpu(ev->interval_max);
58048e75b46aSAndre Guedes 	latency = le16_to_cpu(ev->latency);
58058e75b46aSAndre Guedes 	timeout = le16_to_cpu(ev->timeout);
58068e75b46aSAndre Guedes 
58078e75b46aSAndre Guedes 	hcon = hci_conn_hash_lookup_handle(hdev, handle);
58088e75b46aSAndre Guedes 	if (!hcon || hcon->state != BT_CONNECTED)
58098e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
58108e75b46aSAndre Guedes 						 HCI_ERROR_UNKNOWN_CONN_ID);
58118e75b46aSAndre Guedes 
58128e75b46aSAndre Guedes 	if (hci_check_conn_params(min, max, latency, timeout))
58138e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
58148e75b46aSAndre Guedes 						 HCI_ERROR_INVALID_LL_PARAMS);
58158e75b46aSAndre Guedes 
581640bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_MASTER) {
5817348d50b8SJohan Hedberg 		struct hci_conn_params *params;
5818f4869e2aSJohan Hedberg 		u8 store_hint;
5819348d50b8SJohan Hedberg 
5820348d50b8SJohan Hedberg 		hci_dev_lock(hdev);
5821348d50b8SJohan Hedberg 
5822348d50b8SJohan Hedberg 		params = hci_conn_params_lookup(hdev, &hcon->dst,
5823348d50b8SJohan Hedberg 						hcon->dst_type);
5824348d50b8SJohan Hedberg 		if (params) {
5825348d50b8SJohan Hedberg 			params->conn_min_interval = min;
5826348d50b8SJohan Hedberg 			params->conn_max_interval = max;
5827348d50b8SJohan Hedberg 			params->conn_latency = latency;
5828348d50b8SJohan Hedberg 			params->supervision_timeout = timeout;
5829f4869e2aSJohan Hedberg 			store_hint = 0x01;
5830f4869e2aSJohan Hedberg 		} else{
5831f4869e2aSJohan Hedberg 			store_hint = 0x00;
5832348d50b8SJohan Hedberg 		}
5833348d50b8SJohan Hedberg 
5834348d50b8SJohan Hedberg 		hci_dev_unlock(hdev);
5835348d50b8SJohan Hedberg 
5836f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type,
5837f4869e2aSJohan Hedberg 				    store_hint, min, max, latency, timeout);
5838348d50b8SJohan Hedberg 	}
5839ffb5a827SAndre Guedes 
58408e75b46aSAndre Guedes 	cp.handle = ev->handle;
58418e75b46aSAndre Guedes 	cp.interval_min = ev->interval_min;
58428e75b46aSAndre Guedes 	cp.interval_max = ev->interval_max;
58438e75b46aSAndre Guedes 	cp.latency = ev->latency;
58448e75b46aSAndre Guedes 	cp.timeout = ev->timeout;
58458e75b46aSAndre Guedes 	cp.min_ce_len = 0;
58468e75b46aSAndre Guedes 	cp.max_ce_len = 0;
58478e75b46aSAndre Guedes 
58488e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
58498e75b46aSAndre Guedes }
58508e75b46aSAndre Guedes 
58512f010b55SMarcel Holtmann static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
58522f010b55SMarcel Holtmann 					 struct sk_buff *skb)
58532f010b55SMarcel Holtmann {
58542f010b55SMarcel Holtmann 	u8 num_reports = skb->data[0];
58552f010b55SMarcel Holtmann 	void *ptr = &skb->data[1];
58562f010b55SMarcel Holtmann 
58572f010b55SMarcel Holtmann 	hci_dev_lock(hdev);
58582f010b55SMarcel Holtmann 
58592f010b55SMarcel Holtmann 	while (num_reports--) {
58602f010b55SMarcel Holtmann 		struct hci_ev_le_direct_adv_info *ev = ptr;
58612f010b55SMarcel Holtmann 
58622f010b55SMarcel Holtmann 		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
58632f010b55SMarcel Holtmann 				   ev->bdaddr_type, &ev->direct_addr,
58642f010b55SMarcel Holtmann 				   ev->direct_addr_type, ev->rssi, NULL, 0);
58652f010b55SMarcel Holtmann 
58662f010b55SMarcel Holtmann 		ptr += sizeof(*ev);
58672f010b55SMarcel Holtmann 	}
58682f010b55SMarcel Holtmann 
58692f010b55SMarcel Holtmann 	hci_dev_unlock(hdev);
58702f010b55SMarcel Holtmann }
58712f010b55SMarcel Holtmann 
58721efd927dSLuiz Augusto von Dentz static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
58731efd927dSLuiz Augusto von Dentz {
58741efd927dSLuiz Augusto von Dentz 	struct hci_ev_le_phy_update_complete *ev = (void *) skb->data;
58751efd927dSLuiz Augusto von Dentz 	struct hci_conn *conn;
58761efd927dSLuiz Augusto von Dentz 
58771efd927dSLuiz Augusto von Dentz 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
58781efd927dSLuiz Augusto von Dentz 
58791efd927dSLuiz Augusto von Dentz 	if (!ev->status)
58801efd927dSLuiz Augusto von Dentz 		return;
58811efd927dSLuiz Augusto von Dentz 
58821efd927dSLuiz Augusto von Dentz 	hci_dev_lock(hdev);
58831efd927dSLuiz Augusto von Dentz 
58841efd927dSLuiz Augusto von Dentz 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
58851efd927dSLuiz Augusto von Dentz 	if (!conn)
58861efd927dSLuiz Augusto von Dentz 		goto unlock;
58871efd927dSLuiz Augusto von Dentz 
58881efd927dSLuiz Augusto von Dentz 	conn->le_tx_phy = ev->tx_phy;
58891efd927dSLuiz Augusto von Dentz 	conn->le_rx_phy = ev->rx_phy;
58901efd927dSLuiz Augusto von Dentz 
58911efd927dSLuiz Augusto von Dentz unlock:
58921efd927dSLuiz Augusto von Dentz 	hci_dev_unlock(hdev);
58931efd927dSLuiz Augusto von Dentz }
58941efd927dSLuiz Augusto von Dentz 
58956039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
5896fcd89c09SVille Tervo {
5897fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
5898fcd89c09SVille Tervo 
5899fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
5900fcd89c09SVille Tervo 
5901fcd89c09SVille Tervo 	switch (le_ev->subevent) {
5902fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
5903fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
5904fcd89c09SVille Tervo 		break;
5905fcd89c09SVille Tervo 
59061855d92dSMarcel Holtmann 	case HCI_EV_LE_CONN_UPDATE_COMPLETE:
59071855d92dSMarcel Holtmann 		hci_le_conn_update_complete_evt(hdev, skb);
59081855d92dSMarcel Holtmann 		break;
59091855d92dSMarcel Holtmann 
59109aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
59119aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
59129aa04c91SAndre Guedes 		break;
59139aa04c91SAndre Guedes 
59140fe29fd1SMarcel Holtmann 	case HCI_EV_LE_REMOTE_FEAT_COMPLETE:
59150fe29fd1SMarcel Holtmann 		hci_le_remote_feat_complete_evt(hdev, skb);
59160fe29fd1SMarcel Holtmann 		break;
59170fe29fd1SMarcel Holtmann 
5918a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
5919a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
5920a7a595f6SVinicius Costa Gomes 		break;
5921a7a595f6SVinicius Costa Gomes 
59228e75b46aSAndre Guedes 	case HCI_EV_LE_REMOTE_CONN_PARAM_REQ:
59238e75b46aSAndre Guedes 		hci_le_remote_conn_param_req_evt(hdev, skb);
59248e75b46aSAndre Guedes 		break;
59258e75b46aSAndre Guedes 
59262f010b55SMarcel Holtmann 	case HCI_EV_LE_DIRECT_ADV_REPORT:
59272f010b55SMarcel Holtmann 		hci_le_direct_adv_report_evt(hdev, skb);
59282f010b55SMarcel Holtmann 		break;
59292f010b55SMarcel Holtmann 
59301efd927dSLuiz Augusto von Dentz 	case HCI_EV_LE_PHY_UPDATE_COMPLETE:
59311efd927dSLuiz Augusto von Dentz 		hci_le_phy_update_evt(hdev, skb);
59321efd927dSLuiz Augusto von Dentz 		break;
59331efd927dSLuiz Augusto von Dentz 
5934c215e939SJaganath Kanakkassery 	case HCI_EV_LE_EXT_ADV_REPORT:
5935c215e939SJaganath Kanakkassery 		hci_le_ext_adv_report_evt(hdev, skb);
5936c215e939SJaganath Kanakkassery 		break;
5937c215e939SJaganath Kanakkassery 
59384d94f95dSJaganath Kanakkassery 	case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
59394d94f95dSJaganath Kanakkassery 		hci_le_enh_conn_complete_evt(hdev, skb);
59404d94f95dSJaganath Kanakkassery 		break;
59414d94f95dSJaganath Kanakkassery 
5942acf0aeaeSJaganath Kanakkassery 	case HCI_EV_LE_EXT_ADV_SET_TERM:
5943acf0aeaeSJaganath Kanakkassery 		hci_le_ext_adv_term_evt(hdev, skb);
5944acf0aeaeSJaganath Kanakkassery 		break;
5945acf0aeaeSJaganath Kanakkassery 
5946fcd89c09SVille Tervo 	default:
5947fcd89c09SVille Tervo 		break;
5948fcd89c09SVille Tervo 	}
5949fcd89c09SVille Tervo }
5950fcd89c09SVille Tervo 
5951757aa0b5SJohan Hedberg static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
5952757aa0b5SJohan Hedberg 				 u8 event, struct sk_buff *skb)
5953757aa0b5SJohan Hedberg {
5954757aa0b5SJohan Hedberg 	struct hci_ev_cmd_complete *ev;
5955757aa0b5SJohan Hedberg 	struct hci_event_hdr *hdr;
5956757aa0b5SJohan Hedberg 
5957757aa0b5SJohan Hedberg 	if (!skb)
5958757aa0b5SJohan Hedberg 		return false;
5959757aa0b5SJohan Hedberg 
5960757aa0b5SJohan Hedberg 	if (skb->len < sizeof(*hdr)) {
59612064ee33SMarcel Holtmann 		bt_dev_err(hdev, "too short HCI event");
5962757aa0b5SJohan Hedberg 		return false;
5963757aa0b5SJohan Hedberg 	}
5964757aa0b5SJohan Hedberg 
5965757aa0b5SJohan Hedberg 	hdr = (void *) skb->data;
5966757aa0b5SJohan Hedberg 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
5967757aa0b5SJohan Hedberg 
5968757aa0b5SJohan Hedberg 	if (event) {
5969757aa0b5SJohan Hedberg 		if (hdr->evt != event)
5970757aa0b5SJohan Hedberg 			return false;
5971757aa0b5SJohan Hedberg 		return true;
5972757aa0b5SJohan Hedberg 	}
5973757aa0b5SJohan Hedberg 
59741629db9cSJohan Hedberg 	/* Check if request ended in Command Status - no way to retreive
59751629db9cSJohan Hedberg 	 * any extra parameters in this case.
59761629db9cSJohan Hedberg 	 */
59771629db9cSJohan Hedberg 	if (hdr->evt == HCI_EV_CMD_STATUS)
59781629db9cSJohan Hedberg 		return false;
59791629db9cSJohan Hedberg 
5980757aa0b5SJohan Hedberg 	if (hdr->evt != HCI_EV_CMD_COMPLETE) {
59812064ee33SMarcel Holtmann 		bt_dev_err(hdev, "last event is not cmd complete (0x%2.2x)",
59822064ee33SMarcel Holtmann 			   hdr->evt);
5983757aa0b5SJohan Hedberg 		return false;
5984757aa0b5SJohan Hedberg 	}
5985757aa0b5SJohan Hedberg 
5986757aa0b5SJohan Hedberg 	if (skb->len < sizeof(*ev)) {
59872064ee33SMarcel Holtmann 		bt_dev_err(hdev, "too short cmd_complete event");
5988757aa0b5SJohan Hedberg 		return false;
5989757aa0b5SJohan Hedberg 	}
5990757aa0b5SJohan Hedberg 
5991757aa0b5SJohan Hedberg 	ev = (void *) skb->data;
5992757aa0b5SJohan Hedberg 	skb_pull(skb, sizeof(*ev));
5993757aa0b5SJohan Hedberg 
5994757aa0b5SJohan Hedberg 	if (opcode != __le16_to_cpu(ev->opcode)) {
5995757aa0b5SJohan Hedberg 		BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode,
5996757aa0b5SJohan Hedberg 		       __le16_to_cpu(ev->opcode));
5997757aa0b5SJohan Hedberg 		return false;
5998757aa0b5SJohan Hedberg 	}
5999757aa0b5SJohan Hedberg 
6000757aa0b5SJohan Hedberg 	return true;
6001757aa0b5SJohan Hedberg }
6002757aa0b5SJohan Hedberg 
60032f20216cSAbhishek Pandit-Subedi static void hci_store_wake_reason(struct hci_dev *hdev, u8 event,
60042f20216cSAbhishek Pandit-Subedi 				  struct sk_buff *skb)
60052f20216cSAbhishek Pandit-Subedi {
60062f20216cSAbhishek Pandit-Subedi 	struct hci_ev_le_advertising_info *adv;
60072f20216cSAbhishek Pandit-Subedi 	struct hci_ev_le_direct_adv_info *direct_adv;
60082f20216cSAbhishek Pandit-Subedi 	struct hci_ev_le_ext_adv_report *ext_adv;
60092f20216cSAbhishek Pandit-Subedi 	const struct hci_ev_conn_complete *conn_complete = (void *)skb->data;
60102f20216cSAbhishek Pandit-Subedi 	const struct hci_ev_conn_request *conn_request = (void *)skb->data;
60112f20216cSAbhishek Pandit-Subedi 
60122f20216cSAbhishek Pandit-Subedi 	hci_dev_lock(hdev);
60132f20216cSAbhishek Pandit-Subedi 
60142f20216cSAbhishek Pandit-Subedi 	/* If we are currently suspended and this is the first BT event seen,
60152f20216cSAbhishek Pandit-Subedi 	 * save the wake reason associated with the event.
60162f20216cSAbhishek Pandit-Subedi 	 */
60172f20216cSAbhishek Pandit-Subedi 	if (!hdev->suspended || hdev->wake_reason)
60182f20216cSAbhishek Pandit-Subedi 		goto unlock;
60192f20216cSAbhishek Pandit-Subedi 
60202f20216cSAbhishek Pandit-Subedi 	/* Default to remote wake. Values for wake_reason are documented in the
60212f20216cSAbhishek Pandit-Subedi 	 * Bluez mgmt api docs.
60222f20216cSAbhishek Pandit-Subedi 	 */
60232f20216cSAbhishek Pandit-Subedi 	hdev->wake_reason = MGMT_WAKE_REASON_REMOTE_WAKE;
60242f20216cSAbhishek Pandit-Subedi 
60252f20216cSAbhishek Pandit-Subedi 	/* Once configured for remote wakeup, we should only wake up for
60262f20216cSAbhishek Pandit-Subedi 	 * reconnections. It's useful to see which device is waking us up so
60272f20216cSAbhishek Pandit-Subedi 	 * keep track of the bdaddr of the connection event that woke us up.
60282f20216cSAbhishek Pandit-Subedi 	 */
60292f20216cSAbhishek Pandit-Subedi 	if (event == HCI_EV_CONN_REQUEST) {
60302f20216cSAbhishek Pandit-Subedi 		bacpy(&hdev->wake_addr, &conn_complete->bdaddr);
60312f20216cSAbhishek Pandit-Subedi 		hdev->wake_addr_type = BDADDR_BREDR;
60322f20216cSAbhishek Pandit-Subedi 	} else if (event == HCI_EV_CONN_COMPLETE) {
60332f20216cSAbhishek Pandit-Subedi 		bacpy(&hdev->wake_addr, &conn_request->bdaddr);
60342f20216cSAbhishek Pandit-Subedi 		hdev->wake_addr_type = BDADDR_BREDR;
60352f20216cSAbhishek Pandit-Subedi 	} else if (event == HCI_EV_LE_META) {
60362f20216cSAbhishek Pandit-Subedi 		struct hci_ev_le_meta *le_ev = (void *)skb->data;
60372f20216cSAbhishek Pandit-Subedi 		u8 subevent = le_ev->subevent;
60382f20216cSAbhishek Pandit-Subedi 		u8 *ptr = &skb->data[sizeof(*le_ev)];
60392f20216cSAbhishek Pandit-Subedi 		u8 num_reports = *ptr;
60402f20216cSAbhishek Pandit-Subedi 
60412f20216cSAbhishek Pandit-Subedi 		if ((subevent == HCI_EV_LE_ADVERTISING_REPORT ||
60422f20216cSAbhishek Pandit-Subedi 		     subevent == HCI_EV_LE_DIRECT_ADV_REPORT ||
60432f20216cSAbhishek Pandit-Subedi 		     subevent == HCI_EV_LE_EXT_ADV_REPORT) &&
60442f20216cSAbhishek Pandit-Subedi 		    num_reports) {
60452f20216cSAbhishek Pandit-Subedi 			adv = (void *)(ptr + 1);
60462f20216cSAbhishek Pandit-Subedi 			direct_adv = (void *)(ptr + 1);
60472f20216cSAbhishek Pandit-Subedi 			ext_adv = (void *)(ptr + 1);
60482f20216cSAbhishek Pandit-Subedi 
60492f20216cSAbhishek Pandit-Subedi 			switch (subevent) {
60502f20216cSAbhishek Pandit-Subedi 			case HCI_EV_LE_ADVERTISING_REPORT:
60512f20216cSAbhishek Pandit-Subedi 				bacpy(&hdev->wake_addr, &adv->bdaddr);
60522f20216cSAbhishek Pandit-Subedi 				hdev->wake_addr_type = adv->bdaddr_type;
60532f20216cSAbhishek Pandit-Subedi 				break;
60542f20216cSAbhishek Pandit-Subedi 			case HCI_EV_LE_DIRECT_ADV_REPORT:
60552f20216cSAbhishek Pandit-Subedi 				bacpy(&hdev->wake_addr, &direct_adv->bdaddr);
60562f20216cSAbhishek Pandit-Subedi 				hdev->wake_addr_type = direct_adv->bdaddr_type;
60572f20216cSAbhishek Pandit-Subedi 				break;
60582f20216cSAbhishek Pandit-Subedi 			case HCI_EV_LE_EXT_ADV_REPORT:
60592f20216cSAbhishek Pandit-Subedi 				bacpy(&hdev->wake_addr, &ext_adv->bdaddr);
60602f20216cSAbhishek Pandit-Subedi 				hdev->wake_addr_type = ext_adv->bdaddr_type;
60612f20216cSAbhishek Pandit-Subedi 				break;
60622f20216cSAbhishek Pandit-Subedi 			}
60632f20216cSAbhishek Pandit-Subedi 		}
60642f20216cSAbhishek Pandit-Subedi 	} else {
60652f20216cSAbhishek Pandit-Subedi 		hdev->wake_reason = MGMT_WAKE_REASON_UNEXPECTED;
60662f20216cSAbhishek Pandit-Subedi 	}
60672f20216cSAbhishek Pandit-Subedi 
60682f20216cSAbhishek Pandit-Subedi unlock:
60692f20216cSAbhishek Pandit-Subedi 	hci_dev_unlock(hdev);
60702f20216cSAbhishek Pandit-Subedi }
60712f20216cSAbhishek Pandit-Subedi 
60721da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
60731da177e4SLinus Torvalds {
6074a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
6075e6214487SJohan Hedberg 	hci_req_complete_t req_complete = NULL;
6076e6214487SJohan Hedberg 	hci_req_complete_skb_t req_complete_skb = NULL;
6077e6214487SJohan Hedberg 	struct sk_buff *orig_skb = NULL;
6078757aa0b5SJohan Hedberg 	u8 status = 0, event = hdr->evt, req_evt = 0;
6079e6214487SJohan Hedberg 	u16 opcode = HCI_OP_NOP;
60801da177e4SLinus Torvalds 
608108bb4da9SAlain Michaud 	if (!event) {
608208bb4da9SAlain Michaud 		bt_dev_warn(hdev, "Received unexpected HCI Event 00000000");
608308bb4da9SAlain Michaud 		goto done;
608408bb4da9SAlain Michaud 	}
608508bb4da9SAlain Michaud 
6086242c0ebdSMarcel Holtmann 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->hci.req_event == event) {
6087c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
6088e6214487SJohan Hedberg 		opcode = __le16_to_cpu(cmd_hdr->opcode);
6089e6214487SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, status, &req_complete,
6090e6214487SJohan Hedberg 				     &req_complete_skb);
6091757aa0b5SJohan Hedberg 		req_evt = event;
609202350a72SJohan Hedberg 	}
609302350a72SJohan Hedberg 
6094e6214487SJohan Hedberg 	/* If it looks like we might end up having to call
6095e6214487SJohan Hedberg 	 * req_complete_skb, store a pristine copy of the skb since the
6096e6214487SJohan Hedberg 	 * various handlers may modify the original one through
6097e6214487SJohan Hedberg 	 * skb_pull() calls, etc.
6098e6214487SJohan Hedberg 	 */
6099e6214487SJohan Hedberg 	if (req_complete_skb || event == HCI_EV_CMD_STATUS ||
6100e6214487SJohan Hedberg 	    event == HCI_EV_CMD_COMPLETE)
6101e6214487SJohan Hedberg 		orig_skb = skb_clone(skb, GFP_KERNEL);
6102e6214487SJohan Hedberg 
6103e6214487SJohan Hedberg 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
6104e6214487SJohan Hedberg 
61052f20216cSAbhishek Pandit-Subedi 	/* Store wake reason if we're suspended */
61062f20216cSAbhishek Pandit-Subedi 	hci_store_wake_reason(hdev, event, skb);
61072f20216cSAbhishek Pandit-Subedi 
6108a9de9248SMarcel Holtmann 	switch (event) {
61091da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
61101da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
61111da177e4SLinus Torvalds 		break;
61121da177e4SLinus Torvalds 
61131da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
61141da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
61151da177e4SLinus Torvalds 		break;
61161da177e4SLinus Torvalds 
6117a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
6118a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
611921d9e30eSMarcel Holtmann 		break;
612021d9e30eSMarcel Holtmann 
61211da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
61221da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
61231da177e4SLinus Torvalds 		break;
61241da177e4SLinus Torvalds 
61251da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
61261da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
61271da177e4SLinus Torvalds 		break;
61281da177e4SLinus Torvalds 
61291da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
61301da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
61311da177e4SLinus Torvalds 		break;
61321da177e4SLinus Torvalds 
6133a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
6134a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
6135a9de9248SMarcel Holtmann 		break;
6136a9de9248SMarcel Holtmann 
61371da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
61381da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
61391da177e4SLinus Torvalds 		break;
61401da177e4SLinus Torvalds 
6141a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
6142a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
6143a9de9248SMarcel Holtmann 		break;
6144a9de9248SMarcel Holtmann 
6145a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
6146a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
6147a9de9248SMarcel Holtmann 		break;
6148a9de9248SMarcel Holtmann 
6149a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
6150e6214487SJohan Hedberg 		hci_cmd_complete_evt(hdev, skb, &opcode, &status,
6151e6214487SJohan Hedberg 				     &req_complete, &req_complete_skb);
6152a9de9248SMarcel Holtmann 		break;
6153a9de9248SMarcel Holtmann 
6154a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
6155e6214487SJohan Hedberg 		hci_cmd_status_evt(hdev, skb, &opcode, &status, &req_complete,
6156e6214487SJohan Hedberg 				   &req_complete_skb);
6157a9de9248SMarcel Holtmann 		break;
6158a9de9248SMarcel Holtmann 
615924dfa343SMarcel Holtmann 	case HCI_EV_HARDWARE_ERROR:
616024dfa343SMarcel Holtmann 		hci_hardware_error_evt(hdev, skb);
616124dfa343SMarcel Holtmann 		break;
616224dfa343SMarcel Holtmann 
6163a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
6164a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
6165a9de9248SMarcel Holtmann 		break;
6166a9de9248SMarcel Holtmann 
6167a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
6168a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
6169a9de9248SMarcel Holtmann 		break;
6170a9de9248SMarcel Holtmann 
6171a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
6172a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
61731da177e4SLinus Torvalds 		break;
61741da177e4SLinus Torvalds 
61751da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
61761da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
61771da177e4SLinus Torvalds 		break;
61781da177e4SLinus Torvalds 
61791da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
61801da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
61811da177e4SLinus Torvalds 		break;
61821da177e4SLinus Torvalds 
61831da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
61841da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
61851da177e4SLinus Torvalds 		break;
61861da177e4SLinus Torvalds 
61871da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
61881da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
61891da177e4SLinus Torvalds 		break;
61901da177e4SLinus Torvalds 
6191a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
6192a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
6193a8746417SMarcel Holtmann 		break;
6194a8746417SMarcel Holtmann 
619585a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
619685a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
619785a1e930SMarcel Holtmann 		break;
619885a1e930SMarcel Holtmann 
6199a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
6200a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
6201a9de9248SMarcel Holtmann 		break;
6202a9de9248SMarcel Holtmann 
6203a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
6204a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
6205a9de9248SMarcel Holtmann 		break;
6206a9de9248SMarcel Holtmann 
6207a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
6208a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
6209a9de9248SMarcel Holtmann 		break;
6210a9de9248SMarcel Holtmann 
6211a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
6212a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
62131da177e4SLinus Torvalds 		break;
62141da177e4SLinus Torvalds 
62151c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
62161c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
62171c2e0041SJohan Hedberg 		break;
62181c2e0041SJohan Hedberg 
62190493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
62200493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
62210493684eSMarcel Holtmann 		break;
62220493684eSMarcel Holtmann 
622303b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
622403b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
622503b555e1SJohan Hedberg 		break;
622603b555e1SJohan Hedberg 
6227a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
6228a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
6229a5c29683SJohan Hedberg 		break;
6230a5c29683SJohan Hedberg 
62311143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
62321143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
62331143d458SBrian Gix 		break;
62341143d458SBrian Gix 
623592a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
623692a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
623792a25256SJohan Hedberg 		break;
623892a25256SJohan Hedberg 
623992a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
624092a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
624192a25256SJohan Hedberg 		break;
624292a25256SJohan Hedberg 
62430493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
62440493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
62450493684eSMarcel Holtmann 		break;
62460493684eSMarcel Holtmann 
624741a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
624841a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
624941a96212SMarcel Holtmann 		break;
625041a96212SMarcel Holtmann 
6251fcd89c09SVille Tervo 	case HCI_EV_LE_META:
6252fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
6253fcd89c09SVille Tervo 		break;
6254fcd89c09SVille Tervo 
62552763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
62562763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
62572763eda6SSzymon Janc 		break;
62582763eda6SSzymon Janc 
6259a77a6a14SArron Wang #if IS_ENABLED(CONFIG_BT_HS)
6260a77a6a14SArron Wang 	case HCI_EV_CHANNEL_SELECTED:
6261a77a6a14SArron Wang 		hci_chan_selected_evt(hdev, skb);
6262a77a6a14SArron Wang 		break;
6263a77a6a14SArron Wang 
6264d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
6265d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
6266d5e91192SAndrei Emeltchenko 		break;
6267d5e91192SAndrei Emeltchenko 
626827695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
626927695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
627027695fb4SAndrei Emeltchenko 		break;
627127695fb4SAndrei Emeltchenko 
6272606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
6273606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
6274606e2a10SAndrei Emeltchenko 		break;
6275606e2a10SAndrei Emeltchenko 
62769eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
62779eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
62789eef6b3aSAndrei Emeltchenko 		break;
6279a77a6a14SArron Wang #endif
62809eef6b3aSAndrei Emeltchenko 
628125e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
628225e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
628325e89e99SAndrei Emeltchenko 		break;
628425e89e99SAndrei Emeltchenko 
6285145373cbSMiao-chen Chou 	case HCI_EV_VENDOR:
6286145373cbSMiao-chen Chou 		msft_vendor_evt(hdev, skb);
6287145373cbSMiao-chen Chou 		break;
6288145373cbSMiao-chen Chou 
62891da177e4SLinus Torvalds 	default:
62909f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
62911da177e4SLinus Torvalds 		break;
62921da177e4SLinus Torvalds 	}
62931da177e4SLinus Torvalds 
6294757aa0b5SJohan Hedberg 	if (req_complete) {
6295e6214487SJohan Hedberg 		req_complete(hdev, status, opcode);
6296757aa0b5SJohan Hedberg 	} else if (req_complete_skb) {
6297757aa0b5SJohan Hedberg 		if (!hci_get_cmd_complete(hdev, opcode, req_evt, orig_skb)) {
6298757aa0b5SJohan Hedberg 			kfree_skb(orig_skb);
6299757aa0b5SJohan Hedberg 			orig_skb = NULL;
6300757aa0b5SJohan Hedberg 		}
6301e6214487SJohan Hedberg 		req_complete_skb(hdev, status, opcode, orig_skb);
6302757aa0b5SJohan Hedberg 	}
6303e6214487SJohan Hedberg 
630408bb4da9SAlain Michaud done:
6305e6214487SJohan Hedberg 	kfree_skb(orig_skb);
63061da177e4SLinus Torvalds 	kfree_skb(skb);
63071da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
63081da177e4SLinus Torvalds }
6309