xref: /openbmc/linux/net/bluetooth/hci_event.c (revision cd9151b6)
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"
381da177e4SLinus Torvalds 
39aa5b0345SMarcel Holtmann #define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
40aa5b0345SMarcel Holtmann 		 "\x00\x00\x00\x00\x00\x00\x00\x00"
41aa5b0345SMarcel Holtmann 
421da177e4SLinus Torvalds /* Handle HCI Event packets */
431da177e4SLinus Torvalds 
44a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
451da177e4SLinus Torvalds {
46a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
471da177e4SLinus Torvalds 
489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
491da177e4SLinus Torvalds 
5082f4785cSAndre Guedes 	if (status)
51a9de9248SMarcel Holtmann 		return;
521da177e4SLinus Torvalds 
5389352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
544e857c58SPeter Zijlstra 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
553e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
5689352e7dSAndre Guedes 
5750143a43SJohan Hedberg 	hci_dev_lock(hdev);
58168b8a25SJakub Pawlowski 	/* Set discovery state to stopped if we're not doing LE active
59168b8a25SJakub Pawlowski 	 * scanning.
60168b8a25SJakub Pawlowski 	 */
61168b8a25SJakub Pawlowski 	if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
62168b8a25SJakub Pawlowski 	    hdev->le_scan_type != LE_SCAN_ACTIVE)
6350143a43SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
6450143a43SJohan Hedberg 	hci_dev_unlock(hdev);
6550143a43SJohan Hedberg 
66a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
671da177e4SLinus Torvalds }
686bd57416SMarcel Holtmann 
694d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
704d93483bSAndre Guedes {
714d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
724d93483bSAndre Guedes 
739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
74ae854a70SAndre Guedes 
75ae854a70SAndre Guedes 	if (status)
76ae854a70SAndre Guedes 		return;
77ae854a70SAndre Guedes 
78a1536da2SMarcel Holtmann 	hci_dev_set_flag(hdev, HCI_PERIODIC_INQ);
794d93483bSAndre Guedes }
804d93483bSAndre Guedes 
81a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
821da177e4SLinus Torvalds {
83a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
84a9de9248SMarcel Holtmann 
859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
86a9de9248SMarcel Holtmann 
87a9de9248SMarcel Holtmann 	if (status)
88a9de9248SMarcel Holtmann 		return;
89a9de9248SMarcel Holtmann 
90a358dc11SMarcel Holtmann 	hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ);
91ae854a70SAndre Guedes 
92a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
93a9de9248SMarcel Holtmann }
94a9de9248SMarcel Holtmann 
95807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
96807deac2SGustavo Padovan 					  struct sk_buff *skb)
97a9de9248SMarcel Holtmann {
98a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
99a9de9248SMarcel Holtmann }
100a9de9248SMarcel Holtmann 
101a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
102a9de9248SMarcel Holtmann {
103a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
1041da177e4SLinus Torvalds 	struct hci_conn *conn;
1051da177e4SLinus Torvalds 
1069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1071da177e4SLinus Torvalds 
108a9de9248SMarcel Holtmann 	if (rp->status)
109a9de9248SMarcel Holtmann 		return;
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1121da177e4SLinus Torvalds 
113a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
11440bef302SJohan Hedberg 	if (conn)
11540bef302SJohan Hedberg 		conn->role = rp->role;
1161da177e4SLinus Torvalds 
1171da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
118a9de9248SMarcel Holtmann }
1191da177e4SLinus Torvalds 
120e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
121e4e8e37cSMarcel Holtmann {
122e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
123e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
124e4e8e37cSMarcel Holtmann 
1259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
126e4e8e37cSMarcel Holtmann 
127e4e8e37cSMarcel Holtmann 	if (rp->status)
128e4e8e37cSMarcel Holtmann 		return;
129e4e8e37cSMarcel Holtmann 
130e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
131e4e8e37cSMarcel Holtmann 
132e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
133e4e8e37cSMarcel Holtmann 	if (conn)
134e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
135e4e8e37cSMarcel Holtmann 
136e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
137e4e8e37cSMarcel Holtmann }
138e4e8e37cSMarcel Holtmann 
139a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
140a9de9248SMarcel Holtmann {
141a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
142a9de9248SMarcel Holtmann 	struct hci_conn *conn;
143a9de9248SMarcel Holtmann 	void *sent;
144a9de9248SMarcel Holtmann 
1459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
146a9de9248SMarcel Holtmann 
147a9de9248SMarcel Holtmann 	if (rp->status)
148a9de9248SMarcel Holtmann 		return;
149a9de9248SMarcel Holtmann 
150a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
15104837f64SMarcel Holtmann 	if (!sent)
152a9de9248SMarcel Holtmann 		return;
15304837f64SMarcel Holtmann 
15404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
15504837f64SMarcel Holtmann 
156a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
157e4e8e37cSMarcel Holtmann 	if (conn)
15883985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15904837f64SMarcel Holtmann 
16004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1611da177e4SLinus Torvalds }
1621da177e4SLinus Torvalds 
163807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
164807deac2SGustavo Padovan 					struct sk_buff *skb)
165e4e8e37cSMarcel Holtmann {
166e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
167e4e8e37cSMarcel Holtmann 
1689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
169e4e8e37cSMarcel Holtmann 
170e4e8e37cSMarcel Holtmann 	if (rp->status)
171e4e8e37cSMarcel Holtmann 		return;
172e4e8e37cSMarcel Holtmann 
173e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
174e4e8e37cSMarcel Holtmann }
175e4e8e37cSMarcel Holtmann 
176807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
177807deac2SGustavo Padovan 					 struct sk_buff *skb)
178e4e8e37cSMarcel Holtmann {
179e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
180e4e8e37cSMarcel Holtmann 	void *sent;
181e4e8e37cSMarcel Holtmann 
1829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
183e4e8e37cSMarcel Holtmann 
18445296acdSMarcel Holtmann 	if (status)
18545296acdSMarcel Holtmann 		return;
18645296acdSMarcel Holtmann 
187e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
188e4e8e37cSMarcel Holtmann 	if (!sent)
189e4e8e37cSMarcel Holtmann 		return;
190e4e8e37cSMarcel Holtmann 
191e4e8e37cSMarcel Holtmann 	hdev->link_policy = get_unaligned_le16(sent);
192e4e8e37cSMarcel Holtmann }
193e4e8e37cSMarcel Holtmann 
194a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1951da177e4SLinus Torvalds {
196a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
197a9de9248SMarcel Holtmann 
1989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
199a9de9248SMarcel Holtmann 
20010572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
20110572132SGustavo F. Padovan 
2028761f9d6SMarcel Holtmann 	if (status)
2038761f9d6SMarcel Holtmann 		return;
2048761f9d6SMarcel Holtmann 
205a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
206eacb44dfSMarcel Holtmann 	hci_dev_clear_volatile_flags(hdev);
20769775ff6SAndre Guedes 
20839c5d970SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
20939c5d970SJohan Hedberg 
210bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
211bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
2123f0f524bSJohan Hedberg 
2133f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
2143f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
215f8e808bdSMarcel Holtmann 
216f8e808bdSMarcel Holtmann 	memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data));
217f8e808bdSMarcel Holtmann 	hdev->scan_rsp_data_len = 0;
21806f5b778SMarcel Holtmann 
219533553f8SMarcel Holtmann 	hdev->le_scan_type = LE_SCAN_PASSIVE;
220533553f8SMarcel Holtmann 
22106f5b778SMarcel Holtmann 	hdev->ssp_debug_mode = 0;
222a4d5504dSMarcel Holtmann 
223a4d5504dSMarcel Holtmann 	hci_bdaddr_list_clear(&hdev->le_white_list);
224cfdb0c2dSAnkit Navik 	hci_bdaddr_list_clear(&hdev->le_resolv_list);
225a9de9248SMarcel Holtmann }
226a9de9248SMarcel Holtmann 
227c2f0f979SMarcel Holtmann static void hci_cc_read_stored_link_key(struct hci_dev *hdev,
228c2f0f979SMarcel Holtmann 					struct sk_buff *skb)
229c2f0f979SMarcel Holtmann {
230c2f0f979SMarcel Holtmann 	struct hci_rp_read_stored_link_key *rp = (void *)skb->data;
231c2f0f979SMarcel Holtmann 	struct hci_cp_read_stored_link_key *sent;
232c2f0f979SMarcel Holtmann 
233c2f0f979SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
234c2f0f979SMarcel Holtmann 
235c2f0f979SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY);
236c2f0f979SMarcel Holtmann 	if (!sent)
237c2f0f979SMarcel Holtmann 		return;
238c2f0f979SMarcel Holtmann 
239c2f0f979SMarcel Holtmann 	if (!rp->status && sent->read_all == 0x01) {
240c2f0f979SMarcel Holtmann 		hdev->stored_max_keys = rp->max_keys;
241c2f0f979SMarcel Holtmann 		hdev->stored_num_keys = rp->num_keys;
242c2f0f979SMarcel Holtmann 	}
243c2f0f979SMarcel Holtmann }
244c2f0f979SMarcel Holtmann 
245a9366120SMarcel Holtmann static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
246a9366120SMarcel Holtmann 					  struct sk_buff *skb)
247a9366120SMarcel Holtmann {
248a9366120SMarcel Holtmann 	struct hci_rp_delete_stored_link_key *rp = (void *)skb->data;
249a9366120SMarcel Holtmann 
250a9366120SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
251a9366120SMarcel Holtmann 
252a9366120SMarcel Holtmann 	if (rp->status)
253a9366120SMarcel Holtmann 		return;
254a9366120SMarcel Holtmann 
255a9366120SMarcel Holtmann 	if (rp->num_keys <= hdev->stored_num_keys)
256a9366120SMarcel Holtmann 		hdev->stored_num_keys -= rp->num_keys;
257a9366120SMarcel Holtmann 	else
258a9366120SMarcel Holtmann 		hdev->stored_num_keys = 0;
259a9366120SMarcel Holtmann }
260a9366120SMarcel Holtmann 
261a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
262a9de9248SMarcel Holtmann {
263a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2641da177e4SLinus Torvalds 	void *sent;
2651da177e4SLinus Torvalds 
2669f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2671da177e4SLinus Torvalds 
268a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2691da177e4SLinus Torvalds 	if (!sent)
270a9de9248SMarcel Holtmann 		return;
2711da177e4SLinus Torvalds 
27256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
27356e5cb86SJohan Hedberg 
274d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
275f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
27628cc7bdeSJohan Hedberg 	else if (!status)
27728cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
278f51d5b24SJohan Hedberg 
27956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
280a9de9248SMarcel Holtmann }
281a9de9248SMarcel Holtmann 
282a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
283a9de9248SMarcel Holtmann {
284a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
285a9de9248SMarcel Holtmann 
2869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
287a9de9248SMarcel Holtmann 
288a9de9248SMarcel Holtmann 	if (rp->status)
289a9de9248SMarcel Holtmann 		return;
290a9de9248SMarcel Holtmann 
291d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
292d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hdev, HCI_CONFIG))
2931f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
294a9de9248SMarcel Holtmann }
295a9de9248SMarcel Holtmann 
296a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
297a9de9248SMarcel Holtmann {
298a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
299a9de9248SMarcel Holtmann 	void *sent;
300a9de9248SMarcel Holtmann 
3019f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
302a9de9248SMarcel Holtmann 
303a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
304a9de9248SMarcel Holtmann 	if (!sent)
305a9de9248SMarcel Holtmann 		return;
3061da177e4SLinus Torvalds 
3075c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
3085c1a4c8fSJaganath Kanakkassery 
3091da177e4SLinus Torvalds 	if (!status) {
310a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
311a9de9248SMarcel Holtmann 
3121da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
3131da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
3141da177e4SLinus Torvalds 		else
3151da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
3161da177e4SLinus Torvalds 	}
317a9de9248SMarcel Holtmann 
318d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
31933ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
3205c1a4c8fSJaganath Kanakkassery 
3215c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
322a9de9248SMarcel Holtmann }
3231da177e4SLinus Torvalds 
324a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
325a9de9248SMarcel Holtmann {
326a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
32745296acdSMarcel Holtmann 	__u8 param;
328a9de9248SMarcel Holtmann 	void *sent;
329a9de9248SMarcel Holtmann 
3309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
331a9de9248SMarcel Holtmann 
33245296acdSMarcel Holtmann 	if (status)
33345296acdSMarcel Holtmann 		return;
33445296acdSMarcel Holtmann 
335a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
3361da177e4SLinus Torvalds 	if (!sent)
337a9de9248SMarcel Holtmann 		return;
3381da177e4SLinus Torvalds 
33945296acdSMarcel Holtmann 	param = *((__u8 *) sent);
340a9de9248SMarcel Holtmann 
3411da177e4SLinus Torvalds 	if (param)
3421da177e4SLinus Torvalds 		set_bit(HCI_ENCRYPT, &hdev->flags);
3431da177e4SLinus Torvalds 	else
3441da177e4SLinus Torvalds 		clear_bit(HCI_ENCRYPT, &hdev->flags);
3451da177e4SLinus Torvalds }
3461da177e4SLinus Torvalds 
347a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
348a9de9248SMarcel Holtmann {
34945296acdSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
35045296acdSMarcel Holtmann 	__u8 param;
351a9de9248SMarcel Holtmann 	void *sent;
3521da177e4SLinus Torvalds 
3539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
354a9de9248SMarcel Holtmann 
355a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3561da177e4SLinus Torvalds 	if (!sent)
357a9de9248SMarcel Holtmann 		return;
3581da177e4SLinus Torvalds 
35936f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
360a9de9248SMarcel Holtmann 
36156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
36256e5cb86SJohan Hedberg 
363fa1bd918SMikel Astiz 	if (status) {
3642d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3652d7cee58SJohan Hedberg 		goto done;
3662d7cee58SJohan Hedberg 	}
3672d7cee58SJohan Hedberg 
368bc6d2d04SJohan Hedberg 	if (param & SCAN_INQUIRY)
3691da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
370bc6d2d04SJohan Hedberg 	else
371bc6d2d04SJohan Hedberg 		clear_bit(HCI_ISCAN, &hdev->flags);
3721da177e4SLinus Torvalds 
373031547d8SJohan Hedberg 	if (param & SCAN_PAGE)
3741da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
375bc6d2d04SJohan Hedberg 	else
376204e3990SJohan Hedberg 		clear_bit(HCI_PSCAN, &hdev->flags);
377a9de9248SMarcel Holtmann 
37836f7fc7eSJohan Hedberg done:
37956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
3801da177e4SLinus Torvalds }
3811da177e4SLinus Torvalds 
382a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
383a9de9248SMarcel Holtmann {
384a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
385a9de9248SMarcel Holtmann 
3869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
387a9de9248SMarcel Holtmann 
388a9de9248SMarcel Holtmann 	if (rp->status)
389a9de9248SMarcel Holtmann 		return;
390a9de9248SMarcel Holtmann 
391a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
392a9de9248SMarcel Holtmann 
393a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
394a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
395a9de9248SMarcel Holtmann }
396a9de9248SMarcel Holtmann 
397a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
398a9de9248SMarcel Holtmann {
399a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
400a9de9248SMarcel Holtmann 	void *sent;
401a9de9248SMarcel Holtmann 
4029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
403a9de9248SMarcel Holtmann 
404a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
405a9de9248SMarcel Holtmann 	if (!sent)
406a9de9248SMarcel Holtmann 		return;
407a9de9248SMarcel Holtmann 
4087f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
4097f9a903cSMarcel Holtmann 
4107f9a903cSMarcel Holtmann 	if (status == 0)
411a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
4127f9a903cSMarcel Holtmann 
413d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
4147f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
4157f9a903cSMarcel Holtmann 
4167f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
417a9de9248SMarcel Holtmann }
418a9de9248SMarcel Holtmann 
419a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
420a9de9248SMarcel Holtmann {
421a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
422a9de9248SMarcel Holtmann 	__u16 setting;
423a9de9248SMarcel Holtmann 
4249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
425a9de9248SMarcel Holtmann 
426a9de9248SMarcel Holtmann 	if (rp->status)
427a9de9248SMarcel Holtmann 		return;
428a9de9248SMarcel Holtmann 
429a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
430a9de9248SMarcel Holtmann 
431a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
432a9de9248SMarcel Holtmann 		return;
433a9de9248SMarcel Holtmann 
434a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
435a9de9248SMarcel Holtmann 
4369f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
437a9de9248SMarcel Holtmann 
4383c54711cSGustavo F. Padovan 	if (hdev->notify)
439a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
440a9de9248SMarcel Holtmann }
441a9de9248SMarcel Holtmann 
4428fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
4438fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
444a9de9248SMarcel Holtmann {
445a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
446f383f275SMarcel Holtmann 	__u16 setting;
447a9de9248SMarcel Holtmann 	void *sent;
448a9de9248SMarcel Holtmann 
4499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
450a9de9248SMarcel Holtmann 
451f383f275SMarcel Holtmann 	if (status)
452f383f275SMarcel Holtmann 		return;
453f383f275SMarcel Holtmann 
454a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
455a9de9248SMarcel Holtmann 	if (!sent)
456a9de9248SMarcel Holtmann 		return;
457a9de9248SMarcel Holtmann 
458f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4591da177e4SLinus Torvalds 
460f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
461f383f275SMarcel Holtmann 		return;
462f383f275SMarcel Holtmann 
4631da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4641da177e4SLinus Torvalds 
4659f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4661da177e4SLinus Torvalds 
4673c54711cSGustavo F. Padovan 	if (hdev->notify)
4681da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4691da177e4SLinus Torvalds }
4701da177e4SLinus Torvalds 
471b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev,
472b4cb9fb2SMarcel Holtmann 					  struct sk_buff *skb)
473b4cb9fb2SMarcel Holtmann {
474b4cb9fb2SMarcel Holtmann 	struct hci_rp_read_num_supported_iac *rp = (void *) skb->data;
475b4cb9fb2SMarcel Holtmann 
476b4cb9fb2SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
477b4cb9fb2SMarcel Holtmann 
478b4cb9fb2SMarcel Holtmann 	if (rp->status)
479b4cb9fb2SMarcel Holtmann 		return;
480b4cb9fb2SMarcel Holtmann 
481b4cb9fb2SMarcel Holtmann 	hdev->num_iac = rp->num_iac;
482b4cb9fb2SMarcel Holtmann 
483b4cb9fb2SMarcel Holtmann 	BT_DBG("%s num iac %d", hdev->name, hdev->num_iac);
484b4cb9fb2SMarcel Holtmann }
485b4cb9fb2SMarcel Holtmann 
486333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
487333140b5SMarcel Holtmann {
488333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4895ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
490333140b5SMarcel Holtmann 
4919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
492333140b5SMarcel Holtmann 
493333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
494333140b5SMarcel Holtmann 	if (!sent)
495333140b5SMarcel Holtmann 		return;
496333140b5SMarcel Holtmann 
4975c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
4985c1a4c8fSJaganath Kanakkassery 
4995ed8eb2fSJohan Hedberg 	if (!status) {
5005ed8eb2fSJohan Hedberg 		if (sent->mode)
501cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_SSP;
5025ed8eb2fSJohan Hedberg 		else
503cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_SSP;
5045ed8eb2fSJohan Hedberg 	}
5055ed8eb2fSJohan Hedberg 
506d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
5075ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
508c0ecddc2SJohan Hedberg 	else if (!status) {
5095ed8eb2fSJohan Hedberg 		if (sent->mode)
510a1536da2SMarcel Holtmann 			hci_dev_set_flag(hdev, HCI_SSP_ENABLED);
51184bde9d6SJohan Hedberg 		else
512a358dc11SMarcel Holtmann 			hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
513c0ecddc2SJohan Hedberg 	}
5145c1a4c8fSJaganath Kanakkassery 
5155c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
516333140b5SMarcel Holtmann }
517333140b5SMarcel Holtmann 
518eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
519eac83dc6SMarcel Holtmann {
520eac83dc6SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
521eac83dc6SMarcel Holtmann 	struct hci_cp_write_sc_support *sent;
522eac83dc6SMarcel Holtmann 
523eac83dc6SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
524eac83dc6SMarcel Holtmann 
525eac83dc6SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
526eac83dc6SMarcel Holtmann 	if (!sent)
527eac83dc6SMarcel Holtmann 		return;
528eac83dc6SMarcel Holtmann 
5295c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
5305c1a4c8fSJaganath Kanakkassery 
531eac83dc6SMarcel Holtmann 	if (!status) {
532eac83dc6SMarcel Holtmann 		if (sent->support)
533eac83dc6SMarcel Holtmann 			hdev->features[1][0] |= LMP_HOST_SC;
534eac83dc6SMarcel Holtmann 		else
535eac83dc6SMarcel Holtmann 			hdev->features[1][0] &= ~LMP_HOST_SC;
536eac83dc6SMarcel Holtmann 	}
537eac83dc6SMarcel Holtmann 
538d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT) && !status) {
539eac83dc6SMarcel Holtmann 		if (sent->support)
540a1536da2SMarcel Holtmann 			hci_dev_set_flag(hdev, HCI_SC_ENABLED);
541eac83dc6SMarcel Holtmann 		else
542a358dc11SMarcel Holtmann 			hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
543eac83dc6SMarcel Holtmann 	}
5445c1a4c8fSJaganath Kanakkassery 
5455c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
546eac83dc6SMarcel Holtmann }
547eac83dc6SMarcel Holtmann 
548a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
549a9de9248SMarcel Holtmann {
550a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5511143e5a6SMarcel Holtmann 
5529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5531143e5a6SMarcel Holtmann 
554a9de9248SMarcel Holtmann 	if (rp->status)
55542c6b129SJohan Hedberg 		return;
5561143e5a6SMarcel Holtmann 
557d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
558d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hdev, HCI_CONFIG)) {
559a9de9248SMarcel Holtmann 		hdev->hci_ver = rp->hci_ver;
560e4e8e37cSMarcel Holtmann 		hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
561d5859e22SJohan Hedberg 		hdev->lmp_ver = rp->lmp_ver;
562e4e8e37cSMarcel Holtmann 		hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
563d5859e22SJohan Hedberg 		hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5640d5551f5SMarcel Holtmann 	}
565d5859e22SJohan Hedberg }
566d5859e22SJohan Hedberg 
5678fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
5688fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
569a9de9248SMarcel Holtmann {
570a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
571a9de9248SMarcel Holtmann 
5729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
573a9de9248SMarcel Holtmann 
5746a070e6eSMarcel Holtmann 	if (rp->status)
5756a070e6eSMarcel Holtmann 		return;
5766a070e6eSMarcel Holtmann 
577d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
578d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hdev, HCI_CONFIG))
579a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
580a9de9248SMarcel Holtmann }
581a9de9248SMarcel Holtmann 
5828fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
5838fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
584a9de9248SMarcel Holtmann {
585a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
586a9de9248SMarcel Holtmann 
5879f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
588a9de9248SMarcel Holtmann 
589a9de9248SMarcel Holtmann 	if (rp->status)
590a9de9248SMarcel Holtmann 		return;
591a9de9248SMarcel Holtmann 
592a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
5931da177e4SLinus Torvalds 
5941da177e4SLinus Torvalds 	/* Adjust default settings according to features
5951da177e4SLinus Torvalds 	 * supported by device. */
596a9de9248SMarcel Holtmann 
597cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_3SLOT)
5981da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
5991da177e4SLinus Torvalds 
600cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_5SLOT)
6011da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6021da177e4SLinus Torvalds 
603cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV2) {
6041da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6055b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6065b7f9909SMarcel Holtmann 	}
6071da177e4SLinus Torvalds 
608cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV3) {
6091da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6105b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6115b7f9909SMarcel Holtmann 	}
6125b7f9909SMarcel Holtmann 
61345db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
6145b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6155b7f9909SMarcel Holtmann 
616cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV4)
6175b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6185b7f9909SMarcel Holtmann 
619cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV5)
6205b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6211da177e4SLinus Torvalds 
622cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
623efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
624efc7688bSMarcel Holtmann 
625cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
626efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
627efc7688bSMarcel Holtmann 
628cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
629efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
6301da177e4SLinus Torvalds }
6311da177e4SLinus Torvalds 
632971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
633971e3a4bSAndre Guedes 					   struct sk_buff *skb)
634971e3a4bSAndre Guedes {
635971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
636971e3a4bSAndre Guedes 
6379f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
638971e3a4bSAndre Guedes 
639971e3a4bSAndre Guedes 	if (rp->status)
64042c6b129SJohan Hedberg 		return;
641971e3a4bSAndre Guedes 
64257af75a8SMarcel Holtmann 	if (hdev->max_page < rp->max_page)
643d2c5d77fSJohan Hedberg 		hdev->max_page = rp->max_page;
644d2c5d77fSJohan Hedberg 
645cad718edSJohan Hedberg 	if (rp->page < HCI_MAX_PAGES)
646cad718edSJohan Hedberg 		memcpy(hdev->features[rp->page], rp->features, 8);
647971e3a4bSAndre Guedes }
648971e3a4bSAndre Guedes 
6491e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
6501e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
6511e89cffbSAndrei Emeltchenko {
6521e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
6531e89cffbSAndrei Emeltchenko 
6549f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
6551e89cffbSAndrei Emeltchenko 
65645296acdSMarcel Holtmann 	if (rp->status)
65745296acdSMarcel Holtmann 		return;
65845296acdSMarcel Holtmann 
6591e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
6601e89cffbSAndrei Emeltchenko }
6611e89cffbSAndrei Emeltchenko 
662a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
663a9de9248SMarcel Holtmann {
664a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
665a9de9248SMarcel Holtmann 
6669f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
667a9de9248SMarcel Holtmann 
668a9de9248SMarcel Holtmann 	if (rp->status)
669a9de9248SMarcel Holtmann 		return;
670a9de9248SMarcel Holtmann 
671a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
672a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
673a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
674a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
675da1f5198SMarcel Holtmann 
676da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
677da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
678da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
679da1f5198SMarcel Holtmann 	}
680da1f5198SMarcel Holtmann 
681da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
682da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
6831da177e4SLinus Torvalds 
684807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
685807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
6861da177e4SLinus Torvalds }
6871da177e4SLinus Torvalds 
688a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
689a9de9248SMarcel Holtmann {
690a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6911da177e4SLinus Torvalds 
6929f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
693a9de9248SMarcel Holtmann 
694e30d3f5fSMarcel Holtmann 	if (rp->status)
695e30d3f5fSMarcel Holtmann 		return;
696e30d3f5fSMarcel Holtmann 
697e30d3f5fSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
698a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
699e30d3f5fSMarcel Holtmann 
700d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP))
701e30d3f5fSMarcel Holtmann 		bacpy(&hdev->setup_addr, &rp->bdaddr);
70223bb5763SJohan Hedberg }
70323bb5763SJohan Hedberg 
704f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
705f332ec66SJohan Hedberg 					   struct sk_buff *skb)
706f332ec66SJohan Hedberg {
707f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
708f332ec66SJohan Hedberg 
709f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
710f332ec66SJohan Hedberg 
71145296acdSMarcel Holtmann 	if (rp->status)
71245296acdSMarcel Holtmann 		return;
71345296acdSMarcel Holtmann 
71445296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags)) {
715f332ec66SJohan Hedberg 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
716f332ec66SJohan Hedberg 		hdev->page_scan_window = __le16_to_cpu(rp->window);
717f332ec66SJohan Hedberg 	}
718f332ec66SJohan Hedberg }
719f332ec66SJohan Hedberg 
7204a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
7214a3ee763SJohan Hedberg 					    struct sk_buff *skb)
7224a3ee763SJohan Hedberg {
7234a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
7244a3ee763SJohan Hedberg 	struct hci_cp_write_page_scan_activity *sent;
7254a3ee763SJohan Hedberg 
7264a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
7274a3ee763SJohan Hedberg 
7284a3ee763SJohan Hedberg 	if (status)
7294a3ee763SJohan Hedberg 		return;
7304a3ee763SJohan Hedberg 
7314a3ee763SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
7324a3ee763SJohan Hedberg 	if (!sent)
7334a3ee763SJohan Hedberg 		return;
7344a3ee763SJohan Hedberg 
7354a3ee763SJohan Hedberg 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
7364a3ee763SJohan Hedberg 	hdev->page_scan_window = __le16_to_cpu(sent->window);
7374a3ee763SJohan Hedberg }
7384a3ee763SJohan Hedberg 
739f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
740f332ec66SJohan Hedberg 					   struct sk_buff *skb)
741f332ec66SJohan Hedberg {
742f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
743f332ec66SJohan Hedberg 
744f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
745f332ec66SJohan Hedberg 
74645296acdSMarcel Holtmann 	if (rp->status)
74745296acdSMarcel Holtmann 		return;
74845296acdSMarcel Holtmann 
74945296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
750f332ec66SJohan Hedberg 		hdev->page_scan_type = rp->type;
751f332ec66SJohan Hedberg }
752f332ec66SJohan Hedberg 
7534a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
7544a3ee763SJohan Hedberg 					struct sk_buff *skb)
7554a3ee763SJohan Hedberg {
7564a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
7574a3ee763SJohan Hedberg 	u8 *type;
7584a3ee763SJohan Hedberg 
7594a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
7604a3ee763SJohan Hedberg 
7614a3ee763SJohan Hedberg 	if (status)
7624a3ee763SJohan Hedberg 		return;
7634a3ee763SJohan Hedberg 
7644a3ee763SJohan Hedberg 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
7654a3ee763SJohan Hedberg 	if (type)
7664a3ee763SJohan Hedberg 		hdev->page_scan_type = *type;
7674a3ee763SJohan Hedberg }
7684a3ee763SJohan Hedberg 
769350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
770350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
771350ee4cfSAndrei Emeltchenko {
772350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
773350ee4cfSAndrei Emeltchenko 
7749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
775350ee4cfSAndrei Emeltchenko 
776350ee4cfSAndrei Emeltchenko 	if (rp->status)
777350ee4cfSAndrei Emeltchenko 		return;
778350ee4cfSAndrei Emeltchenko 
779350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
780350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
781350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
782350ee4cfSAndrei Emeltchenko 
783350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
784350ee4cfSAndrei Emeltchenko 
785350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
786350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
787350ee4cfSAndrei Emeltchenko }
788350ee4cfSAndrei Emeltchenko 
78933f35721SJohan Hedberg static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb)
79033f35721SJohan Hedberg {
79133f35721SJohan Hedberg 	struct hci_rp_read_clock *rp = (void *) skb->data;
79233f35721SJohan Hedberg 	struct hci_cp_read_clock *cp;
79333f35721SJohan Hedberg 	struct hci_conn *conn;
79433f35721SJohan Hedberg 
79533f35721SJohan Hedberg 	BT_DBG("%s", hdev->name);
79633f35721SJohan Hedberg 
79733f35721SJohan Hedberg 	if (skb->len < sizeof(*rp))
79833f35721SJohan Hedberg 		return;
79933f35721SJohan Hedberg 
80033f35721SJohan Hedberg 	if (rp->status)
80133f35721SJohan Hedberg 		return;
80233f35721SJohan Hedberg 
80333f35721SJohan Hedberg 	hci_dev_lock(hdev);
80433f35721SJohan Hedberg 
80533f35721SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
80633f35721SJohan Hedberg 	if (!cp)
80733f35721SJohan Hedberg 		goto unlock;
80833f35721SJohan Hedberg 
80933f35721SJohan Hedberg 	if (cp->which == 0x00) {
81033f35721SJohan Hedberg 		hdev->clock = le32_to_cpu(rp->clock);
81133f35721SJohan Hedberg 		goto unlock;
81233f35721SJohan Hedberg 	}
81333f35721SJohan Hedberg 
81433f35721SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
81533f35721SJohan Hedberg 	if (conn) {
81633f35721SJohan Hedberg 		conn->clock = le32_to_cpu(rp->clock);
81733f35721SJohan Hedberg 		conn->clock_accuracy = le16_to_cpu(rp->accuracy);
81833f35721SJohan Hedberg 	}
81933f35721SJohan Hedberg 
82033f35721SJohan Hedberg unlock:
82133f35721SJohan Hedberg 	hci_dev_unlock(hdev);
82233f35721SJohan Hedberg }
82333f35721SJohan Hedberg 
824928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
825928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
826928abaa7SAndrei Emeltchenko {
827928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
828928abaa7SAndrei Emeltchenko 
8299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
830928abaa7SAndrei Emeltchenko 
831928abaa7SAndrei Emeltchenko 	if (rp->status)
83283927882SArron Wang 		return;
833928abaa7SAndrei Emeltchenko 
834928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
835928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
836928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
837928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
838928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
839928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
840928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
841928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
842928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
843928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
844928abaa7SAndrei Emeltchenko }
845928abaa7SAndrei Emeltchenko 
846d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
847d5859e22SJohan Hedberg 					 struct sk_buff *skb)
848d5859e22SJohan Hedberg {
84991c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
850d5859e22SJohan Hedberg 
8519f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
852d5859e22SJohan Hedberg 
85345296acdSMarcel Holtmann 	if (rp->status)
85445296acdSMarcel Holtmann 		return;
85545296acdSMarcel Holtmann 
85691c4e9b1SMarcel Holtmann 	hdev->inq_tx_power = rp->tx_power;
857d5859e22SJohan Hedberg }
858d5859e22SJohan Hedberg 
859980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
860980e1a53SJohan Hedberg {
861980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
862980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
863980e1a53SJohan Hedberg 	struct hci_conn *conn;
864980e1a53SJohan Hedberg 
8659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
866980e1a53SJohan Hedberg 
86756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
86856e5cb86SJohan Hedberg 
869d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
870744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
871980e1a53SJohan Hedberg 
872fa1bd918SMikel Astiz 	if (rp->status)
87356e5cb86SJohan Hedberg 		goto unlock;
874980e1a53SJohan Hedberg 
875980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
876980e1a53SJohan Hedberg 	if (!cp)
87756e5cb86SJohan Hedberg 		goto unlock;
878980e1a53SJohan Hedberg 
879980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
880980e1a53SJohan Hedberg 	if (conn)
881980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
88256e5cb86SJohan Hedberg 
88356e5cb86SJohan Hedberg unlock:
88456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
885980e1a53SJohan Hedberg }
886980e1a53SJohan Hedberg 
887980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
888980e1a53SJohan Hedberg {
889980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
890980e1a53SJohan Hedberg 
8919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
892980e1a53SJohan Hedberg 
89356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
89456e5cb86SJohan Hedberg 
895d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
896744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
897980e1a53SJohan Hedberg 						 rp->status);
89856e5cb86SJohan Hedberg 
89956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
900980e1a53SJohan Hedberg }
90156e5cb86SJohan Hedberg 
9026ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9036ed58ec5SVille Tervo 				       struct sk_buff *skb)
9046ed58ec5SVille Tervo {
9056ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9066ed58ec5SVille Tervo 
9079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9086ed58ec5SVille Tervo 
9096ed58ec5SVille Tervo 	if (rp->status)
9106ed58ec5SVille Tervo 		return;
9116ed58ec5SVille Tervo 
9126ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9136ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9146ed58ec5SVille Tervo 
9156ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9166ed58ec5SVille Tervo 
9176ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9186ed58ec5SVille Tervo }
919980e1a53SJohan Hedberg 
92060e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
92160e77321SJohan Hedberg 					  struct sk_buff *skb)
92260e77321SJohan Hedberg {
92360e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
92460e77321SJohan Hedberg 
92560e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
92660e77321SJohan Hedberg 
92745296acdSMarcel Holtmann 	if (rp->status)
92845296acdSMarcel Holtmann 		return;
92945296acdSMarcel Holtmann 
93060e77321SJohan Hedberg 	memcpy(hdev->le_features, rp->features, 8);
93160e77321SJohan Hedberg }
93260e77321SJohan Hedberg 
9338fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
9348fa19098SJohan Hedberg 					struct sk_buff *skb)
9358fa19098SJohan Hedberg {
9368fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
9378fa19098SJohan Hedberg 
9388fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9398fa19098SJohan Hedberg 
94045296acdSMarcel Holtmann 	if (rp->status)
94145296acdSMarcel Holtmann 		return;
94245296acdSMarcel Holtmann 
9438fa19098SJohan Hedberg 	hdev->adv_tx_power = rp->tx_power;
9448fa19098SJohan Hedberg }
9458fa19098SJohan Hedberg 
946a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
947a5c29683SJohan Hedberg {
948a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
949a5c29683SJohan Hedberg 
9509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
951a5c29683SJohan Hedberg 
95256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
95356e5cb86SJohan Hedberg 
954d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
95504124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
95604124681SGustavo F. Padovan 						 rp->status);
95756e5cb86SJohan Hedberg 
95856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
959a5c29683SJohan Hedberg }
960a5c29683SJohan Hedberg 
961a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
962a5c29683SJohan Hedberg 					  struct sk_buff *skb)
963a5c29683SJohan Hedberg {
964a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
965a5c29683SJohan Hedberg 
9669f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
967a5c29683SJohan Hedberg 
96856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
96956e5cb86SJohan Hedberg 
970d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
971744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
97204124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
97356e5cb86SJohan Hedberg 
97456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
975a5c29683SJohan Hedberg }
976a5c29683SJohan Hedberg 
9771143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9781143d458SBrian Gix {
9791143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9801143d458SBrian Gix 
9819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9821143d458SBrian Gix 
9831143d458SBrian Gix 	hci_dev_lock(hdev);
9841143d458SBrian Gix 
985d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
986272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
987272d90dfSJohan Hedberg 						 0, rp->status);
9881143d458SBrian Gix 
9891143d458SBrian Gix 	hci_dev_unlock(hdev);
9901143d458SBrian Gix }
9911143d458SBrian Gix 
9921143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9931143d458SBrian Gix 					  struct sk_buff *skb)
9941143d458SBrian Gix {
9951143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9961143d458SBrian Gix 
9979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9981143d458SBrian Gix 
9991143d458SBrian Gix 	hci_dev_lock(hdev);
10001143d458SBrian Gix 
1001d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
10021143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
100304124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
10041143d458SBrian Gix 
10051143d458SBrian Gix 	hci_dev_unlock(hdev);
10061143d458SBrian Gix }
10071143d458SBrian Gix 
10084d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
1009c35938b2SSzymon Janc 				       struct sk_buff *skb)
1010c35938b2SSzymon Janc {
1011c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1012c35938b2SSzymon Janc 
10139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10144d2d2796SMarcel Holtmann }
10154d2d2796SMarcel Holtmann 
10164d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
10174d2d2796SMarcel Holtmann 					   struct sk_buff *skb)
10184d2d2796SMarcel Holtmann {
10194d2d2796SMarcel Holtmann 	struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
10204d2d2796SMarcel Holtmann 
10214d2d2796SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1022c35938b2SSzymon Janc }
1023c35938b2SSzymon Janc 
10247a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
10257a4cd51dSMarcel Holtmann {
10267a4cd51dSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
10277a4cd51dSMarcel Holtmann 	bdaddr_t *sent;
10287a4cd51dSMarcel Holtmann 
10297a4cd51dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10307a4cd51dSMarcel Holtmann 
103145296acdSMarcel Holtmann 	if (status)
103245296acdSMarcel Holtmann 		return;
103345296acdSMarcel Holtmann 
10347a4cd51dSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
10357a4cd51dSMarcel Holtmann 	if (!sent)
10367a4cd51dSMarcel Holtmann 		return;
10377a4cd51dSMarcel Holtmann 
10387a4cd51dSMarcel Holtmann 	hci_dev_lock(hdev);
10397a4cd51dSMarcel Holtmann 
10407a4cd51dSMarcel Holtmann 	bacpy(&hdev->random_addr, sent);
10417a4cd51dSMarcel Holtmann 
10427a4cd51dSMarcel Holtmann 	hci_dev_unlock(hdev);
10437a4cd51dSMarcel Holtmann }
10447a4cd51dSMarcel Holtmann 
10450314f286SJaganath Kanakkassery static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
10460314f286SJaganath Kanakkassery {
10470314f286SJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
10480314f286SJaganath Kanakkassery 	struct hci_cp_le_set_default_phy *cp;
10490314f286SJaganath Kanakkassery 
10500314f286SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10510314f286SJaganath Kanakkassery 
10520314f286SJaganath Kanakkassery 	if (status)
10530314f286SJaganath Kanakkassery 		return;
10540314f286SJaganath Kanakkassery 
10550314f286SJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY);
10560314f286SJaganath Kanakkassery 	if (!cp)
10570314f286SJaganath Kanakkassery 		return;
10580314f286SJaganath Kanakkassery 
10590314f286SJaganath Kanakkassery 	hci_dev_lock(hdev);
10600314f286SJaganath Kanakkassery 
10610314f286SJaganath Kanakkassery 	hdev->le_tx_def_phys = cp->tx_phys;
10620314f286SJaganath Kanakkassery 	hdev->le_rx_def_phys = cp->rx_phys;
10630314f286SJaganath Kanakkassery 
10640314f286SJaganath Kanakkassery 	hci_dev_unlock(hdev);
10650314f286SJaganath Kanakkassery }
10660314f286SJaganath Kanakkassery 
1067a73c046aSJaganath Kanakkassery static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
1068a73c046aSJaganath Kanakkassery                                               struct sk_buff *skb)
1069a73c046aSJaganath Kanakkassery {
1070a73c046aSJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
1071a73c046aSJaganath Kanakkassery 	struct hci_cp_le_set_adv_set_rand_addr *cp;
1072a73c046aSJaganath Kanakkassery 	struct adv_info *adv_instance;
1073a73c046aSJaganath Kanakkassery 
1074a73c046aSJaganath Kanakkassery 	if (status)
1075a73c046aSJaganath Kanakkassery 		return;
1076a73c046aSJaganath Kanakkassery 
1077a73c046aSJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR);
1078a73c046aSJaganath Kanakkassery 	if (!cp)
1079a73c046aSJaganath Kanakkassery 		return;
1080a73c046aSJaganath Kanakkassery 
1081a73c046aSJaganath Kanakkassery 	hci_dev_lock(hdev);
1082a73c046aSJaganath Kanakkassery 
1083a73c046aSJaganath Kanakkassery 	if (!hdev->cur_adv_instance) {
1084a73c046aSJaganath Kanakkassery 		/* Store in hdev for instance 0 (Set adv and Directed advs) */
1085a73c046aSJaganath Kanakkassery 		bacpy(&hdev->random_addr, &cp->bdaddr);
1086a73c046aSJaganath Kanakkassery 	} else {
1087a73c046aSJaganath Kanakkassery 		adv_instance = hci_find_adv_instance(hdev,
1088a73c046aSJaganath Kanakkassery 						     hdev->cur_adv_instance);
1089a73c046aSJaganath Kanakkassery 		if (adv_instance)
1090a73c046aSJaganath Kanakkassery 			bacpy(&adv_instance->random_addr, &cp->bdaddr);
1091a73c046aSJaganath Kanakkassery 	}
1092a73c046aSJaganath Kanakkassery 
1093a73c046aSJaganath Kanakkassery 	hci_dev_unlock(hdev);
1094a73c046aSJaganath Kanakkassery }
1095a73c046aSJaganath Kanakkassery 
1096c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1097c1d5dc4aSJohan Hedberg {
1098c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
1099c1d5dc4aSJohan Hedberg 
1100c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1101c1d5dc4aSJohan Hedberg 
110245296acdSMarcel Holtmann 	if (status)
1103c1d5dc4aSJohan Hedberg 		return;
1104c1d5dc4aSJohan Hedberg 
110545296acdSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
110645296acdSMarcel Holtmann 	if (!sent)
11073c857757SJohan Hedberg 		return;
11083c857757SJohan Hedberg 
1109c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
1110c1d5dc4aSJohan Hedberg 
111149c922bbSStephen Hemminger 	/* If we're doing connection initiation as peripheral. Set a
11123c857757SJohan Hedberg 	 * timeout in case something goes wrong.
11133c857757SJohan Hedberg 	 */
11143c857757SJohan Hedberg 	if (*sent) {
11153c857757SJohan Hedberg 		struct hci_conn *conn;
11163c857757SJohan Hedberg 
1117a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_LE_ADV);
111866c417c1SJohan Hedberg 
1119e7d9ab73SJakub Pawlowski 		conn = hci_lookup_le_connect(hdev);
11203c857757SJohan Hedberg 		if (conn)
11213c857757SJohan Hedberg 			queue_delayed_work(hdev->workqueue,
11223c857757SJohan Hedberg 					   &conn->le_conn_timeout,
112309ae260bSJohan Hedberg 					   conn->conn_timeout);
112466c417c1SJohan Hedberg 	} else {
1125a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_LE_ADV);
11263c857757SJohan Hedberg 	}
11273c857757SJohan Hedberg 
112804b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
1129c1d5dc4aSJohan Hedberg }
1130c1d5dc4aSJohan Hedberg 
1131de181e88SJaganath Kanakkassery static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
1132de181e88SJaganath Kanakkassery 					 struct sk_buff *skb)
1133de181e88SJaganath Kanakkassery {
1134de181e88SJaganath Kanakkassery 	struct hci_cp_le_set_ext_adv_enable *cp;
1135de181e88SJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
1136de181e88SJaganath Kanakkassery 
1137de181e88SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1138de181e88SJaganath Kanakkassery 
1139de181e88SJaganath Kanakkassery 	if (status)
1140de181e88SJaganath Kanakkassery 		return;
1141de181e88SJaganath Kanakkassery 
1142de181e88SJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE);
1143de181e88SJaganath Kanakkassery 	if (!cp)
1144de181e88SJaganath Kanakkassery 		return;
1145de181e88SJaganath Kanakkassery 
1146de181e88SJaganath Kanakkassery 	hci_dev_lock(hdev);
1147de181e88SJaganath Kanakkassery 
1148de181e88SJaganath Kanakkassery 	if (cp->enable) {
1149de181e88SJaganath Kanakkassery 		struct hci_conn *conn;
1150de181e88SJaganath Kanakkassery 
1151de181e88SJaganath Kanakkassery 		hci_dev_set_flag(hdev, HCI_LE_ADV);
1152de181e88SJaganath Kanakkassery 
1153de181e88SJaganath Kanakkassery 		conn = hci_lookup_le_connect(hdev);
1154de181e88SJaganath Kanakkassery 		if (conn)
1155de181e88SJaganath Kanakkassery 			queue_delayed_work(hdev->workqueue,
1156de181e88SJaganath Kanakkassery 					   &conn->le_conn_timeout,
1157de181e88SJaganath Kanakkassery 					   conn->conn_timeout);
115845b7749fSJaganath Kanakkassery 	} else {
115945b7749fSJaganath Kanakkassery 		hci_dev_clear_flag(hdev, HCI_LE_ADV);
1160de181e88SJaganath Kanakkassery 	}
1161de181e88SJaganath Kanakkassery 
1162de181e88SJaganath Kanakkassery 	hci_dev_unlock(hdev);
1163de181e88SJaganath Kanakkassery }
1164de181e88SJaganath Kanakkassery 
1165533553f8SMarcel Holtmann static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1166533553f8SMarcel Holtmann {
1167533553f8SMarcel Holtmann 	struct hci_cp_le_set_scan_param *cp;
1168533553f8SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1169533553f8SMarcel Holtmann 
1170533553f8SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1171533553f8SMarcel Holtmann 
117245296acdSMarcel Holtmann 	if (status)
117345296acdSMarcel Holtmann 		return;
117445296acdSMarcel Holtmann 
1175533553f8SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM);
1176533553f8SMarcel Holtmann 	if (!cp)
1177533553f8SMarcel Holtmann 		return;
1178533553f8SMarcel Holtmann 
1179533553f8SMarcel Holtmann 	hci_dev_lock(hdev);
1180533553f8SMarcel Holtmann 
1181533553f8SMarcel Holtmann 	hdev->le_scan_type = cp->type;
1182533553f8SMarcel Holtmann 
1183533553f8SMarcel Holtmann 	hci_dev_unlock(hdev);
1184533553f8SMarcel Holtmann }
1185533553f8SMarcel Holtmann 
1186a2344b9eSJaganath Kanakkassery static void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev,
1187a2344b9eSJaganath Kanakkassery 					 struct sk_buff *skb)
1188a2344b9eSJaganath Kanakkassery {
1189a2344b9eSJaganath Kanakkassery 	struct hci_cp_le_set_ext_scan_params *cp;
1190a2344b9eSJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
1191a2344b9eSJaganath Kanakkassery 	struct hci_cp_le_scan_phy_params *phy_param;
1192a2344b9eSJaganath Kanakkassery 
1193a2344b9eSJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1194a2344b9eSJaganath Kanakkassery 
1195a2344b9eSJaganath Kanakkassery 	if (status)
1196a2344b9eSJaganath Kanakkassery 		return;
1197a2344b9eSJaganath Kanakkassery 
1198a2344b9eSJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS);
1199a2344b9eSJaganath Kanakkassery 	if (!cp)
1200a2344b9eSJaganath Kanakkassery 		return;
1201a2344b9eSJaganath Kanakkassery 
1202a2344b9eSJaganath Kanakkassery 	phy_param = (void *)cp->data;
1203a2344b9eSJaganath Kanakkassery 
1204a2344b9eSJaganath Kanakkassery 	hci_dev_lock(hdev);
1205a2344b9eSJaganath Kanakkassery 
1206a2344b9eSJaganath Kanakkassery 	hdev->le_scan_type = phy_param->type;
1207a2344b9eSJaganath Kanakkassery 
1208a2344b9eSJaganath Kanakkassery 	hci_dev_unlock(hdev);
1209a2344b9eSJaganath Kanakkassery }
1210a2344b9eSJaganath Kanakkassery 
1211b9a6328fSJohan Hedberg static bool has_pending_adv_report(struct hci_dev *hdev)
1212b9a6328fSJohan Hedberg {
1213b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1214b9a6328fSJohan Hedberg 
1215b9a6328fSJohan Hedberg 	return bacmp(&d->last_adv_addr, BDADDR_ANY);
1216b9a6328fSJohan Hedberg }
1217b9a6328fSJohan Hedberg 
1218b9a6328fSJohan Hedberg static void clear_pending_adv_report(struct hci_dev *hdev)
1219b9a6328fSJohan Hedberg {
1220b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1221b9a6328fSJohan Hedberg 
1222b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, BDADDR_ANY);
1223b9a6328fSJohan Hedberg 	d->last_adv_data_len = 0;
1224b9a6328fSJohan Hedberg }
1225b9a6328fSJohan Hedberg 
1226b9a6328fSJohan Hedberg static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
1227c70a7e4cSMarcel Holtmann 				     u8 bdaddr_type, s8 rssi, u32 flags,
1228c70a7e4cSMarcel Holtmann 				     u8 *data, u8 len)
1229b9a6328fSJohan Hedberg {
1230b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1231b9a6328fSJohan Hedberg 
1232b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, bdaddr);
1233b9a6328fSJohan Hedberg 	d->last_adv_addr_type = bdaddr_type;
1234ff5cd29fSJohan Hedberg 	d->last_adv_rssi = rssi;
1235c70a7e4cSMarcel Holtmann 	d->last_adv_flags = flags;
1236b9a6328fSJohan Hedberg 	memcpy(d->last_adv_data, data, len);
1237b9a6328fSJohan Hedberg 	d->last_adv_data_len = len;
1238b9a6328fSJohan Hedberg }
1239b9a6328fSJohan Hedberg 
12403baef810SJaganath Kanakkassery static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable)
1241eb9d91f5SAndre Guedes {
12425c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
12435c1a4c8fSJaganath Kanakkassery 
12443baef810SJaganath Kanakkassery 	switch (enable) {
12453fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
1246a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_LE_SCAN);
1247b9a6328fSJohan Hedberg 		if (hdev->le_scan_type == LE_SCAN_ACTIVE)
1248b9a6328fSJohan Hedberg 			clear_pending_adv_report(hdev);
124968a8aea4SAndrei Emeltchenko 		break;
125068a8aea4SAndrei Emeltchenko 
125176a388beSAndre Guedes 	case LE_SCAN_DISABLE:
1252b9a6328fSJohan Hedberg 		/* We do this here instead of when setting DISCOVERY_STOPPED
1253b9a6328fSJohan Hedberg 		 * since the latter would potentially require waiting for
1254b9a6328fSJohan Hedberg 		 * inquiry to stop too.
1255b9a6328fSJohan Hedberg 		 */
1256b9a6328fSJohan Hedberg 		if (has_pending_adv_report(hdev)) {
1257b9a6328fSJohan Hedberg 			struct discovery_state *d = &hdev->discovery;
1258b9a6328fSJohan Hedberg 
1259b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
1260ab0aa433SJohan Hedberg 					  d->last_adv_addr_type, NULL,
1261c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
1262ab0aa433SJohan Hedberg 					  d->last_adv_data,
1263b9a6328fSJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
1264b9a6328fSJohan Hedberg 		}
1265b9a6328fSJohan Hedberg 
1266317ac8cbSJohan Hedberg 		/* Cancel this timer so that we don't try to disable scanning
1267317ac8cbSJohan Hedberg 		 * when it's already disabled.
1268317ac8cbSJohan Hedberg 		 */
1269317ac8cbSJohan Hedberg 		cancel_delayed_work(&hdev->le_scan_disable);
1270317ac8cbSJohan Hedberg 
1271a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_LE_SCAN);
1272e8bb6b97SJohan Hedberg 
127381ad6fd9SJohan Hedberg 		/* The HCI_LE_SCAN_INTERRUPTED flag indicates that we
127481ad6fd9SJohan Hedberg 		 * interrupted scanning due to a connect request. Mark
1275e8bb6b97SJohan Hedberg 		 * therefore discovery as stopped. If this was not
1276e8bb6b97SJohan Hedberg 		 * because of a connect request advertising might have
1277e8bb6b97SJohan Hedberg 		 * been disabled because of active scanning, so
1278e8bb6b97SJohan Hedberg 		 * re-enable it again if necessary.
127981ad6fd9SJohan Hedberg 		 */
1280a69d8927SMarcel Holtmann 		if (hci_dev_test_and_clear_flag(hdev, HCI_LE_SCAN_INTERRUPTED))
128181ad6fd9SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1282d7a5a11dSMarcel Holtmann 		else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) &&
128334722277SJohan Hedberg 			 hdev->discovery.state == DISCOVERY_FINDING)
1284f2252570SJohan Hedberg 			hci_req_reenable_advertising(hdev);
1285e8bb6b97SJohan Hedberg 
128668a8aea4SAndrei Emeltchenko 		break;
128768a8aea4SAndrei Emeltchenko 
128868a8aea4SAndrei Emeltchenko 	default:
12892064ee33SMarcel Holtmann 		bt_dev_err(hdev, "use of reserved LE_Scan_Enable param %d",
12903baef810SJaganath Kanakkassery 			   enable);
129168a8aea4SAndrei Emeltchenko 		break;
129235815085SAndre Guedes 	}
12935c1a4c8fSJaganath Kanakkassery 
12945c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
1295eb9d91f5SAndre Guedes }
1296eb9d91f5SAndre Guedes 
12973baef810SJaganath Kanakkassery static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
12983baef810SJaganath Kanakkassery 				      struct sk_buff *skb)
12993baef810SJaganath Kanakkassery {
13003baef810SJaganath Kanakkassery 	struct hci_cp_le_set_scan_enable *cp;
13013baef810SJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
13023baef810SJaganath Kanakkassery 
13033baef810SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
13043baef810SJaganath Kanakkassery 
13053baef810SJaganath Kanakkassery 	if (status)
13063baef810SJaganath Kanakkassery 		return;
13073baef810SJaganath Kanakkassery 
13083baef810SJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
13093baef810SJaganath Kanakkassery 	if (!cp)
13103baef810SJaganath Kanakkassery 		return;
13113baef810SJaganath Kanakkassery 
13123baef810SJaganath Kanakkassery 	le_set_scan_enable_complete(hdev, cp->enable);
13133baef810SJaganath Kanakkassery }
13143baef810SJaganath Kanakkassery 
1315a2344b9eSJaganath Kanakkassery static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev,
1316a2344b9eSJaganath Kanakkassery 				      struct sk_buff *skb)
1317a2344b9eSJaganath Kanakkassery {
1318a2344b9eSJaganath Kanakkassery 	struct hci_cp_le_set_ext_scan_enable *cp;
1319a2344b9eSJaganath Kanakkassery 	__u8 status = *((__u8 *) skb->data);
1320a2344b9eSJaganath Kanakkassery 
1321a2344b9eSJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1322a2344b9eSJaganath Kanakkassery 
1323a2344b9eSJaganath Kanakkassery 	if (status)
1324a2344b9eSJaganath Kanakkassery 		return;
1325a2344b9eSJaganath Kanakkassery 
1326a2344b9eSJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_ENABLE);
1327a2344b9eSJaganath Kanakkassery 	if (!cp)
1328a2344b9eSJaganath Kanakkassery 		return;
1329a2344b9eSJaganath Kanakkassery 
1330a2344b9eSJaganath Kanakkassery 	le_set_scan_enable_complete(hdev, cp->enable);
1331a2344b9eSJaganath Kanakkassery }
1332a2344b9eSJaganath Kanakkassery 
13336b49bcb4SJaganath Kanakkassery static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev,
13346b49bcb4SJaganath Kanakkassery 				      struct sk_buff *skb)
13356b49bcb4SJaganath Kanakkassery {
13366b49bcb4SJaganath Kanakkassery 	struct hci_rp_le_read_num_supported_adv_sets *rp = (void *) skb->data;
13376b49bcb4SJaganath Kanakkassery 
13386b49bcb4SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x No of Adv sets %u", hdev->name, rp->status,
13396b49bcb4SJaganath Kanakkassery 	       rp->num_of_sets);
13406b49bcb4SJaganath Kanakkassery 
13416b49bcb4SJaganath Kanakkassery 	if (rp->status)
13426b49bcb4SJaganath Kanakkassery 		return;
13436b49bcb4SJaganath Kanakkassery 
13446b49bcb4SJaganath Kanakkassery 	hdev->le_num_of_adv_sets = rp->num_of_sets;
13456b49bcb4SJaganath Kanakkassery }
13466b49bcb4SJaganath Kanakkassery 
1347cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1348cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
1349cf1d081fSJohan Hedberg {
1350cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1351cf1d081fSJohan Hedberg 
1352cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1353cf1d081fSJohan Hedberg 
135445296acdSMarcel Holtmann 	if (rp->status)
135545296acdSMarcel Holtmann 		return;
135645296acdSMarcel Holtmann 
1357cf1d081fSJohan Hedberg 	hdev->le_white_list_size = rp->size;
1358cf1d081fSJohan Hedberg }
1359cf1d081fSJohan Hedberg 
13600f36b589SMarcel Holtmann static void hci_cc_le_clear_white_list(struct hci_dev *hdev,
13610f36b589SMarcel Holtmann 				       struct sk_buff *skb)
13620f36b589SMarcel Holtmann {
13630f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
13640f36b589SMarcel Holtmann 
13650f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
13660f36b589SMarcel Holtmann 
136745296acdSMarcel Holtmann 	if (status)
136845296acdSMarcel Holtmann 		return;
136945296acdSMarcel Holtmann 
1370dcc36c16SJohan Hedberg 	hci_bdaddr_list_clear(&hdev->le_white_list);
13710f36b589SMarcel Holtmann }
13720f36b589SMarcel Holtmann 
13730f36b589SMarcel Holtmann static void hci_cc_le_add_to_white_list(struct hci_dev *hdev,
13740f36b589SMarcel Holtmann 					struct sk_buff *skb)
13750f36b589SMarcel Holtmann {
13760f36b589SMarcel Holtmann 	struct hci_cp_le_add_to_white_list *sent;
13770f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
13780f36b589SMarcel Holtmann 
13790f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
13800f36b589SMarcel Holtmann 
138145296acdSMarcel Holtmann 	if (status)
138245296acdSMarcel Holtmann 		return;
138345296acdSMarcel Holtmann 
13840f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST);
13850f36b589SMarcel Holtmann 	if (!sent)
13860f36b589SMarcel Holtmann 		return;
13870f36b589SMarcel Holtmann 
1388dcc36c16SJohan Hedberg 	hci_bdaddr_list_add(&hdev->le_white_list, &sent->bdaddr,
1389dcc36c16SJohan Hedberg 			   sent->bdaddr_type);
13900f36b589SMarcel Holtmann }
13910f36b589SMarcel Holtmann 
13920f36b589SMarcel Holtmann static void hci_cc_le_del_from_white_list(struct hci_dev *hdev,
13930f36b589SMarcel Holtmann 					  struct sk_buff *skb)
13940f36b589SMarcel Holtmann {
13950f36b589SMarcel Holtmann 	struct hci_cp_le_del_from_white_list *sent;
13960f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
13970f36b589SMarcel Holtmann 
13980f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
13990f36b589SMarcel Holtmann 
140045296acdSMarcel Holtmann 	if (status)
140145296acdSMarcel Holtmann 		return;
140245296acdSMarcel Holtmann 
14030f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST);
14040f36b589SMarcel Holtmann 	if (!sent)
14050f36b589SMarcel Holtmann 		return;
14060f36b589SMarcel Holtmann 
1407dcc36c16SJohan Hedberg 	hci_bdaddr_list_del(&hdev->le_white_list, &sent->bdaddr,
1408dcc36c16SJohan Hedberg 			    sent->bdaddr_type);
14090f36b589SMarcel Holtmann }
14100f36b589SMarcel Holtmann 
14119b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
14129b008c04SJohan Hedberg 					    struct sk_buff *skb)
14139b008c04SJohan Hedberg {
14149b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
14159b008c04SJohan Hedberg 
14169b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
14179b008c04SJohan Hedberg 
141845296acdSMarcel Holtmann 	if (rp->status)
141945296acdSMarcel Holtmann 		return;
142045296acdSMarcel Holtmann 
14219b008c04SJohan Hedberg 	memcpy(hdev->le_states, rp->le_states, 8);
14229b008c04SJohan Hedberg }
14239b008c04SJohan Hedberg 
1424a8e1bfaaSMarcel Holtmann static void hci_cc_le_read_def_data_len(struct hci_dev *hdev,
1425a8e1bfaaSMarcel Holtmann 					struct sk_buff *skb)
1426a8e1bfaaSMarcel Holtmann {
1427a8e1bfaaSMarcel Holtmann 	struct hci_rp_le_read_def_data_len *rp = (void *) skb->data;
1428a8e1bfaaSMarcel Holtmann 
1429a8e1bfaaSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1430a8e1bfaaSMarcel Holtmann 
1431a8e1bfaaSMarcel Holtmann 	if (rp->status)
1432a8e1bfaaSMarcel Holtmann 		return;
1433a8e1bfaaSMarcel Holtmann 
1434a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_len = le16_to_cpu(rp->tx_len);
1435a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_time = le16_to_cpu(rp->tx_time);
1436a8e1bfaaSMarcel Holtmann }
1437a8e1bfaaSMarcel Holtmann 
1438a8e1bfaaSMarcel Holtmann static void hci_cc_le_write_def_data_len(struct hci_dev *hdev,
1439a8e1bfaaSMarcel Holtmann 					 struct sk_buff *skb)
1440a8e1bfaaSMarcel Holtmann {
1441a8e1bfaaSMarcel Holtmann 	struct hci_cp_le_write_def_data_len *sent;
1442a8e1bfaaSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1443a8e1bfaaSMarcel Holtmann 
1444a8e1bfaaSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1445a8e1bfaaSMarcel Holtmann 
1446a8e1bfaaSMarcel Holtmann 	if (status)
1447a8e1bfaaSMarcel Holtmann 		return;
1448a8e1bfaaSMarcel Holtmann 
1449a8e1bfaaSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN);
1450a8e1bfaaSMarcel Holtmann 	if (!sent)
1451a8e1bfaaSMarcel Holtmann 		return;
1452a8e1bfaaSMarcel Holtmann 
1453a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_len = le16_to_cpu(sent->tx_len);
1454a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_time = le16_to_cpu(sent->tx_time);
1455a8e1bfaaSMarcel Holtmann }
1456a8e1bfaaSMarcel Holtmann 
1457b950aa88SAnkit Navik static void hci_cc_le_add_to_resolv_list(struct hci_dev *hdev,
1458b950aa88SAnkit Navik 					 struct sk_buff *skb)
1459b950aa88SAnkit Navik {
1460b950aa88SAnkit Navik 	struct hci_cp_le_add_to_resolv_list *sent;
1461b950aa88SAnkit Navik 	__u8 status = *((__u8 *) skb->data);
1462b950aa88SAnkit Navik 
1463b950aa88SAnkit Navik 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1464b950aa88SAnkit Navik 
1465b950aa88SAnkit Navik 	if (status)
1466b950aa88SAnkit Navik 		return;
1467b950aa88SAnkit Navik 
1468b950aa88SAnkit Navik 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST);
1469b950aa88SAnkit Navik 	if (!sent)
1470b950aa88SAnkit Navik 		return;
1471b950aa88SAnkit Navik 
1472b950aa88SAnkit Navik 	hci_bdaddr_list_add_with_irk(&hdev->le_resolv_list, &sent->bdaddr,
1473b950aa88SAnkit Navik 				sent->bdaddr_type, sent->peer_irk,
1474b950aa88SAnkit Navik 				sent->local_irk);
1475b950aa88SAnkit Navik }
1476b950aa88SAnkit Navik 
1477b950aa88SAnkit Navik static void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev,
1478b950aa88SAnkit Navik 					  struct sk_buff *skb)
1479b950aa88SAnkit Navik {
1480b950aa88SAnkit Navik 	struct hci_cp_le_del_from_resolv_list *sent;
1481b950aa88SAnkit Navik 	__u8 status = *((__u8 *) skb->data);
1482b950aa88SAnkit Navik 
1483b950aa88SAnkit Navik 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1484b950aa88SAnkit Navik 
1485b950aa88SAnkit Navik 	if (status)
1486b950aa88SAnkit Navik 		return;
1487b950aa88SAnkit Navik 
1488b950aa88SAnkit Navik 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLV_LIST);
1489b950aa88SAnkit Navik 	if (!sent)
1490b950aa88SAnkit Navik 		return;
1491b950aa88SAnkit Navik 
1492b950aa88SAnkit Navik 	hci_bdaddr_list_del_with_irk(&hdev->le_resolv_list, &sent->bdaddr,
1493b950aa88SAnkit Navik 			    sent->bdaddr_type);
1494b950aa88SAnkit Navik }
1495b950aa88SAnkit Navik 
1496545f2596SAnkit Navik static void hci_cc_le_clear_resolv_list(struct hci_dev *hdev,
1497545f2596SAnkit Navik 				       struct sk_buff *skb)
1498545f2596SAnkit Navik {
1499545f2596SAnkit Navik 	__u8 status = *((__u8 *) skb->data);
1500545f2596SAnkit Navik 
1501545f2596SAnkit Navik 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1502545f2596SAnkit Navik 
1503545f2596SAnkit Navik 	if (status)
1504545f2596SAnkit Navik 		return;
1505545f2596SAnkit Navik 
1506545f2596SAnkit Navik 	hci_bdaddr_list_clear(&hdev->le_resolv_list);
1507545f2596SAnkit Navik }
1508545f2596SAnkit Navik 
1509cfdb0c2dSAnkit Navik static void hci_cc_le_read_resolv_list_size(struct hci_dev *hdev,
1510cfdb0c2dSAnkit Navik 					   struct sk_buff *skb)
1511cfdb0c2dSAnkit Navik {
1512cfdb0c2dSAnkit Navik 	struct hci_rp_le_read_resolv_list_size *rp = (void *) skb->data;
1513cfdb0c2dSAnkit Navik 
1514cfdb0c2dSAnkit Navik 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1515cfdb0c2dSAnkit Navik 
1516cfdb0c2dSAnkit Navik 	if (rp->status)
1517cfdb0c2dSAnkit Navik 		return;
1518cfdb0c2dSAnkit Navik 
1519cfdb0c2dSAnkit Navik 	hdev->le_resolv_list_size = rp->size;
1520cfdb0c2dSAnkit Navik }
1521cfdb0c2dSAnkit Navik 
1522aa12af77SAnkit Navik static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev,
1523aa12af77SAnkit Navik 						struct sk_buff *skb)
1524aa12af77SAnkit Navik {
1525aa12af77SAnkit Navik 	__u8 *sent, status = *((__u8 *) skb->data);
1526aa12af77SAnkit Navik 
1527aa12af77SAnkit Navik 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1528aa12af77SAnkit Navik 
1529aa12af77SAnkit Navik 	if (status)
1530aa12af77SAnkit Navik 		return;
1531aa12af77SAnkit Navik 
1532aa12af77SAnkit Navik 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE);
1533aa12af77SAnkit Navik 	if (!sent)
1534aa12af77SAnkit Navik 		return;
1535aa12af77SAnkit Navik 
1536aa12af77SAnkit Navik 	hci_dev_lock(hdev);
1537aa12af77SAnkit Navik 
1538aa12af77SAnkit Navik 	if (*sent)
1539aa12af77SAnkit Navik 		hci_dev_set_flag(hdev, HCI_LL_RPA_RESOLUTION);
1540aa12af77SAnkit Navik 	else
1541aa12af77SAnkit Navik 		hci_dev_clear_flag(hdev, HCI_LL_RPA_RESOLUTION);
1542aa12af77SAnkit Navik 
1543aa12af77SAnkit Navik 	hci_dev_unlock(hdev);
1544aa12af77SAnkit Navik }
1545aa12af77SAnkit Navik 
1546a8e1bfaaSMarcel Holtmann static void hci_cc_le_read_max_data_len(struct hci_dev *hdev,
1547a8e1bfaaSMarcel Holtmann 					struct sk_buff *skb)
1548a8e1bfaaSMarcel Holtmann {
1549a8e1bfaaSMarcel Holtmann 	struct hci_rp_le_read_max_data_len *rp = (void *) skb->data;
1550a8e1bfaaSMarcel Holtmann 
1551a8e1bfaaSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1552a8e1bfaaSMarcel Holtmann 
1553a8e1bfaaSMarcel Holtmann 	if (rp->status)
1554a8e1bfaaSMarcel Holtmann 		return;
1555a8e1bfaaSMarcel Holtmann 
1556a8e1bfaaSMarcel Holtmann 	hdev->le_max_tx_len = le16_to_cpu(rp->tx_len);
1557a8e1bfaaSMarcel Holtmann 	hdev->le_max_tx_time = le16_to_cpu(rp->tx_time);
1558a8e1bfaaSMarcel Holtmann 	hdev->le_max_rx_len = le16_to_cpu(rp->rx_len);
1559a8e1bfaaSMarcel Holtmann 	hdev->le_max_rx_time = le16_to_cpu(rp->rx_time);
1560a8e1bfaaSMarcel Holtmann }
1561a8e1bfaaSMarcel Holtmann 
15626039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1563f9b49306SAndre Guedes 					   struct sk_buff *skb)
1564f9b49306SAndre Guedes {
156506199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1566f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1567f9b49306SAndre Guedes 
15689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1569f9b49306SAndre Guedes 
157045296acdSMarcel Holtmann 	if (status)
157145296acdSMarcel Holtmann 		return;
157245296acdSMarcel Holtmann 
157306199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
15748f984dfaSJohan Hedberg 	if (!sent)
1575f9b49306SAndre Guedes 		return;
1576f9b49306SAndre Guedes 
15775c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
15785c1a4c8fSJaganath Kanakkassery 
1579416a4ae5SJohan Hedberg 	if (sent->le) {
1580cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE;
1581a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_LE_ENABLED);
1582416a4ae5SJohan Hedberg 	} else {
1583cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE;
1584a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_LE_ENABLED);
1585a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_ADVERTISING);
1586416a4ae5SJohan Hedberg 	}
158753b2caabSJohan Hedberg 
158853b2caabSJohan Hedberg 	if (sent->simul)
1589cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE_BREDR;
159053b2caabSJohan Hedberg 	else
1591cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
15925c1a4c8fSJaganath Kanakkassery 
15935c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
15948f984dfaSJohan Hedberg }
1595f9b49306SAndre Guedes 
159656ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
159756ed2cb8SJohan Hedberg {
159856ed2cb8SJohan Hedberg 	struct hci_cp_le_set_adv_param *cp;
159956ed2cb8SJohan Hedberg 	u8 status = *((u8 *) skb->data);
160056ed2cb8SJohan Hedberg 
160156ed2cb8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
160256ed2cb8SJohan Hedberg 
160356ed2cb8SJohan Hedberg 	if (status)
160456ed2cb8SJohan Hedberg 		return;
160556ed2cb8SJohan Hedberg 
160656ed2cb8SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
160756ed2cb8SJohan Hedberg 	if (!cp)
160856ed2cb8SJohan Hedberg 		return;
160956ed2cb8SJohan Hedberg 
161056ed2cb8SJohan Hedberg 	hci_dev_lock(hdev);
161156ed2cb8SJohan Hedberg 	hdev->adv_addr_type = cp->own_address_type;
161256ed2cb8SJohan Hedberg 	hci_dev_unlock(hdev);
161356ed2cb8SJohan Hedberg }
161456ed2cb8SJohan Hedberg 
1615de181e88SJaganath Kanakkassery static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
1616de181e88SJaganath Kanakkassery {
1617de181e88SJaganath Kanakkassery 	struct hci_rp_le_set_ext_adv_params *rp = (void *) skb->data;
1618de181e88SJaganath Kanakkassery 	struct hci_cp_le_set_ext_adv_params *cp;
1619de181e88SJaganath Kanakkassery 	struct adv_info *adv_instance;
1620de181e88SJaganath Kanakkassery 
1621de181e88SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1622de181e88SJaganath Kanakkassery 
1623de181e88SJaganath Kanakkassery 	if (rp->status)
1624de181e88SJaganath Kanakkassery 		return;
1625de181e88SJaganath Kanakkassery 
1626de181e88SJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS);
1627de181e88SJaganath Kanakkassery 	if (!cp)
1628de181e88SJaganath Kanakkassery 		return;
1629de181e88SJaganath Kanakkassery 
1630de181e88SJaganath Kanakkassery 	hci_dev_lock(hdev);
1631de181e88SJaganath Kanakkassery 	hdev->adv_addr_type = cp->own_addr_type;
1632de181e88SJaganath Kanakkassery 	if (!hdev->cur_adv_instance) {
1633de181e88SJaganath Kanakkassery 		/* Store in hdev for instance 0 */
1634de181e88SJaganath Kanakkassery 		hdev->adv_tx_power = rp->tx_power;
1635de181e88SJaganath Kanakkassery 	} else {
1636de181e88SJaganath Kanakkassery 		adv_instance = hci_find_adv_instance(hdev,
1637de181e88SJaganath Kanakkassery 						     hdev->cur_adv_instance);
1638de181e88SJaganath Kanakkassery 		if (adv_instance)
1639de181e88SJaganath Kanakkassery 			adv_instance->tx_power = rp->tx_power;
1640de181e88SJaganath Kanakkassery 	}
1641a0fb3726SJaganath Kanakkassery 	/* Update adv data as tx power is known now */
1642a0fb3726SJaganath Kanakkassery 	hci_req_update_adv_data(hdev, hdev->cur_adv_instance);
1643de181e88SJaganath Kanakkassery 	hci_dev_unlock(hdev);
1644de181e88SJaganath Kanakkassery }
1645de181e88SJaganath Kanakkassery 
16465ae76a94SAndrzej Kaczmarek static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
16475ae76a94SAndrzej Kaczmarek {
16485ae76a94SAndrzej Kaczmarek 	struct hci_rp_read_rssi *rp = (void *) skb->data;
16495ae76a94SAndrzej Kaczmarek 	struct hci_conn *conn;
16505ae76a94SAndrzej Kaczmarek 
16515ae76a94SAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
16525ae76a94SAndrzej Kaczmarek 
16535ae76a94SAndrzej Kaczmarek 	if (rp->status)
16545ae76a94SAndrzej Kaczmarek 		return;
16555ae76a94SAndrzej Kaczmarek 
16565ae76a94SAndrzej Kaczmarek 	hci_dev_lock(hdev);
16575ae76a94SAndrzej Kaczmarek 
16585ae76a94SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
16595ae76a94SAndrzej Kaczmarek 	if (conn)
16605ae76a94SAndrzej Kaczmarek 		conn->rssi = rp->rssi;
16615ae76a94SAndrzej Kaczmarek 
16625ae76a94SAndrzej Kaczmarek 	hci_dev_unlock(hdev);
16635ae76a94SAndrzej Kaczmarek }
16645ae76a94SAndrzej Kaczmarek 
16655a134faeSAndrzej Kaczmarek static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb)
16665a134faeSAndrzej Kaczmarek {
16675a134faeSAndrzej Kaczmarek 	struct hci_cp_read_tx_power *sent;
16685a134faeSAndrzej Kaczmarek 	struct hci_rp_read_tx_power *rp = (void *) skb->data;
16695a134faeSAndrzej Kaczmarek 	struct hci_conn *conn;
16705a134faeSAndrzej Kaczmarek 
16715a134faeSAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
16725a134faeSAndrzej Kaczmarek 
16735a134faeSAndrzej Kaczmarek 	if (rp->status)
16745a134faeSAndrzej Kaczmarek 		return;
16755a134faeSAndrzej Kaczmarek 
16765a134faeSAndrzej Kaczmarek 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
16775a134faeSAndrzej Kaczmarek 	if (!sent)
16785a134faeSAndrzej Kaczmarek 		return;
16795a134faeSAndrzej Kaczmarek 
16805a134faeSAndrzej Kaczmarek 	hci_dev_lock(hdev);
16815a134faeSAndrzej Kaczmarek 
16825a134faeSAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1683d0455ed9SAndrzej Kaczmarek 	if (!conn)
1684d0455ed9SAndrzej Kaczmarek 		goto unlock;
16855a134faeSAndrzej Kaczmarek 
1686d0455ed9SAndrzej Kaczmarek 	switch (sent->type) {
1687d0455ed9SAndrzej Kaczmarek 	case 0x00:
1688d0455ed9SAndrzej Kaczmarek 		conn->tx_power = rp->tx_power;
1689d0455ed9SAndrzej Kaczmarek 		break;
1690d0455ed9SAndrzej Kaczmarek 	case 0x01:
1691d0455ed9SAndrzej Kaczmarek 		conn->max_tx_power = rp->tx_power;
1692d0455ed9SAndrzej Kaczmarek 		break;
1693d0455ed9SAndrzej Kaczmarek 	}
1694d0455ed9SAndrzej Kaczmarek 
1695d0455ed9SAndrzej Kaczmarek unlock:
16965a134faeSAndrzej Kaczmarek 	hci_dev_unlock(hdev);
16975a134faeSAndrzej Kaczmarek }
16985a134faeSAndrzej Kaczmarek 
1699c50b33c8SMarcel Holtmann static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb)
1700c50b33c8SMarcel Holtmann {
1701c50b33c8SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
1702c50b33c8SMarcel Holtmann 	u8 *mode;
1703c50b33c8SMarcel Holtmann 
1704c50b33c8SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1705c50b33c8SMarcel Holtmann 
1706c50b33c8SMarcel Holtmann 	if (status)
1707c50b33c8SMarcel Holtmann 		return;
1708c50b33c8SMarcel Holtmann 
1709c50b33c8SMarcel Holtmann 	mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE);
1710c50b33c8SMarcel Holtmann 	if (mode)
1711c50b33c8SMarcel Holtmann 		hdev->ssp_debug_mode = *mode;
1712c50b33c8SMarcel Holtmann }
1713c50b33c8SMarcel Holtmann 
17146039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1715a9de9248SMarcel Holtmann {
17169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1717a9de9248SMarcel Holtmann 
1718a9de9248SMarcel Holtmann 	if (status) {
1719a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1720314b2381SJohan Hedberg 		return;
1721314b2381SJohan Hedberg 	}
1722314b2381SJohan Hedberg 
172389352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1724a9de9248SMarcel Holtmann }
1725a9de9248SMarcel Holtmann 
17266039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
17271da177e4SLinus Torvalds {
1728a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
17291da177e4SLinus Torvalds 	struct hci_conn *conn;
17301da177e4SLinus Torvalds 
17319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1732a9de9248SMarcel Holtmann 
1733a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
17341da177e4SLinus Torvalds 	if (!cp)
17351da177e4SLinus Torvalds 		return;
17361da177e4SLinus Torvalds 
17371da177e4SLinus Torvalds 	hci_dev_lock(hdev);
17381da177e4SLinus Torvalds 
17391da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
17401da177e4SLinus Torvalds 
17416ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
17421da177e4SLinus Torvalds 
17431da177e4SLinus Torvalds 	if (status) {
17441da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
17454c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
17461da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
1747539c496dSJohan Hedberg 				hci_connect_cfm(conn, status);
17481da177e4SLinus Torvalds 				hci_conn_del(conn);
17494c67bc74SMarcel Holtmann 			} else
17504c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
17511da177e4SLinus Torvalds 		}
17521da177e4SLinus Torvalds 	} else {
17531da177e4SLinus Torvalds 		if (!conn) {
1754a5c4e309SJohan Hedberg 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr,
1755a5c4e309SJohan Hedberg 					    HCI_ROLE_MASTER);
1756a5c4e309SJohan Hedberg 			if (!conn)
17572064ee33SMarcel Holtmann 				bt_dev_err(hdev, "no memory for new connection");
17581da177e4SLinus Torvalds 		}
17591da177e4SLinus Torvalds 	}
17601da177e4SLinus Torvalds 
17611da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17621da177e4SLinus Torvalds }
17631da177e4SLinus Torvalds 
1764a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
17651da177e4SLinus Torvalds {
1766a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
17671da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
17681da177e4SLinus Torvalds 	__u16 handle;
17691da177e4SLinus Torvalds 
17709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1771b6a0dc82SMarcel Holtmann 
1772a9de9248SMarcel Holtmann 	if (!status)
1773a9de9248SMarcel Holtmann 		return;
1774a9de9248SMarcel Holtmann 
1775a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
17761da177e4SLinus Torvalds 	if (!cp)
1777a9de9248SMarcel Holtmann 		return;
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
17801da177e4SLinus Torvalds 
17819f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
17821da177e4SLinus Torvalds 
17831da177e4SLinus Torvalds 	hci_dev_lock(hdev);
17841da177e4SLinus Torvalds 
17851da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
17865a08ecceSAndrei Emeltchenko 	if (acl) {
17875a08ecceSAndrei Emeltchenko 		sco = acl->link;
17885a08ecceSAndrei Emeltchenko 		if (sco) {
17891da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
17901da177e4SLinus Torvalds 
1791539c496dSJohan Hedberg 			hci_connect_cfm(sco, status);
17921da177e4SLinus Torvalds 			hci_conn_del(sco);
17931da177e4SLinus Torvalds 		}
17945a08ecceSAndrei Emeltchenko 	}
17951da177e4SLinus Torvalds 
17961da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17971da177e4SLinus Torvalds }
17981da177e4SLinus Torvalds 
1799f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1800f8558555SMarcel Holtmann {
1801f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1802f8558555SMarcel Holtmann 	struct hci_conn *conn;
1803f8558555SMarcel Holtmann 
18049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1805f8558555SMarcel Holtmann 
1806f8558555SMarcel Holtmann 	if (!status)
1807f8558555SMarcel Holtmann 		return;
1808f8558555SMarcel Holtmann 
1809f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1810f8558555SMarcel Holtmann 	if (!cp)
1811f8558555SMarcel Holtmann 		return;
1812f8558555SMarcel Holtmann 
1813f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1814f8558555SMarcel Holtmann 
1815f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1816f8558555SMarcel Holtmann 	if (conn) {
1817f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1818539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
181976a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1820f8558555SMarcel Holtmann 		}
1821f8558555SMarcel Holtmann 	}
1822f8558555SMarcel Holtmann 
1823f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1824f8558555SMarcel Holtmann }
1825f8558555SMarcel Holtmann 
1826f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1827f8558555SMarcel Holtmann {
1828f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1829f8558555SMarcel Holtmann 	struct hci_conn *conn;
1830f8558555SMarcel Holtmann 
18319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1832f8558555SMarcel Holtmann 
1833f8558555SMarcel Holtmann 	if (!status)
1834f8558555SMarcel Holtmann 		return;
1835f8558555SMarcel Holtmann 
1836f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1837f8558555SMarcel Holtmann 	if (!cp)
1838f8558555SMarcel Holtmann 		return;
1839f8558555SMarcel Holtmann 
1840f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1841f8558555SMarcel Holtmann 
1842f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1843f8558555SMarcel Holtmann 	if (conn) {
1844f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1845539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
184676a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1847f8558555SMarcel Holtmann 		}
1848f8558555SMarcel Holtmann 	}
1849f8558555SMarcel Holtmann 
1850f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1851f8558555SMarcel Holtmann }
1852f8558555SMarcel Holtmann 
1853127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1854392599b9SJohan Hedberg 				    struct hci_conn *conn)
1855392599b9SJohan Hedberg {
1856392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1857392599b9SJohan Hedberg 		return 0;
1858392599b9SJohan Hedberg 
1859765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1860392599b9SJohan Hedberg 		return 0;
1861392599b9SJohan Hedberg 
1862392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1863264b8b4eSJohan Hedberg 	 * devices with sec_level MEDIUM or HIGH or if MITM protection
1864264b8b4eSJohan Hedberg 	 * is requested.
1865264b8b4eSJohan Hedberg 	 */
1866807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
18677e3691e1SJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_FIPS &&
1868264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
1869264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
1870392599b9SJohan Hedberg 		return 0;
1871392599b9SJohan Hedberg 
1872392599b9SJohan Hedberg 	return 1;
1873392599b9SJohan Hedberg }
1874392599b9SJohan Hedberg 
18756039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
187600abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
187730dc78e1SJohan Hedberg {
187830dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
187930dc78e1SJohan Hedberg 
188030dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
188130dc78e1SJohan Hedberg 
188230dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
188330dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
188430dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
188530dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
188630dc78e1SJohan Hedberg 
188730dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
188830dc78e1SJohan Hedberg }
188930dc78e1SJohan Hedberg 
1890b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
189130dc78e1SJohan Hedberg {
189230dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
189330dc78e1SJohan Hedberg 	struct inquiry_entry *e;
189430dc78e1SJohan Hedberg 
1895b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1896b644ba33SJohan Hedberg 		return false;
1897b644ba33SJohan Hedberg 
1898b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1899c810089cSRam Malovany 	if (!e)
1900c810089cSRam Malovany 		return false;
1901c810089cSRam Malovany 
1902b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1903b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1904b644ba33SJohan Hedberg 		return true;
1905b644ba33SJohan Hedberg 	}
1906b644ba33SJohan Hedberg 
1907b644ba33SJohan Hedberg 	return false;
1908b644ba33SJohan Hedberg }
1909b644ba33SJohan Hedberg 
1910b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1911b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1912b644ba33SJohan Hedberg {
1913b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1914b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1915b644ba33SJohan Hedberg 
191660cb49d2SJohan Hedberg 	/* Update the mgmt connected state if necessary. Be careful with
191760cb49d2SJohan Hedberg 	 * conn objects that exist but are not (yet) connected however.
191860cb49d2SJohan Hedberg 	 * Only those in BT_CONFIG or BT_CONNECTED states can be
191960cb49d2SJohan Hedberg 	 * considered connected.
192060cb49d2SJohan Hedberg 	 */
192160cb49d2SJohan Hedberg 	if (conn &&
192260cb49d2SJohan Hedberg 	    (conn->state == BT_CONFIG || conn->state == BT_CONNECTED) &&
1923cb77c3ecSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
192448ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, name, name_len);
1925b644ba33SJohan Hedberg 
1926b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1927b644ba33SJohan Hedberg 		return;
1928b644ba33SJohan Hedberg 
192930dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
193030dc78e1SJohan Hedberg 		goto discov_complete;
193130dc78e1SJohan Hedberg 
193230dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
193330dc78e1SJohan Hedberg 		return;
193430dc78e1SJohan Hedberg 
193530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
19367cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
19377cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
19387cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
19397cc8380eSRam Malovany 	 * Event */
19407cc8380eSRam Malovany 	if (!e)
19417cc8380eSRam Malovany 		return;
19427cc8380eSRam Malovany 
194330dc78e1SJohan Hedberg 	list_del(&e->list);
19447cc8380eSRam Malovany 	if (name) {
19457cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1946b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1947b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1948c3e7c0d9SRam Malovany 	} else {
1949c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
195030dc78e1SJohan Hedberg 	}
195130dc78e1SJohan Hedberg 
1952b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
195330dc78e1SJohan Hedberg 		return;
195430dc78e1SJohan Hedberg 
195530dc78e1SJohan Hedberg discov_complete:
195630dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
195730dc78e1SJohan Hedberg }
195830dc78e1SJohan Hedberg 
1959a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
19601da177e4SLinus Torvalds {
1961127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1962127178d2SJohan Hedberg 	struct hci_conn *conn;
1963127178d2SJohan Hedberg 
19649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1965127178d2SJohan Hedberg 
1966127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1967127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1968127178d2SJohan Hedberg 	if (!status)
1969127178d2SJohan Hedberg 		return;
1970127178d2SJohan Hedberg 
1971127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1972127178d2SJohan Hedberg 	if (!cp)
1973127178d2SJohan Hedberg 		return;
1974127178d2SJohan Hedberg 
1975127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1976127178d2SJohan Hedberg 
1977127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1978b644ba33SJohan Hedberg 
1979d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
1980b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1981b644ba33SJohan Hedberg 
198279c6c70cSJohan Hedberg 	if (!conn)
198379c6c70cSJohan Hedberg 		goto unlock;
198479c6c70cSJohan Hedberg 
198579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
198679c6c70cSJohan Hedberg 		goto unlock;
198779c6c70cSJohan Hedberg 
198851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1989c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
1990c1f23a2bSJohannes Berg 
1991977f8fceSJohan Hedberg 		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
1992977f8fceSJohan Hedberg 
1993c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
1994c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1995c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
1996127178d2SJohan Hedberg 	}
1997127178d2SJohan Hedberg 
199879c6c70cSJohan Hedberg unlock:
1999127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2000a9de9248SMarcel Holtmann }
20011da177e4SLinus Torvalds 
2002769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
2003769be974SMarcel Holtmann {
2004769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
2005769be974SMarcel Holtmann 	struct hci_conn *conn;
2006769be974SMarcel Holtmann 
20079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2008769be974SMarcel Holtmann 
2009769be974SMarcel Holtmann 	if (!status)
2010769be974SMarcel Holtmann 		return;
2011769be974SMarcel Holtmann 
2012769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
2013769be974SMarcel Holtmann 	if (!cp)
2014769be974SMarcel Holtmann 		return;
2015769be974SMarcel Holtmann 
2016769be974SMarcel Holtmann 	hci_dev_lock(hdev);
2017769be974SMarcel Holtmann 
2018769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
2019769be974SMarcel Holtmann 	if (conn) {
2020769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2021539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
202276a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2023769be974SMarcel Holtmann 		}
2024769be974SMarcel Holtmann 	}
2025769be974SMarcel Holtmann 
2026769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
2027769be974SMarcel Holtmann }
2028769be974SMarcel Holtmann 
2029769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
2030769be974SMarcel Holtmann {
2031769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
2032769be974SMarcel Holtmann 	struct hci_conn *conn;
2033769be974SMarcel Holtmann 
20349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2035769be974SMarcel Holtmann 
2036769be974SMarcel Holtmann 	if (!status)
2037769be974SMarcel Holtmann 		return;
2038769be974SMarcel Holtmann 
2039769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
2040769be974SMarcel Holtmann 	if (!cp)
2041769be974SMarcel Holtmann 		return;
2042769be974SMarcel Holtmann 
2043769be974SMarcel Holtmann 	hci_dev_lock(hdev);
2044769be974SMarcel Holtmann 
2045769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
2046769be974SMarcel Holtmann 	if (conn) {
2047769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2048539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
204976a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2050769be974SMarcel Holtmann 		}
2051769be974SMarcel Holtmann 	}
2052769be974SMarcel Holtmann 
2053769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
2054769be974SMarcel Holtmann }
2055769be974SMarcel Holtmann 
2056a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
2057a9de9248SMarcel Holtmann {
2058b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
2059b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
2060b6a0dc82SMarcel Holtmann 	__u16 handle;
2061b6a0dc82SMarcel Holtmann 
20629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2063b6a0dc82SMarcel Holtmann 
2064b6a0dc82SMarcel Holtmann 	if (!status)
2065b6a0dc82SMarcel Holtmann 		return;
2066b6a0dc82SMarcel Holtmann 
2067b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
2068b6a0dc82SMarcel Holtmann 	if (!cp)
2069b6a0dc82SMarcel Holtmann 		return;
2070b6a0dc82SMarcel Holtmann 
2071b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
2072b6a0dc82SMarcel Holtmann 
20739f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
2074b6a0dc82SMarcel Holtmann 
2075b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2076b6a0dc82SMarcel Holtmann 
2077b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
20785a08ecceSAndrei Emeltchenko 	if (acl) {
20795a08ecceSAndrei Emeltchenko 		sco = acl->link;
20805a08ecceSAndrei Emeltchenko 		if (sco) {
2081b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
2082b6a0dc82SMarcel Holtmann 
2083539c496dSJohan Hedberg 			hci_connect_cfm(sco, status);
2084b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
2085b6a0dc82SMarcel Holtmann 		}
20865a08ecceSAndrei Emeltchenko 	}
2087b6a0dc82SMarcel Holtmann 
2088b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2089a9de9248SMarcel Holtmann }
2090a9de9248SMarcel Holtmann 
2091a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
2092a9de9248SMarcel Holtmann {
2093a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
209404837f64SMarcel Holtmann 	struct hci_conn *conn;
209504837f64SMarcel Holtmann 
20969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2097a9de9248SMarcel Holtmann 
2098a9de9248SMarcel Holtmann 	if (!status)
2099a9de9248SMarcel Holtmann 		return;
2100a9de9248SMarcel Holtmann 
2101a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
210204837f64SMarcel Holtmann 	if (!cp)
2103a9de9248SMarcel Holtmann 		return;
210404837f64SMarcel Holtmann 
210504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
210604837f64SMarcel Holtmann 
210704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
2108e73439d8SMarcel Holtmann 	if (conn) {
210951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
211004837f64SMarcel Holtmann 
211151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2112e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
2113e73439d8SMarcel Holtmann 	}
2114e73439d8SMarcel Holtmann 
211504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
211604837f64SMarcel Holtmann }
211704837f64SMarcel Holtmann 
2118a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
2119a9de9248SMarcel Holtmann {
2120a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
212104837f64SMarcel Holtmann 	struct hci_conn *conn;
212204837f64SMarcel Holtmann 
21239f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2124a9de9248SMarcel Holtmann 
2125a9de9248SMarcel Holtmann 	if (!status)
2126a9de9248SMarcel Holtmann 		return;
2127a9de9248SMarcel Holtmann 
2128a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
212904837f64SMarcel Holtmann 	if (!cp)
2130a9de9248SMarcel Holtmann 		return;
213104837f64SMarcel Holtmann 
213204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
213304837f64SMarcel Holtmann 
213404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
2135e73439d8SMarcel Holtmann 	if (conn) {
213651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
213704837f64SMarcel Holtmann 
213851a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2139e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
2140e73439d8SMarcel Holtmann 	}
2141e73439d8SMarcel Holtmann 
214204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
214304837f64SMarcel Holtmann }
214404837f64SMarcel Holtmann 
214588c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
214688c3df13SJohan Hedberg {
214788c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
214888c3df13SJohan Hedberg 	struct hci_conn *conn;
214988c3df13SJohan Hedberg 
215088c3df13SJohan Hedberg 	if (!status)
215188c3df13SJohan Hedberg 		return;
215288c3df13SJohan Hedberg 
215388c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
215488c3df13SJohan Hedberg 	if (!cp)
215588c3df13SJohan Hedberg 		return;
215688c3df13SJohan Hedberg 
215788c3df13SJohan Hedberg 	hci_dev_lock(hdev);
215888c3df13SJohan Hedberg 
215988c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
216088c3df13SJohan Hedberg 	if (conn)
216188c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
216288c3df13SJohan Hedberg 				       conn->dst_type, status);
216388c3df13SJohan Hedberg 
216488c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
216588c3df13SJohan Hedberg }
216688c3df13SJohan Hedberg 
2167d12fb056SJaganath Kanakkassery static void cs_le_create_conn(struct hci_dev *hdev, bdaddr_t *peer_addr,
2168d12fb056SJaganath Kanakkassery 			      u8 peer_addr_type, u8 own_address_type,
2169d12fb056SJaganath Kanakkassery 			      u8 filter_policy)
2170d12fb056SJaganath Kanakkassery {
2171d12fb056SJaganath Kanakkassery 	struct hci_conn *conn;
2172d12fb056SJaganath Kanakkassery 
2173d12fb056SJaganath Kanakkassery 	conn = hci_conn_hash_lookup_le(hdev, peer_addr,
2174d12fb056SJaganath Kanakkassery 				       peer_addr_type);
2175d12fb056SJaganath Kanakkassery 	if (!conn)
2176d12fb056SJaganath Kanakkassery 		return;
2177d12fb056SJaganath Kanakkassery 
2178d12fb056SJaganath Kanakkassery 	/* Store the initiator and responder address information which
2179d12fb056SJaganath Kanakkassery 	 * is needed for SMP. These values will not change during the
2180d12fb056SJaganath Kanakkassery 	 * lifetime of the connection.
2181d12fb056SJaganath Kanakkassery 	 */
2182d12fb056SJaganath Kanakkassery 	conn->init_addr_type = own_address_type;
2183d12fb056SJaganath Kanakkassery 	if (own_address_type == ADDR_LE_DEV_RANDOM)
2184d12fb056SJaganath Kanakkassery 		bacpy(&conn->init_addr, &hdev->random_addr);
2185d12fb056SJaganath Kanakkassery 	else
2186d12fb056SJaganath Kanakkassery 		bacpy(&conn->init_addr, &hdev->bdaddr);
2187d12fb056SJaganath Kanakkassery 
2188d12fb056SJaganath Kanakkassery 	conn->resp_addr_type = peer_addr_type;
2189d12fb056SJaganath Kanakkassery 	bacpy(&conn->resp_addr, peer_addr);
2190d12fb056SJaganath Kanakkassery 
2191d12fb056SJaganath Kanakkassery 	/* We don't want the connection attempt to stick around
2192d12fb056SJaganath Kanakkassery 	 * indefinitely since LE doesn't have a page timeout concept
2193d12fb056SJaganath Kanakkassery 	 * like BR/EDR. Set a timer for any connection that doesn't use
2194d12fb056SJaganath Kanakkassery 	 * the white list for connecting.
2195d12fb056SJaganath Kanakkassery 	 */
2196d12fb056SJaganath Kanakkassery 	if (filter_policy == HCI_LE_USE_PEER_ADDR)
2197d12fb056SJaganath Kanakkassery 		queue_delayed_work(conn->hdev->workqueue,
2198d12fb056SJaganath Kanakkassery 				   &conn->le_conn_timeout,
2199d12fb056SJaganath Kanakkassery 				   conn->conn_timeout);
2200d12fb056SJaganath Kanakkassery }
2201d12fb056SJaganath Kanakkassery 
2202cb1d68f7SJohan Hedberg static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
2203cb1d68f7SJohan Hedberg {
2204cb1d68f7SJohan Hedberg 	struct hci_cp_le_create_conn *cp;
2205cb1d68f7SJohan Hedberg 
2206cb1d68f7SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2207cb1d68f7SJohan Hedberg 
2208cb1d68f7SJohan Hedberg 	/* All connection failure handling is taken care of by the
2209cb1d68f7SJohan Hedberg 	 * hci_le_conn_failed function which is triggered by the HCI
2210cb1d68f7SJohan Hedberg 	 * request completion callbacks used for connecting.
2211cb1d68f7SJohan Hedberg 	 */
2212cb1d68f7SJohan Hedberg 	if (status)
2213cb1d68f7SJohan Hedberg 		return;
2214cb1d68f7SJohan Hedberg 
2215cb1d68f7SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
2216cb1d68f7SJohan Hedberg 	if (!cp)
2217cb1d68f7SJohan Hedberg 		return;
2218cb1d68f7SJohan Hedberg 
2219cb1d68f7SJohan Hedberg 	hci_dev_lock(hdev);
2220cb1d68f7SJohan Hedberg 
2221d12fb056SJaganath Kanakkassery 	cs_le_create_conn(hdev, &cp->peer_addr, cp->peer_addr_type,
2222d12fb056SJaganath Kanakkassery 			  cp->own_address_type, cp->filter_policy);
2223cb1d68f7SJohan Hedberg 
2224cb1d68f7SJohan Hedberg 	hci_dev_unlock(hdev);
2225cb1d68f7SJohan Hedberg }
2226cb1d68f7SJohan Hedberg 
22274d94f95dSJaganath Kanakkassery static void hci_cs_le_ext_create_conn(struct hci_dev *hdev, u8 status)
22284d94f95dSJaganath Kanakkassery {
22294d94f95dSJaganath Kanakkassery 	struct hci_cp_le_ext_create_conn *cp;
22304d94f95dSJaganath Kanakkassery 
22314d94f95dSJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
22324d94f95dSJaganath Kanakkassery 
22334d94f95dSJaganath Kanakkassery 	/* All connection failure handling is taken care of by the
22344d94f95dSJaganath Kanakkassery 	 * hci_le_conn_failed function which is triggered by the HCI
22354d94f95dSJaganath Kanakkassery 	 * request completion callbacks used for connecting.
22364d94f95dSJaganath Kanakkassery 	 */
22374d94f95dSJaganath Kanakkassery 	if (status)
22384d94f95dSJaganath Kanakkassery 		return;
22394d94f95dSJaganath Kanakkassery 
22404d94f95dSJaganath Kanakkassery 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_EXT_CREATE_CONN);
22414d94f95dSJaganath Kanakkassery 	if (!cp)
22424d94f95dSJaganath Kanakkassery 		return;
22434d94f95dSJaganath Kanakkassery 
22444d94f95dSJaganath Kanakkassery 	hci_dev_lock(hdev);
22454d94f95dSJaganath Kanakkassery 
22464d94f95dSJaganath Kanakkassery 	cs_le_create_conn(hdev, &cp->peer_addr, cp->peer_addr_type,
22474d94f95dSJaganath Kanakkassery 			  cp->own_addr_type, cp->filter_policy);
22484d94f95dSJaganath Kanakkassery 
22494d94f95dSJaganath Kanakkassery 	hci_dev_unlock(hdev);
22504d94f95dSJaganath Kanakkassery }
22514d94f95dSJaganath Kanakkassery 
22520fe29fd1SMarcel Holtmann static void hci_cs_le_read_remote_features(struct hci_dev *hdev, u8 status)
22530fe29fd1SMarcel Holtmann {
22540fe29fd1SMarcel Holtmann 	struct hci_cp_le_read_remote_features *cp;
22550fe29fd1SMarcel Holtmann 	struct hci_conn *conn;
22560fe29fd1SMarcel Holtmann 
22570fe29fd1SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
22580fe29fd1SMarcel Holtmann 
22590fe29fd1SMarcel Holtmann 	if (!status)
22600fe29fd1SMarcel Holtmann 		return;
22610fe29fd1SMarcel Holtmann 
22620fe29fd1SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_READ_REMOTE_FEATURES);
22630fe29fd1SMarcel Holtmann 	if (!cp)
22640fe29fd1SMarcel Holtmann 		return;
22650fe29fd1SMarcel Holtmann 
22660fe29fd1SMarcel Holtmann 	hci_dev_lock(hdev);
22670fe29fd1SMarcel Holtmann 
22680fe29fd1SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
22690fe29fd1SMarcel Holtmann 	if (conn) {
22700fe29fd1SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
22710fe29fd1SMarcel Holtmann 			hci_connect_cfm(conn, status);
22720fe29fd1SMarcel Holtmann 			hci_conn_drop(conn);
22730fe29fd1SMarcel Holtmann 		}
22740fe29fd1SMarcel Holtmann 	}
22750fe29fd1SMarcel Holtmann 
22760fe29fd1SMarcel Holtmann 	hci_dev_unlock(hdev);
22770fe29fd1SMarcel Holtmann }
22780fe29fd1SMarcel Holtmann 
227981d0c8adSJohan Hedberg static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
228081d0c8adSJohan Hedberg {
228181d0c8adSJohan Hedberg 	struct hci_cp_le_start_enc *cp;
228281d0c8adSJohan Hedberg 	struct hci_conn *conn;
228381d0c8adSJohan Hedberg 
228481d0c8adSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
228581d0c8adSJohan Hedberg 
228681d0c8adSJohan Hedberg 	if (!status)
228781d0c8adSJohan Hedberg 		return;
228881d0c8adSJohan Hedberg 
228981d0c8adSJohan Hedberg 	hci_dev_lock(hdev);
229081d0c8adSJohan Hedberg 
229181d0c8adSJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC);
229281d0c8adSJohan Hedberg 	if (!cp)
229381d0c8adSJohan Hedberg 		goto unlock;
229481d0c8adSJohan Hedberg 
229581d0c8adSJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
229681d0c8adSJohan Hedberg 	if (!conn)
229781d0c8adSJohan Hedberg 		goto unlock;
229881d0c8adSJohan Hedberg 
229981d0c8adSJohan Hedberg 	if (conn->state != BT_CONNECTED)
230081d0c8adSJohan Hedberg 		goto unlock;
230181d0c8adSJohan Hedberg 
230281d0c8adSJohan Hedberg 	hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
230381d0c8adSJohan Hedberg 	hci_conn_drop(conn);
230481d0c8adSJohan Hedberg 
230581d0c8adSJohan Hedberg unlock:
230681d0c8adSJohan Hedberg 	hci_dev_unlock(hdev);
230781d0c8adSJohan Hedberg }
230881d0c8adSJohan Hedberg 
230950fc85f1SKuba Pawlak static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
231050fc85f1SKuba Pawlak {
231150fc85f1SKuba Pawlak 	struct hci_cp_switch_role *cp;
231250fc85f1SKuba Pawlak 	struct hci_conn *conn;
231350fc85f1SKuba Pawlak 
231450fc85f1SKuba Pawlak 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
231550fc85f1SKuba Pawlak 
231650fc85f1SKuba Pawlak 	if (!status)
231750fc85f1SKuba Pawlak 		return;
231850fc85f1SKuba Pawlak 
231950fc85f1SKuba Pawlak 	cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE);
232050fc85f1SKuba Pawlak 	if (!cp)
232150fc85f1SKuba Pawlak 		return;
232250fc85f1SKuba Pawlak 
232350fc85f1SKuba Pawlak 	hci_dev_lock(hdev);
232450fc85f1SKuba Pawlak 
232550fc85f1SKuba Pawlak 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
232650fc85f1SKuba Pawlak 	if (conn)
232750fc85f1SKuba Pawlak 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
232850fc85f1SKuba Pawlak 
232950fc85f1SKuba Pawlak 	hci_dev_unlock(hdev);
233050fc85f1SKuba Pawlak }
233150fc85f1SKuba Pawlak 
23326039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
23331da177e4SLinus Torvalds {
23341da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
233530dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
233630dc78e1SJohan Hedberg 	struct inquiry_entry *e;
23371da177e4SLinus Torvalds 
23389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
23391da177e4SLinus Torvalds 
2340a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
234189352e7dSAndre Guedes 
234289352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
234389352e7dSAndre Guedes 		return;
234489352e7dSAndre Guedes 
23454e857c58SPeter Zijlstra 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
23463e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
23473e13fa1eSAndre Guedes 
2348d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
234930dc78e1SJohan Hedberg 		return;
235030dc78e1SJohan Hedberg 
235156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
235230dc78e1SJohan Hedberg 
2353343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
235430dc78e1SJohan Hedberg 		goto unlock;
235530dc78e1SJohan Hedberg 
235630dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
235707d2334aSJakub Pawlowski 		/* When BR/EDR inquiry is active and no LE scanning is in
235807d2334aSJakub Pawlowski 		 * progress, then change discovery state to indicate completion.
235907d2334aSJakub Pawlowski 		 *
236007d2334aSJakub Pawlowski 		 * When running LE scanning and BR/EDR inquiry simultaneously
236107d2334aSJakub Pawlowski 		 * and the LE scan already finished, then change the discovery
236207d2334aSJakub Pawlowski 		 * state to indicate completion.
236307d2334aSJakub Pawlowski 		 */
236407d2334aSJakub Pawlowski 		if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
236507d2334aSJakub Pawlowski 		    !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
2366ff9ef578SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
236730dc78e1SJohan Hedberg 		goto unlock;
236830dc78e1SJohan Hedberg 	}
236930dc78e1SJohan Hedberg 
237030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
237130dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
237230dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
237330dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
237430dc78e1SJohan Hedberg 	} else {
237507d2334aSJakub Pawlowski 		/* When BR/EDR inquiry is active and no LE scanning is in
237607d2334aSJakub Pawlowski 		 * progress, then change discovery state to indicate completion.
237707d2334aSJakub Pawlowski 		 *
237807d2334aSJakub Pawlowski 		 * When running LE scanning and BR/EDR inquiry simultaneously
237907d2334aSJakub Pawlowski 		 * and the LE scan already finished, then change the discovery
238007d2334aSJakub Pawlowski 		 * state to indicate completion.
238107d2334aSJakub Pawlowski 		 */
238207d2334aSJakub Pawlowski 		if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
238307d2334aSJakub Pawlowski 		    !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
238430dc78e1SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
238530dc78e1SJohan Hedberg 	}
238630dc78e1SJohan Hedberg 
238730dc78e1SJohan Hedberg unlock:
238856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
23891da177e4SLinus Torvalds }
23901da177e4SLinus Torvalds 
23916039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
23921da177e4SLinus Torvalds {
239345bb4bf0SMarcel Holtmann 	struct inquiry_data data;
2394a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
23951da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
23961da177e4SLinus Torvalds 
23971da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
23981da177e4SLinus Torvalds 
239945bb4bf0SMarcel Holtmann 	if (!num_rsp)
240045bb4bf0SMarcel Holtmann 		return;
240145bb4bf0SMarcel Holtmann 
2402d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
24031519cc17SAndre Guedes 		return;
24041519cc17SAndre Guedes 
24051da177e4SLinus Torvalds 	hci_dev_lock(hdev);
240645bb4bf0SMarcel Holtmann 
2407e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2408af58925cSMarcel Holtmann 		u32 flags;
24093175405bSJohan Hedberg 
24101da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
24111da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
24121da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
24131da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
24141da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
24151da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
2416efb2513fSMarcel Holtmann 		data.rssi		= HCI_RSSI_INVALID;
241741a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
24183175405bSJohan Hedberg 
2419af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, false);
2420af58925cSMarcel Holtmann 
242148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2422efb2513fSMarcel Holtmann 				  info->dev_class, HCI_RSSI_INVALID,
2423efb2513fSMarcel Holtmann 				  flags, NULL, 0, NULL, 0);
24241da177e4SLinus Torvalds 	}
242545bb4bf0SMarcel Holtmann 
24261da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
24271da177e4SLinus Torvalds }
24281da177e4SLinus Torvalds 
24296039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
24301da177e4SLinus Torvalds {
2431a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
2432a9de9248SMarcel Holtmann 	struct hci_conn *conn;
24331da177e4SLinus Torvalds 
2434a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
243545bb4bf0SMarcel Holtmann 
24361da177e4SLinus Torvalds 	hci_dev_lock(hdev);
243745bb4bf0SMarcel Holtmann 
2438a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
24399499237aSMarcel Holtmann 	if (!conn) {
24409499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
24419499237aSMarcel Holtmann 			goto unlock;
24429499237aSMarcel Holtmann 
24439499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2444a9de9248SMarcel Holtmann 		if (!conn)
2445a9de9248SMarcel Holtmann 			goto unlock;
244645bb4bf0SMarcel Holtmann 
24479499237aSMarcel Holtmann 		conn->type = SCO_LINK;
24489499237aSMarcel Holtmann 	}
24499499237aSMarcel Holtmann 
2450a9de9248SMarcel Holtmann 	if (!ev->status) {
2451a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2452769be974SMarcel Holtmann 
2453769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2454769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
2455769be974SMarcel Holtmann 			hci_conn_hold(conn);
2456a9ea3ed9SSzymon Janc 
2457a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
2458a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
2459a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2460a9ea3ed9SSzymon Janc 			else
2461052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2462769be974SMarcel Holtmann 		} else
2463a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
2464a9de9248SMarcel Holtmann 
246523b9ceb7SMarcel Holtmann 		hci_debugfs_create_conn(conn);
24667d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
24677d0db0a3SMarcel Holtmann 
2468a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
24694dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2470a9de9248SMarcel Holtmann 
2471a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
24724dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2473a9de9248SMarcel Holtmann 
2474a9de9248SMarcel Holtmann 		/* Get remote features */
2475a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2476a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
2477a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2478769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
2479769be974SMarcel Holtmann 				     sizeof(cp), &cp);
248022f433dcSJohan Hedberg 
248101b1cb87SJohan Hedberg 			hci_req_update_scan(hdev);
248245bb4bf0SMarcel Holtmann 		}
2483a9de9248SMarcel Holtmann 
2484a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
2485d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
2486a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
2487a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2488a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
248904124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
249004124681SGustavo F. Padovan 				     &cp);
2491a9de9248SMarcel Holtmann 		}
249217d5c04cSJohan Hedberg 	} else {
2493a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
249417d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
249564c7b77cSMarcel Holtmann 			mgmt_connect_failed(hdev, &conn->dst, conn->type,
249648264f06SJohan Hedberg 					    conn->dst_type, ev->status);
249717d5c04cSJohan Hedberg 	}
249845bb4bf0SMarcel Holtmann 
2499e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
2500e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
250145bb4bf0SMarcel Holtmann 
2502769be974SMarcel Holtmann 	if (ev->status) {
2503539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
2504a9de9248SMarcel Holtmann 		hci_conn_del(conn);
2505c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
2506539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
2507a9de9248SMarcel Holtmann 
2508a9de9248SMarcel Holtmann unlock:
25091da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
2510a9de9248SMarcel Holtmann 
2511a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
25121da177e4SLinus Torvalds }
25131da177e4SLinus Torvalds 
251470c46425SJohan Hedberg static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr)
251570c46425SJohan Hedberg {
251670c46425SJohan Hedberg 	struct hci_cp_reject_conn_req cp;
251770c46425SJohan Hedberg 
251870c46425SJohan Hedberg 	bacpy(&cp.bdaddr, bdaddr);
251970c46425SJohan Hedberg 	cp.reason = HCI_ERROR_REJ_BAD_ADDR;
252070c46425SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
252170c46425SJohan Hedberg }
252270c46425SJohan Hedberg 
25236039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25241da177e4SLinus Torvalds {
2525a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
25261da177e4SLinus Torvalds 	int mask = hdev->link_mode;
252770c46425SJohan Hedberg 	struct inquiry_entry *ie;
252870c46425SJohan Hedberg 	struct hci_conn *conn;
252920714bfeSFrédéric Dalleau 	__u8 flags = 0;
25301da177e4SLinus Torvalds 
25316ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
2532807deac2SGustavo Padovan 	       ev->link_type);
25331da177e4SLinus Torvalds 
253420714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
253520714bfeSFrédéric Dalleau 				      &flags);
25361da177e4SLinus Torvalds 
253770c46425SJohan Hedberg 	if (!(mask & HCI_LM_ACCEPT)) {
253870c46425SJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
253970c46425SJohan Hedberg 		return;
254070c46425SJohan Hedberg 	}
254170c46425SJohan Hedberg 
2542a55bd29dSJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr,
2543dcc36c16SJohan Hedberg 				   BDADDR_BREDR)) {
254470c46425SJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
254570c46425SJohan Hedberg 		return;
254670c46425SJohan Hedberg 	}
254746c4c941SJohan Hedberg 
25486a8fc95cSJohan Hedberg 	/* Require HCI_CONNECTABLE or a whitelist entry to accept the
25496a8fc95cSJohan Hedberg 	 * connection. These features are only touched through mgmt so
25506a8fc95cSJohan Hedberg 	 * only do the checks if HCI_MGMT is set.
25516a8fc95cSJohan Hedberg 	 */
2552d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT) &&
2553d7a5a11dSMarcel Holtmann 	    !hci_dev_test_flag(hdev, HCI_CONNECTABLE) &&
255446c4c941SJohan Hedberg 	    !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr,
2555a55bd29dSJohan Hedberg 				    BDADDR_BREDR)) {
2556a55bd29dSJohan Hedberg 		    hci_reject_conn(hdev, &ev->bdaddr);
2557a55bd29dSJohan Hedberg 		    return;
2558a55bd29dSJohan Hedberg 	}
255970c46425SJohan Hedberg 
25601da177e4SLinus Torvalds 	/* Connection accepted */
25611da177e4SLinus Torvalds 
25621da177e4SLinus Torvalds 	hci_dev_lock(hdev);
2563b6a0dc82SMarcel Holtmann 
2564cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2565cc11b9c1SAndrei Emeltchenko 	if (ie)
2566c7bdd502SMarcel Holtmann 		memcpy(ie->data.dev_class, ev->dev_class, 3);
2567c7bdd502SMarcel Holtmann 
25688fc9ced3SGustavo Padovan 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
25698fc9ced3SGustavo Padovan 			&ev->bdaddr);
25701da177e4SLinus Torvalds 	if (!conn) {
2571a5c4e309SJohan Hedberg 		conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
2572a5c4e309SJohan Hedberg 				    HCI_ROLE_SLAVE);
2573cc11b9c1SAndrei Emeltchenko 		if (!conn) {
25742064ee33SMarcel Holtmann 			bt_dev_err(hdev, "no memory for new connection");
25751da177e4SLinus Torvalds 			hci_dev_unlock(hdev);
25761da177e4SLinus Torvalds 			return;
25771da177e4SLinus Torvalds 		}
25781da177e4SLinus Torvalds 	}
2579b6a0dc82SMarcel Holtmann 
25801da177e4SLinus Torvalds 	memcpy(conn->dev_class, ev->dev_class, 3);
2581b6a0dc82SMarcel Holtmann 
25821da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
25831da177e4SLinus Torvalds 
258420714bfeSFrédéric Dalleau 	if (ev->link_type == ACL_LINK ||
258520714bfeSFrédéric Dalleau 	    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
2586b6a0dc82SMarcel Holtmann 		struct hci_cp_accept_conn_req cp;
258720714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT;
2588b6a0dc82SMarcel Holtmann 
25891da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
25901da177e4SLinus Torvalds 
25911da177e4SLinus Torvalds 		if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
25921da177e4SLinus Torvalds 			cp.role = 0x00; /* Become master */
25931da177e4SLinus Torvalds 		else
25941da177e4SLinus Torvalds 			cp.role = 0x01; /* Remain slave */
25951da177e4SLinus Torvalds 
259670c46425SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
259720714bfeSFrédéric Dalleau 	} else if (!(flags & HCI_PROTO_DEFER)) {
2598b6a0dc82SMarcel Holtmann 		struct hci_cp_accept_sync_conn_req cp;
259920714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT;
2600b6a0dc82SMarcel Holtmann 
2601b6a0dc82SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
2602a8746417SMarcel Holtmann 		cp.pkt_type = cpu_to_le16(conn->pkt_type);
2603b6a0dc82SMarcel Holtmann 
2604dcf4adbfSJoe Perches 		cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
2605dcf4adbfSJoe Perches 		cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
2606dcf4adbfSJoe Perches 		cp.max_latency    = cpu_to_le16(0xffff);
2607b6a0dc82SMarcel Holtmann 		cp.content_format = cpu_to_le16(hdev->voice_setting);
2608b6a0dc82SMarcel Holtmann 		cp.retrans_effort = 0xff;
2609b6a0dc82SMarcel Holtmann 
261070c46425SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(cp),
261170c46425SJohan Hedberg 			     &cp);
261220714bfeSFrédéric Dalleau 	} else {
261320714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT2;
2614539c496dSJohan Hedberg 		hci_connect_cfm(conn, 0);
2615b6a0dc82SMarcel Holtmann 	}
26161da177e4SLinus Torvalds }
26171da177e4SLinus Torvalds 
2618f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2619f0d6a0eaSMikel Astiz {
2620f0d6a0eaSMikel Astiz 	switch (err) {
2621f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2622f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2623f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2624f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2625f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2626f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2627f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2628f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2629f0d6a0eaSMikel Astiz 	default:
2630f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2631f0d6a0eaSMikel Astiz 	}
2632f0d6a0eaSMikel Astiz }
2633f0d6a0eaSMikel Astiz 
26346039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
26351da177e4SLinus Torvalds {
2636a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
2637160b9251SSzymon Janc 	u8 reason;
26389fcb18efSAndre Guedes 	struct hci_conn_params *params;
263904837f64SMarcel Holtmann 	struct hci_conn *conn;
264012d4a3b2SJohan Hedberg 	bool mgmt_connected;
26413846220bSAndre Guedes 	u8 type;
26421da177e4SLinus Torvalds 
26439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
26441da177e4SLinus Torvalds 
26451da177e4SLinus Torvalds 	hci_dev_lock(hdev);
26461da177e4SLinus Torvalds 
264704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2648f7520543SJohan Hedberg 	if (!conn)
2649f7520543SJohan Hedberg 		goto unlock;
2650f7520543SJohan Hedberg 
2651f0d6a0eaSMikel Astiz 	if (ev->status) {
265288c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
265388c3df13SJohan Hedberg 				       conn->dst_type, ev->status);
2654abf54a50SAndre Guedes 		goto unlock;
2655abf54a50SAndre Guedes 	}
2656f0d6a0eaSMikel Astiz 
26573846220bSAndre Guedes 	conn->state = BT_CLOSED;
26583846220bSAndre Guedes 
265912d4a3b2SJohan Hedberg 	mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
2660160b9251SSzymon Janc 
2661160b9251SSzymon Janc 	if (test_bit(HCI_CONN_AUTH_FAILURE, &conn->flags))
2662160b9251SSzymon Janc 		reason = MGMT_DEV_DISCONN_AUTH_FAILURE;
2663160b9251SSzymon Janc 	else
2664160b9251SSzymon Janc 		reason = hci_to_mgmt_reason(ev->reason);
2665160b9251SSzymon Janc 
266612d4a3b2SJohan Hedberg 	mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
266712d4a3b2SJohan Hedberg 				reason, mgmt_connected);
2668f7520543SJohan Hedberg 
266922f433dcSJohan Hedberg 	if (conn->type == ACL_LINK) {
267022f433dcSJohan Hedberg 		if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
26716ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
26723846220bSAndre Guedes 
267301b1cb87SJohan Hedberg 		hci_req_update_scan(hdev);
267422f433dcSJohan Hedberg 	}
267522f433dcSJohan Hedberg 
26769fcb18efSAndre Guedes 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
26779fcb18efSAndre Guedes 	if (params) {
26789fcb18efSAndre Guedes 		switch (params->auto_connect) {
26799fcb18efSAndre Guedes 		case HCI_AUTO_CONN_LINK_LOSS:
26809fcb18efSAndre Guedes 			if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
26819fcb18efSAndre Guedes 				break;
26829fcb18efSAndre Guedes 			/* Fall through */
26839fcb18efSAndre Guedes 
26844b9e7e75SMarcel Holtmann 		case HCI_AUTO_CONN_DIRECT:
26859fcb18efSAndre Guedes 		case HCI_AUTO_CONN_ALWAYS:
2686418025d1SJohan Hedberg 			list_del_init(&params->action);
2687418025d1SJohan Hedberg 			list_add(&params->action, &hdev->pend_le_conns);
2688418025d1SJohan Hedberg 			hci_update_background_scan(hdev);
26899fcb18efSAndre Guedes 			break;
26909fcb18efSAndre Guedes 
26919fcb18efSAndre Guedes 		default:
26929fcb18efSAndre Guedes 			break;
26939fcb18efSAndre Guedes 		}
26949fcb18efSAndre Guedes 	}
26959fcb18efSAndre Guedes 
26963846220bSAndre Guedes 	type = conn->type;
26973846220bSAndre Guedes 
26983a6d576bSJohan Hedberg 	hci_disconn_cfm(conn, ev->reason);
26991da177e4SLinus Torvalds 	hci_conn_del(conn);
27002210246cSJohan Hedberg 
27012210246cSJohan Hedberg 	/* Re-enable advertising if necessary, since it might
27022210246cSJohan Hedberg 	 * have been disabled by the connection. From the
27032210246cSJohan Hedberg 	 * HCI_LE_Set_Advertise_Enable command description in
27042210246cSJohan Hedberg 	 * the core specification (v4.0):
27052210246cSJohan Hedberg 	 * "The Controller shall continue advertising until the Host
27062210246cSJohan Hedberg 	 * issues an LE_Set_Advertise_Enable command with
27072210246cSJohan Hedberg 	 * Advertising_Enable set to 0x00 (Advertising is disabled)
27082210246cSJohan Hedberg 	 * or until a connection is created or until the Advertising
27092210246cSJohan Hedberg 	 * is timed out due to Directed Advertising."
27102210246cSJohan Hedberg 	 */
27112210246cSJohan Hedberg 	if (type == LE_LINK)
2712f2252570SJohan Hedberg 		hci_req_reenable_advertising(hdev);
27131da177e4SLinus Torvalds 
2714f7520543SJohan Hedberg unlock:
27151da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27161da177e4SLinus Torvalds }
27171da177e4SLinus Torvalds 
27186039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2719a9de9248SMarcel Holtmann {
2720a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2721a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2722a9de9248SMarcel Holtmann 
27239f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2724a9de9248SMarcel Holtmann 
2725a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2726a9de9248SMarcel Holtmann 
2727a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2728d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2729d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2730d7556e20SWaldemar Rymarkiewicz 
2731765c2a96SJohan Hedberg 	if (!ev->status) {
2732160b9251SSzymon Janc 		clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
2733160b9251SSzymon Janc 
2734aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
273551a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
27362064ee33SMarcel Holtmann 			bt_dev_info(hdev, "re-auth of legacy device is not possible.");
273719f8def0SWaldemar Rymarkiewicz 		} else {
27384dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2739765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
274019f8def0SWaldemar Rymarkiewicz 		}
27412a611692SJohan Hedberg 	} else {
2742160b9251SSzymon Janc 		if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
2743160b9251SSzymon Janc 			set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
2744160b9251SSzymon Janc 
2745e1e930f5SJohan Hedberg 		mgmt_auth_failed(conn, ev->status);
27462a611692SJohan Hedberg 	}
2747a9de9248SMarcel Holtmann 
274851a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
274951a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2750a9de9248SMarcel Holtmann 
2751f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2752aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2753f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2754f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2755f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2756d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2757d7556e20SWaldemar Rymarkiewicz 				     &cp);
2758f8558555SMarcel Holtmann 		} else {
2759f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2760539c496dSJohan Hedberg 			hci_connect_cfm(conn, ev->status);
276176a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2762f8558555SMarcel Holtmann 		}
2763052b30b0SMarcel Holtmann 	} else {
2764a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2765a9de9248SMarcel Holtmann 
2766052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2767052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
276876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2769052b30b0SMarcel Holtmann 	}
2770052b30b0SMarcel Holtmann 
277151a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2772a9de9248SMarcel Holtmann 		if (!ev->status) {
2773a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2774f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2775f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2776d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2777d7556e20SWaldemar Rymarkiewicz 				     &cp);
2778a9de9248SMarcel Holtmann 		} else {
277951a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2780a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2781a9de9248SMarcel Holtmann 		}
2782a9de9248SMarcel Holtmann 	}
2783a9de9248SMarcel Holtmann 
2784d7556e20SWaldemar Rymarkiewicz unlock:
2785a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2786a9de9248SMarcel Holtmann }
2787a9de9248SMarcel Holtmann 
27886039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2789a9de9248SMarcel Holtmann {
2790127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2791127178d2SJohan Hedberg 	struct hci_conn *conn;
2792127178d2SJohan Hedberg 
2793a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2794a9de9248SMarcel Holtmann 
2795a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2796127178d2SJohan Hedberg 
2797127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2798127178d2SJohan Hedberg 
2799127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2800b644ba33SJohan Hedberg 
2801d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
2802b644ba33SJohan Hedberg 		goto check_auth;
2803b644ba33SJohan Hedberg 
2804b644ba33SJohan Hedberg 	if (ev->status == 0)
2805b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2806b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2807b644ba33SJohan Hedberg 	else
2808b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2809b644ba33SJohan Hedberg 
2810b644ba33SJohan Hedberg check_auth:
281179c6c70cSJohan Hedberg 	if (!conn)
281279c6c70cSJohan Hedberg 		goto unlock;
281379c6c70cSJohan Hedberg 
281479c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
281579c6c70cSJohan Hedberg 		goto unlock;
281679c6c70cSJohan Hedberg 
281751a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2818127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2819977f8fceSJohan Hedberg 
2820977f8fceSJohan Hedberg 		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
2821977f8fceSJohan Hedberg 
2822127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2823127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2824127178d2SJohan Hedberg 	}
2825127178d2SJohan Hedberg 
282679c6c70cSJohan Hedberg unlock:
2827127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2828a9de9248SMarcel Holtmann }
2829a9de9248SMarcel Holtmann 
2830821f3766SJohan Hedberg static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status,
2831821f3766SJohan Hedberg 				       u16 opcode, struct sk_buff *skb)
2832821f3766SJohan Hedberg {
2833821f3766SJohan Hedberg 	const struct hci_rp_read_enc_key_size *rp;
2834821f3766SJohan Hedberg 	struct hci_conn *conn;
2835821f3766SJohan Hedberg 	u16 handle;
2836821f3766SJohan Hedberg 
2837821f3766SJohan Hedberg 	BT_DBG("%s status 0x%02x", hdev->name, status);
2838821f3766SJohan Hedberg 
2839821f3766SJohan Hedberg 	if (!skb || skb->len < sizeof(*rp)) {
28402064ee33SMarcel Holtmann 		bt_dev_err(hdev, "invalid read key size response");
2841821f3766SJohan Hedberg 		return;
2842821f3766SJohan Hedberg 	}
2843821f3766SJohan Hedberg 
2844821f3766SJohan Hedberg 	rp = (void *)skb->data;
2845821f3766SJohan Hedberg 	handle = le16_to_cpu(rp->handle);
2846821f3766SJohan Hedberg 
2847821f3766SJohan Hedberg 	hci_dev_lock(hdev);
2848821f3766SJohan Hedberg 
2849821f3766SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, handle);
2850821f3766SJohan Hedberg 	if (!conn)
2851821f3766SJohan Hedberg 		goto unlock;
2852821f3766SJohan Hedberg 
2853821f3766SJohan Hedberg 	/* If we fail to read the encryption key size, assume maximum
2854821f3766SJohan Hedberg 	 * (which is the same we do also when this HCI command isn't
2855821f3766SJohan Hedberg 	 * supported.
2856821f3766SJohan Hedberg 	 */
2857821f3766SJohan Hedberg 	if (rp->status) {
28582064ee33SMarcel Holtmann 		bt_dev_err(hdev, "failed to read key size for handle %u",
2859821f3766SJohan Hedberg 			   handle);
2860821f3766SJohan Hedberg 		conn->enc_key_size = HCI_LINK_KEY_SIZE;
2861821f3766SJohan Hedberg 	} else {
2862821f3766SJohan Hedberg 		conn->enc_key_size = rp->key_size;
2863821f3766SJohan Hedberg 	}
2864821f3766SJohan Hedberg 
2865821f3766SJohan Hedberg 	if (conn->state == BT_CONFIG) {
2866821f3766SJohan Hedberg 		conn->state = BT_CONNECTED;
2867821f3766SJohan Hedberg 		hci_connect_cfm(conn, 0);
2868821f3766SJohan Hedberg 		hci_conn_drop(conn);
2869821f3766SJohan Hedberg 	} else {
2870821f3766SJohan Hedberg 		u8 encrypt;
2871821f3766SJohan Hedberg 
2872821f3766SJohan Hedberg 		if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
2873821f3766SJohan Hedberg 			encrypt = 0x00;
28745d667ef6SJohan Hedberg 		else if (test_bit(HCI_CONN_AES_CCM, &conn->flags))
2875821f3766SJohan Hedberg 			encrypt = 0x02;
2876821f3766SJohan Hedberg 		else
2877821f3766SJohan Hedberg 			encrypt = 0x01;
2878821f3766SJohan Hedberg 
2879821f3766SJohan Hedberg 		hci_encrypt_cfm(conn, 0, encrypt);
2880821f3766SJohan Hedberg 	}
2881821f3766SJohan Hedberg 
2882821f3766SJohan Hedberg unlock:
2883821f3766SJohan Hedberg 	hci_dev_unlock(hdev);
2884821f3766SJohan Hedberg }
2885821f3766SJohan Hedberg 
28866039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2887a9de9248SMarcel Holtmann {
2888a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2889a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2890a9de9248SMarcel Holtmann 
28919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2892a9de9248SMarcel Holtmann 
2893a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2894a9de9248SMarcel Holtmann 
2895a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2896dc8357ccSMarcel Holtmann 	if (!conn)
2897dc8357ccSMarcel Holtmann 		goto unlock;
2898dc8357ccSMarcel Holtmann 
2899a9de9248SMarcel Holtmann 	if (!ev->status) {
2900ae293196SMarcel Holtmann 		if (ev->encrypt) {
2901ae293196SMarcel Holtmann 			/* Encryption implies authentication */
29024dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
29034dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2904da85e5e5SVinicius Costa Gomes 			conn->sec_level = conn->pending_sec_level;
2905abf76badSMarcel Holtmann 
2906914a6ffeSMarcel Holtmann 			/* P-256 authentication key implies FIPS */
2907914a6ffeSMarcel Holtmann 			if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
29084dae2798SJohan Hedberg 				set_bit(HCI_CONN_FIPS, &conn->flags);
2909914a6ffeSMarcel Holtmann 
2910abf76badSMarcel Holtmann 			if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
2911abf76badSMarcel Holtmann 			    conn->type == LE_LINK)
2912abf76badSMarcel Holtmann 				set_bit(HCI_CONN_AES_CCM, &conn->flags);
2913abf76badSMarcel Holtmann 		} else {
29144dae2798SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
2915abf76badSMarcel Holtmann 			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
2916abf76badSMarcel Holtmann 		}
2917a9de9248SMarcel Holtmann 	}
2918a9de9248SMarcel Holtmann 
29197ed3fa20SJohan Hedberg 	/* We should disregard the current RPA and generate a new one
29207ed3fa20SJohan Hedberg 	 * whenever the encryption procedure fails.
29217ed3fa20SJohan Hedberg 	 */
2922a73c046aSJaganath Kanakkassery 	if (ev->status && conn->type == LE_LINK) {
2923a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
2924a73c046aSJaganath Kanakkassery 		hci_adv_instances_set_rpa_expired(hdev, true);
2925a73c046aSJaganath Kanakkassery 	}
29267ed3fa20SJohan Hedberg 
292751a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2928a9de9248SMarcel Holtmann 
2929a7d7723aSGustavo Padovan 	if (ev->status && conn->state == BT_CONNECTED) {
2930160b9251SSzymon Janc 		if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
2931160b9251SSzymon Janc 			set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
2932160b9251SSzymon Janc 
2933bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
293476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2935a7d7723aSGustavo Padovan 		goto unlock;
2936a7d7723aSGustavo Padovan 	}
2937a7d7723aSGustavo Padovan 
2938035ad621SJohan Hedberg 	/* In Secure Connections Only mode, do not allow any connections
2939035ad621SJohan Hedberg 	 * that are not encrypted with AES-CCM using a P-256 authenticated
2940035ad621SJohan Hedberg 	 * combination key.
294140b552aaSMarcel Holtmann 	 */
2942d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SC_ONLY) &&
294340b552aaSMarcel Holtmann 	    (!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
294440b552aaSMarcel Holtmann 	     conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) {
2945539c496dSJohan Hedberg 		hci_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE);
294640b552aaSMarcel Holtmann 		hci_conn_drop(conn);
294740b552aaSMarcel Holtmann 		goto unlock;
294840b552aaSMarcel Holtmann 	}
294940b552aaSMarcel Holtmann 
2950821f3766SJohan Hedberg 	/* Try reading the encryption key size for encrypted ACL links */
2951821f3766SJohan Hedberg 	if (!ev->status && ev->encrypt && conn->type == ACL_LINK) {
2952821f3766SJohan Hedberg 		struct hci_cp_read_enc_key_size cp;
2953821f3766SJohan Hedberg 		struct hci_request req;
2954821f3766SJohan Hedberg 
2955821f3766SJohan Hedberg 		/* Only send HCI_Read_Encryption_Key_Size if the
2956821f3766SJohan Hedberg 		 * controller really supports it. If it doesn't, assume
2957821f3766SJohan Hedberg 		 * the default size (16).
2958821f3766SJohan Hedberg 		 */
2959821f3766SJohan Hedberg 		if (!(hdev->commands[20] & 0x10)) {
2960821f3766SJohan Hedberg 			conn->enc_key_size = HCI_LINK_KEY_SIZE;
2961821f3766SJohan Hedberg 			goto notify;
2962821f3766SJohan Hedberg 		}
2963821f3766SJohan Hedberg 
2964821f3766SJohan Hedberg 		hci_req_init(&req, hdev);
2965821f3766SJohan Hedberg 
2966821f3766SJohan Hedberg 		cp.handle = cpu_to_le16(conn->handle);
2967821f3766SJohan Hedberg 		hci_req_add(&req, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp);
2968821f3766SJohan Hedberg 
2969821f3766SJohan Hedberg 		if (hci_req_run_skb(&req, read_enc_key_size_complete)) {
29702064ee33SMarcel Holtmann 			bt_dev_err(hdev, "sending read key size failed");
2971821f3766SJohan Hedberg 			conn->enc_key_size = HCI_LINK_KEY_SIZE;
2972821f3766SJohan Hedberg 			goto notify;
2973821f3766SJohan Hedberg 		}
2974821f3766SJohan Hedberg 
2975821f3766SJohan Hedberg 		goto unlock;
2976821f3766SJohan Hedberg 	}
2977821f3766SJohan Hedberg 
2978821f3766SJohan Hedberg notify:
2979035ad621SJohan Hedberg 	if (conn->state == BT_CONFIG) {
2980035ad621SJohan Hedberg 		if (!ev->status)
2981035ad621SJohan Hedberg 			conn->state = BT_CONNECTED;
2982035ad621SJohan Hedberg 
2983539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
298476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2985f8558555SMarcel Holtmann 	} else
2986a9de9248SMarcel Holtmann 		hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2987a9de9248SMarcel Holtmann 
2988a7d7723aSGustavo Padovan unlock:
2989a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2990a9de9248SMarcel Holtmann }
2991a9de9248SMarcel Holtmann 
29926039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2993807deac2SGustavo Padovan 					     struct sk_buff *skb)
2994a9de9248SMarcel Holtmann {
2995a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2996a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2997a9de9248SMarcel Holtmann 
29989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2999a9de9248SMarcel Holtmann 
3000a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3001a9de9248SMarcel Holtmann 
3002a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3003a9de9248SMarcel Holtmann 	if (conn) {
3004a9de9248SMarcel Holtmann 		if (!ev->status)
30054dae2798SJohan Hedberg 			set_bit(HCI_CONN_SECURE, &conn->flags);
3006a9de9248SMarcel Holtmann 
300751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
3008a9de9248SMarcel Holtmann 
3009a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
3010a9de9248SMarcel Holtmann 	}
3011a9de9248SMarcel Holtmann 
3012a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3013a9de9248SMarcel Holtmann }
3014a9de9248SMarcel Holtmann 
30156039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
3016807deac2SGustavo Padovan 				    struct sk_buff *skb)
3017a9de9248SMarcel Holtmann {
3018a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
3019a9de9248SMarcel Holtmann 	struct hci_conn *conn;
3020a9de9248SMarcel Holtmann 
30219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3022a9de9248SMarcel Holtmann 
3023a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3024a9de9248SMarcel Holtmann 
3025a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3026ccd556feSJohan Hedberg 	if (!conn)
3027ccd556feSJohan Hedberg 		goto unlock;
3028ccd556feSJohan Hedberg 
3029769be974SMarcel Holtmann 	if (!ev->status)
3030cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
3031a9de9248SMarcel Holtmann 
3032ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3033ccd556feSJohan Hedberg 		goto unlock;
3034ccd556feSJohan Hedberg 
3035ac363cf9SSzymon Janc 	if (!ev->status && lmp_ext_feat_capable(hdev) &&
3036ac363cf9SSzymon Janc 	    lmp_ext_feat_capable(conn)) {
3037769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
3038769be974SMarcel Holtmann 		cp.handle = ev->handle;
3039769be974SMarcel Holtmann 		cp.page = 0x01;
3040ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
3041769be974SMarcel Holtmann 			     sizeof(cp), &cp);
3042392599b9SJohan Hedberg 		goto unlock;
3043392599b9SJohan Hedberg 	}
3044392599b9SJohan Hedberg 
3045671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3046127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3047127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3048127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3049127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3050127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3051b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
305248ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
3053392599b9SJohan Hedberg 
3054127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3055769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3056539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
305776a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3058769be974SMarcel Holtmann 	}
3059769be974SMarcel Holtmann 
3060ccd556feSJohan Hedberg unlock:
3061a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3062a9de9248SMarcel Holtmann }
3063a9de9248SMarcel Holtmann 
3064e6214487SJohan Hedberg static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
3065e6214487SJohan Hedberg 				 u16 *opcode, u8 *status,
3066e6214487SJohan Hedberg 				 hci_req_complete_t *req_complete,
3067e6214487SJohan Hedberg 				 hci_req_complete_skb_t *req_complete_skb)
3068a9de9248SMarcel Holtmann {
3069a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
3070e6214487SJohan Hedberg 
3071e6214487SJohan Hedberg 	*opcode = __le16_to_cpu(ev->opcode);
3072e6214487SJohan Hedberg 	*status = skb->data[sizeof(*ev)];
3073a9de9248SMarcel Holtmann 
3074a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
3075a9de9248SMarcel Holtmann 
3076e6214487SJohan Hedberg 	switch (*opcode) {
3077a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
3078a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
3079a9de9248SMarcel Holtmann 		break;
3080a9de9248SMarcel Holtmann 
30814d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
30824d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
30834d93483bSAndre Guedes 		break;
30844d93483bSAndre Guedes 
3085a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
3086a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
3087a9de9248SMarcel Holtmann 		break;
3088a9de9248SMarcel Holtmann 
3089a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
3090a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
3091a9de9248SMarcel Holtmann 		break;
3092a9de9248SMarcel Holtmann 
3093a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
3094a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
3095a9de9248SMarcel Holtmann 		break;
3096a9de9248SMarcel Holtmann 
3097e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
3098e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
3099e4e8e37cSMarcel Holtmann 		break;
3100e4e8e37cSMarcel Holtmann 
3101a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
3102a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
3103a9de9248SMarcel Holtmann 		break;
3104a9de9248SMarcel Holtmann 
3105e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
3106e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
3107e4e8e37cSMarcel Holtmann 		break;
3108e4e8e37cSMarcel Holtmann 
3109e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
3110e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
3111e4e8e37cSMarcel Holtmann 		break;
3112e4e8e37cSMarcel Holtmann 
3113a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
3114a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
3115a9de9248SMarcel Holtmann 		break;
3116a9de9248SMarcel Holtmann 
3117c2f0f979SMarcel Holtmann 	case HCI_OP_READ_STORED_LINK_KEY:
3118c2f0f979SMarcel Holtmann 		hci_cc_read_stored_link_key(hdev, skb);
3119c2f0f979SMarcel Holtmann 		break;
3120c2f0f979SMarcel Holtmann 
3121a9366120SMarcel Holtmann 	case HCI_OP_DELETE_STORED_LINK_KEY:
3122a9366120SMarcel Holtmann 		hci_cc_delete_stored_link_key(hdev, skb);
3123a9366120SMarcel Holtmann 		break;
3124a9366120SMarcel Holtmann 
3125a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
3126a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
3127a9de9248SMarcel Holtmann 		break;
3128a9de9248SMarcel Holtmann 
3129a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
3130a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
3131a9de9248SMarcel Holtmann 		break;
3132a9de9248SMarcel Holtmann 
3133a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
3134a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
3135a9de9248SMarcel Holtmann 		break;
3136a9de9248SMarcel Holtmann 
3137a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
3138a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
3139a9de9248SMarcel Holtmann 		break;
3140a9de9248SMarcel Holtmann 
3141a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
3142a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
3143a9de9248SMarcel Holtmann 		break;
3144a9de9248SMarcel Holtmann 
3145a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
3146a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
3147a9de9248SMarcel Holtmann 		break;
3148a9de9248SMarcel Holtmann 
3149a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
3150a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
3151a9de9248SMarcel Holtmann 		break;
3152a9de9248SMarcel Holtmann 
3153a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
3154a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
3155a9de9248SMarcel Holtmann 		break;
3156a9de9248SMarcel Holtmann 
3157a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
3158a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
3159a9de9248SMarcel Holtmann 		break;
3160a9de9248SMarcel Holtmann 
3161b4cb9fb2SMarcel Holtmann 	case HCI_OP_READ_NUM_SUPPORTED_IAC:
3162b4cb9fb2SMarcel Holtmann 		hci_cc_read_num_supported_iac(hdev, skb);
3163b4cb9fb2SMarcel Holtmann 		break;
3164b4cb9fb2SMarcel Holtmann 
3165333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
3166333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
3167333140b5SMarcel Holtmann 		break;
3168333140b5SMarcel Holtmann 
3169eac83dc6SMarcel Holtmann 	case HCI_OP_WRITE_SC_SUPPORT:
3170eac83dc6SMarcel Holtmann 		hci_cc_write_sc_support(hdev, skb);
3171eac83dc6SMarcel Holtmann 		break;
3172eac83dc6SMarcel Holtmann 
3173a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
3174a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
3175a9de9248SMarcel Holtmann 		break;
3176a9de9248SMarcel Holtmann 
3177a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
3178a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
3179a9de9248SMarcel Holtmann 		break;
3180a9de9248SMarcel Holtmann 
3181a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
3182a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
3183a9de9248SMarcel Holtmann 		break;
3184a9de9248SMarcel Holtmann 
3185971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
3186971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
3187971e3a4bSAndre Guedes 		break;
3188971e3a4bSAndre Guedes 
3189a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
3190a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
3191a9de9248SMarcel Holtmann 		break;
3192a9de9248SMarcel Holtmann 
3193a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
3194a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
3195a9de9248SMarcel Holtmann 		break;
3196a9de9248SMarcel Holtmann 
3197f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
3198f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
3199f332ec66SJohan Hedberg 		break;
3200f332ec66SJohan Hedberg 
32014a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
32024a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
32034a3ee763SJohan Hedberg 		break;
32044a3ee763SJohan Hedberg 
3205f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
3206f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
3207f332ec66SJohan Hedberg 		break;
3208f332ec66SJohan Hedberg 
32094a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
32104a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
32114a3ee763SJohan Hedberg 		break;
32124a3ee763SJohan Hedberg 
3213350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
3214350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
3215350ee4cfSAndrei Emeltchenko 		break;
3216350ee4cfSAndrei Emeltchenko 
32171e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
32181e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
32191e89cffbSAndrei Emeltchenko 		break;
32201e89cffbSAndrei Emeltchenko 
3221928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
3222928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
3223928abaa7SAndrei Emeltchenko 		break;
3224928abaa7SAndrei Emeltchenko 
322533f35721SJohan Hedberg 	case HCI_OP_READ_CLOCK:
322633f35721SJohan Hedberg 		hci_cc_read_clock(hdev, skb);
322733f35721SJohan Hedberg 		break;
322833f35721SJohan Hedberg 
3229d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
3230d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
3231d5859e22SJohan Hedberg 		break;
3232d5859e22SJohan Hedberg 
3233980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
3234980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
3235980e1a53SJohan Hedberg 		break;
3236980e1a53SJohan Hedberg 
3237980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
3238980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
3239980e1a53SJohan Hedberg 		break;
3240980e1a53SJohan Hedberg 
3241c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
32424d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_data(hdev, skb);
32434d2d2796SMarcel Holtmann 		break;
32444d2d2796SMarcel Holtmann 
32454d2d2796SMarcel Holtmann 	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
32464d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_ext_data(hdev, skb);
3247c35938b2SSzymon Janc 		break;
3248c35938b2SSzymon Janc 
32496ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
32506ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
32516ed58ec5SVille Tervo 		break;
32526ed58ec5SVille Tervo 
325360e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
325460e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
325560e77321SJohan Hedberg 		break;
325660e77321SJohan Hedberg 
32578fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
32588fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
32598fa19098SJohan Hedberg 		break;
32608fa19098SJohan Hedberg 
3261a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
3262a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
3263a5c29683SJohan Hedberg 		break;
3264a5c29683SJohan Hedberg 
3265a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
3266a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
3267a5c29683SJohan Hedberg 		break;
3268a5c29683SJohan Hedberg 
32691143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
32701143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
32711143d458SBrian Gix 		break;
32721143d458SBrian Gix 
32731143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
32741143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
327516cde993SSzymon Janc 		break;
327607f7fa5dSAndre Guedes 
32777a4cd51dSMarcel Holtmann 	case HCI_OP_LE_SET_RANDOM_ADDR:
32787a4cd51dSMarcel Holtmann 		hci_cc_le_set_random_addr(hdev, skb);
32797a4cd51dSMarcel Holtmann 		break;
32807a4cd51dSMarcel Holtmann 
3281c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
3282c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
3283c1d5dc4aSJohan Hedberg 		break;
3284c1d5dc4aSJohan Hedberg 
3285533553f8SMarcel Holtmann 	case HCI_OP_LE_SET_SCAN_PARAM:
3286533553f8SMarcel Holtmann 		hci_cc_le_set_scan_param(hdev, skb);
3287533553f8SMarcel Holtmann 		break;
3288533553f8SMarcel Holtmann 
3289eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
3290eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
3291eb9d91f5SAndre Guedes 		break;
3292eb9d91f5SAndre Guedes 
3293cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
3294cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
3295cf1d081fSJohan Hedberg 		break;
3296cf1d081fSJohan Hedberg 
32970f36b589SMarcel Holtmann 	case HCI_OP_LE_CLEAR_WHITE_LIST:
32980f36b589SMarcel Holtmann 		hci_cc_le_clear_white_list(hdev, skb);
32990f36b589SMarcel Holtmann 		break;
33000f36b589SMarcel Holtmann 
33010f36b589SMarcel Holtmann 	case HCI_OP_LE_ADD_TO_WHITE_LIST:
33020f36b589SMarcel Holtmann 		hci_cc_le_add_to_white_list(hdev, skb);
33030f36b589SMarcel Holtmann 		break;
33040f36b589SMarcel Holtmann 
33050f36b589SMarcel Holtmann 	case HCI_OP_LE_DEL_FROM_WHITE_LIST:
33060f36b589SMarcel Holtmann 		hci_cc_le_del_from_white_list(hdev, skb);
33070f36b589SMarcel Holtmann 		break;
33080f36b589SMarcel Holtmann 
33099b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
33109b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
33119b008c04SJohan Hedberg 		break;
33129b008c04SJohan Hedberg 
3313a8e1bfaaSMarcel Holtmann 	case HCI_OP_LE_READ_DEF_DATA_LEN:
3314a8e1bfaaSMarcel Holtmann 		hci_cc_le_read_def_data_len(hdev, skb);
3315a8e1bfaaSMarcel Holtmann 		break;
3316a8e1bfaaSMarcel Holtmann 
3317a8e1bfaaSMarcel Holtmann 	case HCI_OP_LE_WRITE_DEF_DATA_LEN:
3318a8e1bfaaSMarcel Holtmann 		hci_cc_le_write_def_data_len(hdev, skb);
3319a8e1bfaaSMarcel Holtmann 		break;
3320a8e1bfaaSMarcel Holtmann 
3321b950aa88SAnkit Navik 	case HCI_OP_LE_ADD_TO_RESOLV_LIST:
3322b950aa88SAnkit Navik 		hci_cc_le_add_to_resolv_list(hdev, skb);
3323b950aa88SAnkit Navik 		break;
3324b950aa88SAnkit Navik 
3325b950aa88SAnkit Navik 	case HCI_OP_LE_DEL_FROM_RESOLV_LIST:
3326b950aa88SAnkit Navik 		hci_cc_le_del_from_resolv_list(hdev, skb);
3327b950aa88SAnkit Navik 		break;
3328b950aa88SAnkit Navik 
3329545f2596SAnkit Navik 	case HCI_OP_LE_CLEAR_RESOLV_LIST:
3330545f2596SAnkit Navik 		hci_cc_le_clear_resolv_list(hdev, skb);
3331545f2596SAnkit Navik 		break;
3332545f2596SAnkit Navik 
3333cfdb0c2dSAnkit Navik 	case HCI_OP_LE_READ_RESOLV_LIST_SIZE:
3334cfdb0c2dSAnkit Navik 		hci_cc_le_read_resolv_list_size(hdev, skb);
3335cfdb0c2dSAnkit Navik 		break;
3336cfdb0c2dSAnkit Navik 
3337aa12af77SAnkit Navik 	case HCI_OP_LE_SET_ADDR_RESOLV_ENABLE:
3338aa12af77SAnkit Navik 		hci_cc_le_set_addr_resolution_enable(hdev, skb);
3339aa12af77SAnkit Navik 		break;
3340aa12af77SAnkit Navik 
3341a8e1bfaaSMarcel Holtmann 	case HCI_OP_LE_READ_MAX_DATA_LEN:
3342a8e1bfaaSMarcel Holtmann 		hci_cc_le_read_max_data_len(hdev, skb);
3343a8e1bfaaSMarcel Holtmann 		break;
3344a8e1bfaaSMarcel Holtmann 
3345f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
3346f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
3347f9b49306SAndre Guedes 		break;
3348f9b49306SAndre Guedes 
334956ed2cb8SJohan Hedberg 	case HCI_OP_LE_SET_ADV_PARAM:
335056ed2cb8SJohan Hedberg 		hci_cc_set_adv_param(hdev, skb);
335156ed2cb8SJohan Hedberg 		break;
335256ed2cb8SJohan Hedberg 
33535ae76a94SAndrzej Kaczmarek 	case HCI_OP_READ_RSSI:
33545ae76a94SAndrzej Kaczmarek 		hci_cc_read_rssi(hdev, skb);
33555ae76a94SAndrzej Kaczmarek 		break;
33565ae76a94SAndrzej Kaczmarek 
33575a134faeSAndrzej Kaczmarek 	case HCI_OP_READ_TX_POWER:
33585a134faeSAndrzej Kaczmarek 		hci_cc_read_tx_power(hdev, skb);
33595a134faeSAndrzej Kaczmarek 		break;
33605a134faeSAndrzej Kaczmarek 
3361c50b33c8SMarcel Holtmann 	case HCI_OP_WRITE_SSP_DEBUG_MODE:
3362c50b33c8SMarcel Holtmann 		hci_cc_write_ssp_debug_mode(hdev, skb);
3363c50b33c8SMarcel Holtmann 		break;
3364c50b33c8SMarcel Holtmann 
3365a2344b9eSJaganath Kanakkassery 	case HCI_OP_LE_SET_EXT_SCAN_PARAMS:
3366a2344b9eSJaganath Kanakkassery 		hci_cc_le_set_ext_scan_param(hdev, skb);
3367a2344b9eSJaganath Kanakkassery 		break;
3368a2344b9eSJaganath Kanakkassery 
3369a2344b9eSJaganath Kanakkassery 	case HCI_OP_LE_SET_EXT_SCAN_ENABLE:
3370a2344b9eSJaganath Kanakkassery 		hci_cc_le_set_ext_scan_enable(hdev, skb);
3371a2344b9eSJaganath Kanakkassery 		break;
3372a2344b9eSJaganath Kanakkassery 
33730314f286SJaganath Kanakkassery 	case HCI_OP_LE_SET_DEFAULT_PHY:
33740314f286SJaganath Kanakkassery 		hci_cc_le_set_default_phy(hdev, skb);
33750314f286SJaganath Kanakkassery 		break;
33760314f286SJaganath Kanakkassery 
33776b49bcb4SJaganath Kanakkassery 	case HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS:
33786b49bcb4SJaganath Kanakkassery 		hci_cc_le_read_num_adv_sets(hdev, skb);
33796b49bcb4SJaganath Kanakkassery 		break;
33806b49bcb4SJaganath Kanakkassery 
3381de181e88SJaganath Kanakkassery 	case HCI_OP_LE_SET_EXT_ADV_PARAMS:
3382de181e88SJaganath Kanakkassery 		hci_cc_set_ext_adv_param(hdev, skb);
3383de181e88SJaganath Kanakkassery 		break;
3384de181e88SJaganath Kanakkassery 
3385de181e88SJaganath Kanakkassery 	case HCI_OP_LE_SET_EXT_ADV_ENABLE:
3386de181e88SJaganath Kanakkassery 		hci_cc_le_set_ext_adv_enable(hdev, skb);
3387de181e88SJaganath Kanakkassery 		break;
3388de181e88SJaganath Kanakkassery 
3389a73c046aSJaganath Kanakkassery 	case HCI_OP_LE_SET_ADV_SET_RAND_ADDR:
3390a73c046aSJaganath Kanakkassery 		hci_cc_le_set_adv_set_random_addr(hdev, skb);
3391a73c046aSJaganath Kanakkassery 		break;
3392a73c046aSJaganath Kanakkassery 
3393a9de9248SMarcel Holtmann 	default:
3394e6214487SJohan Hedberg 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
3395a9de9248SMarcel Holtmann 		break;
3396a9de9248SMarcel Holtmann 	}
3397a9de9248SMarcel Holtmann 
3398e6214487SJohan Hedberg 	if (*opcode != HCI_OP_NOP)
339965cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
34006bd32326SVille Tervo 
3401600b2150SJohan Hedberg 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags))
3402600b2150SJohan Hedberg 		atomic_set(&hdev->cmd_cnt, 1);
3403600b2150SJohan Hedberg 
3404e6214487SJohan Hedberg 	hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
3405e6214487SJohan Hedberg 			     req_complete_skb);
34069238f36aSJohan Hedberg 
3407600b2150SJohan Hedberg 	if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
3408c347b765SGustavo F. Padovan 		queue_work(hdev->workqueue, &hdev->cmd_work);
3409a9de9248SMarcel Holtmann }
3410a9de9248SMarcel Holtmann 
3411e6214487SJohan Hedberg static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
3412e6214487SJohan Hedberg 			       u16 *opcode, u8 *status,
3413e6214487SJohan Hedberg 			       hci_req_complete_t *req_complete,
3414e6214487SJohan Hedberg 			       hci_req_complete_skb_t *req_complete_skb)
3415a9de9248SMarcel Holtmann {
3416a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
3417a9de9248SMarcel Holtmann 
3418a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
3419a9de9248SMarcel Holtmann 
3420e6214487SJohan Hedberg 	*opcode = __le16_to_cpu(ev->opcode);
3421e6214487SJohan Hedberg 	*status = ev->status;
3422a9de9248SMarcel Holtmann 
3423e6214487SJohan Hedberg 	switch (*opcode) {
3424a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
3425a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
3426a9de9248SMarcel Holtmann 		break;
3427a9de9248SMarcel Holtmann 
3428a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
3429a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
3430a9de9248SMarcel Holtmann 		break;
3431a9de9248SMarcel Holtmann 
34329645c76cSKuba Pawlak 	case HCI_OP_DISCONNECT:
34339645c76cSKuba Pawlak 		hci_cs_disconnect(hdev, ev->status);
34349645c76cSKuba Pawlak 		break;
34359645c76cSKuba Pawlak 
3436a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
3437a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
3438a9de9248SMarcel Holtmann 		break;
3439a9de9248SMarcel Holtmann 
3440f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
3441f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
3442f8558555SMarcel Holtmann 		break;
3443f8558555SMarcel Holtmann 
3444f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
3445f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
3446f8558555SMarcel Holtmann 		break;
3447f8558555SMarcel Holtmann 
3448a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
3449a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
3450a9de9248SMarcel Holtmann 		break;
3451a9de9248SMarcel Holtmann 
3452769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
3453769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
3454769be974SMarcel Holtmann 		break;
3455769be974SMarcel Holtmann 
3456769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
3457769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
3458769be974SMarcel Holtmann 		break;
3459769be974SMarcel Holtmann 
3460a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
3461a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
3462a9de9248SMarcel Holtmann 		break;
3463a9de9248SMarcel Holtmann 
3464a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
3465a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
3466a9de9248SMarcel Holtmann 		break;
3467a9de9248SMarcel Holtmann 
3468a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
3469a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
3470a9de9248SMarcel Holtmann 		break;
3471a9de9248SMarcel Holtmann 
347250fc85f1SKuba Pawlak 	case HCI_OP_SWITCH_ROLE:
347350fc85f1SKuba Pawlak 		hci_cs_switch_role(hdev, ev->status);
347450fc85f1SKuba Pawlak 		break;
347550fc85f1SKuba Pawlak 
3476cb1d68f7SJohan Hedberg 	case HCI_OP_LE_CREATE_CONN:
3477cb1d68f7SJohan Hedberg 		hci_cs_le_create_conn(hdev, ev->status);
3478cb1d68f7SJohan Hedberg 		break;
3479cb1d68f7SJohan Hedberg 
34800fe29fd1SMarcel Holtmann 	case HCI_OP_LE_READ_REMOTE_FEATURES:
34810fe29fd1SMarcel Holtmann 		hci_cs_le_read_remote_features(hdev, ev->status);
34820fe29fd1SMarcel Holtmann 		break;
34830fe29fd1SMarcel Holtmann 
348481d0c8adSJohan Hedberg 	case HCI_OP_LE_START_ENC:
348581d0c8adSJohan Hedberg 		hci_cs_le_start_enc(hdev, ev->status);
348681d0c8adSJohan Hedberg 		break;
348781d0c8adSJohan Hedberg 
34884d94f95dSJaganath Kanakkassery 	case HCI_OP_LE_EXT_CREATE_CONN:
34894d94f95dSJaganath Kanakkassery 		hci_cs_le_ext_create_conn(hdev, ev->status);
34904d94f95dSJaganath Kanakkassery 		break;
34914d94f95dSJaganath Kanakkassery 
3492a9de9248SMarcel Holtmann 	default:
3493e6214487SJohan Hedberg 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
3494a9de9248SMarcel Holtmann 		break;
3495a9de9248SMarcel Holtmann 	}
3496a9de9248SMarcel Holtmann 
3497e6214487SJohan Hedberg 	if (*opcode != HCI_OP_NOP)
349865cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
34996bd32326SVille Tervo 
3500600b2150SJohan Hedberg 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags))
3501600b2150SJohan Hedberg 		atomic_set(&hdev->cmd_cnt, 1);
3502600b2150SJohan Hedberg 
3503444c6dd5SJohan Hedberg 	/* Indicate request completion if the command failed. Also, if
3504444c6dd5SJohan Hedberg 	 * we're not waiting for a special event and we get a success
3505444c6dd5SJohan Hedberg 	 * command status we should try to flag the request as completed
3506444c6dd5SJohan Hedberg 	 * (since for this kind of commands there will not be a command
3507444c6dd5SJohan Hedberg 	 * complete event).
3508444c6dd5SJohan Hedberg 	 */
350902350a72SJohan Hedberg 	if (ev->status ||
3510242c0ebdSMarcel Holtmann 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->hci.req_event))
3511e6214487SJohan Hedberg 		hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
3512e6214487SJohan Hedberg 				     req_complete_skb);
35139238f36aSJohan Hedberg 
3514600b2150SJohan Hedberg 	if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
3515c347b765SGustavo F. Padovan 		queue_work(hdev->workqueue, &hdev->cmd_work);
3516a9de9248SMarcel Holtmann }
3517a9de9248SMarcel Holtmann 
351824dfa343SMarcel Holtmann static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
351924dfa343SMarcel Holtmann {
352024dfa343SMarcel Holtmann 	struct hci_ev_hardware_error *ev = (void *) skb->data;
352124dfa343SMarcel Holtmann 
3522c7741d16SMarcel Holtmann 	hdev->hw_error_code = ev->code;
3523c7741d16SMarcel Holtmann 
3524c7741d16SMarcel Holtmann 	queue_work(hdev->req_workqueue, &hdev->error_reset);
352524dfa343SMarcel Holtmann }
352624dfa343SMarcel Holtmann 
35276039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3528a9de9248SMarcel Holtmann {
3529a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
3530a9de9248SMarcel Holtmann 	struct hci_conn *conn;
3531a9de9248SMarcel Holtmann 
35329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3533a9de9248SMarcel Holtmann 
3534a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3535a9de9248SMarcel Holtmann 
3536a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3537a9de9248SMarcel Holtmann 	if (conn) {
353840bef302SJohan Hedberg 		if (!ev->status)
353940bef302SJohan Hedberg 			conn->role = ev->role;
3540a9de9248SMarcel Holtmann 
354151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
3542a9de9248SMarcel Holtmann 
3543a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
3544a9de9248SMarcel Holtmann 	}
3545a9de9248SMarcel Holtmann 
3546a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3547a9de9248SMarcel Holtmann }
3548a9de9248SMarcel Holtmann 
35496039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
35501da177e4SLinus Torvalds {
3551a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
35521da177e4SLinus Torvalds 	int i;
35531da177e4SLinus Torvalds 
355432ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
35552064ee33SMarcel Holtmann 		bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
355632ac5b9bSAndrei Emeltchenko 		return;
355732ac5b9bSAndrei Emeltchenko 	}
355832ac5b9bSAndrei Emeltchenko 
355916e18342SGustavo A. R. Silva 	if (skb->len < sizeof(*ev) ||
356016e18342SGustavo A. R. Silva 	    skb->len < struct_size(ev, handles, ev->num_hndl)) {
35611da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
35621da177e4SLinus Torvalds 		return;
35631da177e4SLinus Torvalds 	}
35641da177e4SLinus Torvalds 
3565c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
3566c5993de8SAndrei Emeltchenko 
3567613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
3568613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
35691da177e4SLinus Torvalds 		struct hci_conn *conn;
35701da177e4SLinus Torvalds 		__u16  handle, count;
35711da177e4SLinus Torvalds 
3572613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
3573613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
35741da177e4SLinus Torvalds 
35751da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
3576f4280918SAndrei Emeltchenko 		if (!conn)
3577f4280918SAndrei Emeltchenko 			continue;
3578f4280918SAndrei Emeltchenko 
35791da177e4SLinus Torvalds 		conn->sent -= count;
35801da177e4SLinus Torvalds 
3581f4280918SAndrei Emeltchenko 		switch (conn->type) {
3582f4280918SAndrei Emeltchenko 		case ACL_LINK:
358370f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
358470f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
35851da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
3586f4280918SAndrei Emeltchenko 			break;
3587f4280918SAndrei Emeltchenko 
3588f4280918SAndrei Emeltchenko 		case LE_LINK:
35896ed58ec5SVille Tervo 			if (hdev->le_pkts) {
35906ed58ec5SVille Tervo 				hdev->le_cnt += count;
35916ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
35926ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
35936ed58ec5SVille Tervo 			} else {
35946ed58ec5SVille Tervo 				hdev->acl_cnt += count;
35956ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
35966ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
35976ed58ec5SVille Tervo 			}
3598f4280918SAndrei Emeltchenko 			break;
3599f4280918SAndrei Emeltchenko 
3600f4280918SAndrei Emeltchenko 		case SCO_LINK:
360170f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
360270f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
36035b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
3604f4280918SAndrei Emeltchenko 			break;
3605f4280918SAndrei Emeltchenko 
3606f4280918SAndrei Emeltchenko 		default:
36072064ee33SMarcel Holtmann 			bt_dev_err(hdev, "unknown type %d conn %p",
36082064ee33SMarcel Holtmann 				   conn->type, conn);
3609f4280918SAndrei Emeltchenko 			break;
36101da177e4SLinus Torvalds 		}
36111da177e4SLinus Torvalds 	}
3612a9de9248SMarcel Holtmann 
36133eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
36141da177e4SLinus Torvalds }
36151da177e4SLinus Torvalds 
361676ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
361776ef7cf7SAndrei Emeltchenko 						 __u16 handle)
361876ef7cf7SAndrei Emeltchenko {
361976ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
362076ef7cf7SAndrei Emeltchenko 
362176ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
3622ca8bee5dSMarcel Holtmann 	case HCI_PRIMARY:
362376ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
362476ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
362576ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
362676ef7cf7SAndrei Emeltchenko 		if (chan)
362776ef7cf7SAndrei Emeltchenko 			return chan->conn;
362876ef7cf7SAndrei Emeltchenko 		break;
362976ef7cf7SAndrei Emeltchenko 	default:
36302064ee33SMarcel Holtmann 		bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type);
363176ef7cf7SAndrei Emeltchenko 		break;
363276ef7cf7SAndrei Emeltchenko 	}
363376ef7cf7SAndrei Emeltchenko 
363476ef7cf7SAndrei Emeltchenko 	return NULL;
363576ef7cf7SAndrei Emeltchenko }
363676ef7cf7SAndrei Emeltchenko 
36376039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
363825e89e99SAndrei Emeltchenko {
363925e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
364025e89e99SAndrei Emeltchenko 	int i;
364125e89e99SAndrei Emeltchenko 
364225e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
36432064ee33SMarcel Holtmann 		bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
364425e89e99SAndrei Emeltchenko 		return;
364525e89e99SAndrei Emeltchenko 	}
364625e89e99SAndrei Emeltchenko 
364716e18342SGustavo A. R. Silva 	if (skb->len < sizeof(*ev) ||
364816e18342SGustavo A. R. Silva 	    skb->len < struct_size(ev, handles, ev->num_hndl)) {
364925e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
365025e89e99SAndrei Emeltchenko 		return;
365125e89e99SAndrei Emeltchenko 	}
365225e89e99SAndrei Emeltchenko 
365325e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
365425e89e99SAndrei Emeltchenko 	       ev->num_hndl);
365525e89e99SAndrei Emeltchenko 
365625e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
365725e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
365876ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
365925e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
366025e89e99SAndrei Emeltchenko 
366125e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
366225e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
366325e89e99SAndrei Emeltchenko 
366476ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
366525e89e99SAndrei Emeltchenko 		if (!conn)
366625e89e99SAndrei Emeltchenko 			continue;
366725e89e99SAndrei Emeltchenko 
366825e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
366925e89e99SAndrei Emeltchenko 
367025e89e99SAndrei Emeltchenko 		switch (conn->type) {
367125e89e99SAndrei Emeltchenko 		case ACL_LINK:
3672bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
367325e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
367425e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
367525e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
367625e89e99SAndrei Emeltchenko 			break;
367725e89e99SAndrei Emeltchenko 
367825e89e99SAndrei Emeltchenko 		default:
36792064ee33SMarcel Holtmann 			bt_dev_err(hdev, "unknown type %d conn %p",
36802064ee33SMarcel Holtmann 				   conn->type, conn);
368125e89e99SAndrei Emeltchenko 			break;
368225e89e99SAndrei Emeltchenko 		}
368325e89e99SAndrei Emeltchenko 	}
368425e89e99SAndrei Emeltchenko 
368525e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
368625e89e99SAndrei Emeltchenko }
368725e89e99SAndrei Emeltchenko 
36886039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
36891da177e4SLinus Torvalds {
3690a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
369104837f64SMarcel Holtmann 	struct hci_conn *conn;
36921da177e4SLinus Torvalds 
36939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
36941da177e4SLinus Torvalds 
36951da177e4SLinus Torvalds 	hci_dev_lock(hdev);
36961da177e4SLinus Torvalds 
369704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
369804837f64SMarcel Holtmann 	if (conn) {
369904837f64SMarcel Holtmann 		conn->mode = ev->mode;
370004837f64SMarcel Holtmann 
37018fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
37028fc9ced3SGustavo Padovan 					&conn->flags)) {
370304837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
370458a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
370504837f64SMarcel Holtmann 			else
370658a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
370704837f64SMarcel Holtmann 		}
3708e73439d8SMarcel Holtmann 
370951a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
3710e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
371104837f64SMarcel Holtmann 	}
371204837f64SMarcel Holtmann 
371304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
371404837f64SMarcel Holtmann }
371504837f64SMarcel Holtmann 
37166039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
37171da177e4SLinus Torvalds {
3718052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
3719052b30b0SMarcel Holtmann 	struct hci_conn *conn;
3720052b30b0SMarcel Holtmann 
3721a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3722052b30b0SMarcel Holtmann 
3723052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3724052b30b0SMarcel Holtmann 
3725052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3726b6f98044SWaldemar Rymarkiewicz 	if (!conn)
3727b6f98044SWaldemar Rymarkiewicz 		goto unlock;
3728b6f98044SWaldemar Rymarkiewicz 
3729b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
3730052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3731052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
373276a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3733052b30b0SMarcel Holtmann 	}
3734052b30b0SMarcel Holtmann 
3735d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
37362f407f0aSJohan Hedberg 	    !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) {
373703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
373803b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
3739d7a5a11dSMarcel Holtmann 	} else if (hci_dev_test_flag(hdev, HCI_MGMT)) {
3740a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
3741a770bb5aSWaldemar Rymarkiewicz 
3742a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
3743a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
3744a770bb5aSWaldemar Rymarkiewicz 		else
3745a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
3746a770bb5aSWaldemar Rymarkiewicz 
3747744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
3748a770bb5aSWaldemar Rymarkiewicz 	}
3749980e1a53SJohan Hedberg 
3750b6f98044SWaldemar Rymarkiewicz unlock:
3751052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
37521da177e4SLinus Torvalds }
37531da177e4SLinus Torvalds 
3754cb6f3f7aSJohan Hedberg static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
3755cb6f3f7aSJohan Hedberg {
3756cb6f3f7aSJohan Hedberg 	if (key_type == HCI_LK_CHANGED_COMBINATION)
3757cb6f3f7aSJohan Hedberg 		return;
3758cb6f3f7aSJohan Hedberg 
3759cb6f3f7aSJohan Hedberg 	conn->pin_length = pin_len;
3760cb6f3f7aSJohan Hedberg 	conn->key_type = key_type;
3761cb6f3f7aSJohan Hedberg 
3762cb6f3f7aSJohan Hedberg 	switch (key_type) {
3763cb6f3f7aSJohan Hedberg 	case HCI_LK_LOCAL_UNIT:
3764cb6f3f7aSJohan Hedberg 	case HCI_LK_REMOTE_UNIT:
3765cb6f3f7aSJohan Hedberg 	case HCI_LK_DEBUG_COMBINATION:
3766cb6f3f7aSJohan Hedberg 		return;
3767cb6f3f7aSJohan Hedberg 	case HCI_LK_COMBINATION:
3768cb6f3f7aSJohan Hedberg 		if (pin_len == 16)
3769cb6f3f7aSJohan Hedberg 			conn->pending_sec_level = BT_SECURITY_HIGH;
3770cb6f3f7aSJohan Hedberg 		else
3771cb6f3f7aSJohan Hedberg 			conn->pending_sec_level = BT_SECURITY_MEDIUM;
3772cb6f3f7aSJohan Hedberg 		break;
3773cb6f3f7aSJohan Hedberg 	case HCI_LK_UNAUTH_COMBINATION_P192:
3774cb6f3f7aSJohan Hedberg 	case HCI_LK_UNAUTH_COMBINATION_P256:
3775cb6f3f7aSJohan Hedberg 		conn->pending_sec_level = BT_SECURITY_MEDIUM;
3776cb6f3f7aSJohan Hedberg 		break;
3777cb6f3f7aSJohan Hedberg 	case HCI_LK_AUTH_COMBINATION_P192:
3778cb6f3f7aSJohan Hedberg 		conn->pending_sec_level = BT_SECURITY_HIGH;
3779cb6f3f7aSJohan Hedberg 		break;
3780cb6f3f7aSJohan Hedberg 	case HCI_LK_AUTH_COMBINATION_P256:
3781cb6f3f7aSJohan Hedberg 		conn->pending_sec_level = BT_SECURITY_FIPS;
3782cb6f3f7aSJohan Hedberg 		break;
3783cb6f3f7aSJohan Hedberg 	}
3784cb6f3f7aSJohan Hedberg }
3785cb6f3f7aSJohan Hedberg 
37866039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
37871da177e4SLinus Torvalds {
378855ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
378955ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
379055ed8ca1SJohan Hedberg 	struct hci_conn *conn;
379155ed8ca1SJohan Hedberg 	struct link_key *key;
379255ed8ca1SJohan Hedberg 
3793a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
379455ed8ca1SJohan Hedberg 
3795d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
379655ed8ca1SJohan Hedberg 		return;
379755ed8ca1SJohan Hedberg 
379855ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
379955ed8ca1SJohan Hedberg 
380055ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
380155ed8ca1SJohan Hedberg 	if (!key) {
38026ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
38036ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
380455ed8ca1SJohan Hedberg 		goto not_found;
380555ed8ca1SJohan Hedberg 	}
380655ed8ca1SJohan Hedberg 
38076ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
38086ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
380955ed8ca1SJohan Hedberg 
381055ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
381160b83f57SWaldemar Rymarkiewicz 	if (conn) {
3812fe8bc5acSJohan Hedberg 		clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
3813fe8bc5acSJohan Hedberg 
381466138ce8SMarcel Holtmann 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
381566138ce8SMarcel Holtmann 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
3816807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
381755ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
381855ed8ca1SJohan Hedberg 			goto not_found;
381955ed8ca1SJohan Hedberg 		}
382055ed8ca1SJohan Hedberg 
382160b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
3822f3fb0b58SJohan Hedberg 		    (conn->pending_sec_level == BT_SECURITY_HIGH ||
3823f3fb0b58SJohan Hedberg 		     conn->pending_sec_level == BT_SECURITY_FIPS)) {
38248fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
38258fc9ced3SGustavo Padovan 			       hdev->name);
382660b83f57SWaldemar Rymarkiewicz 			goto not_found;
382760b83f57SWaldemar Rymarkiewicz 		}
382860b83f57SWaldemar Rymarkiewicz 
3829cb6f3f7aSJohan Hedberg 		conn_set_key(conn, key->type, key->pin_len);
383060b83f57SWaldemar Rymarkiewicz 	}
383160b83f57SWaldemar Rymarkiewicz 
383255ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
38339b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
383455ed8ca1SJohan Hedberg 
383555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
383655ed8ca1SJohan Hedberg 
383755ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
383855ed8ca1SJohan Hedberg 
383955ed8ca1SJohan Hedberg 	return;
384055ed8ca1SJohan Hedberg 
384155ed8ca1SJohan Hedberg not_found:
384255ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
384355ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
38441da177e4SLinus Torvalds }
38451da177e4SLinus Torvalds 
38466039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
38471da177e4SLinus Torvalds {
3848052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
3849052b30b0SMarcel Holtmann 	struct hci_conn *conn;
38507652ff6aSJohan Hedberg 	struct link_key *key;
38517652ff6aSJohan Hedberg 	bool persistent;
385255ed8ca1SJohan Hedberg 	u8 pin_len = 0;
3853052b30b0SMarcel Holtmann 
3854a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3855052b30b0SMarcel Holtmann 
3856052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3857052b30b0SMarcel Holtmann 
3858052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
385982c13d42SJohan Hedberg 	if (!conn)
386082c13d42SJohan Hedberg 		goto unlock;
386182c13d42SJohan Hedberg 
3862052b30b0SMarcel Holtmann 	hci_conn_hold(conn);
3863052b30b0SMarcel Holtmann 	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
386476a68ba0SDavid Herrmann 	hci_conn_drop(conn);
386582c13d42SJohan Hedberg 
3866fe8bc5acSJohan Hedberg 	set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
3867cb6f3f7aSJohan Hedberg 	conn_set_key(conn, ev->key_type, conn->pin_length);
3868052b30b0SMarcel Holtmann 
3869d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
38707652ff6aSJohan Hedberg 		goto unlock;
387155ed8ca1SJohan Hedberg 
38727652ff6aSJohan Hedberg 	key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key,
38737652ff6aSJohan Hedberg 			        ev->key_type, pin_len, &persistent);
38747652ff6aSJohan Hedberg 	if (!key)
38757652ff6aSJohan Hedberg 		goto unlock;
38767652ff6aSJohan Hedberg 
3877cb6f3f7aSJohan Hedberg 	/* Update connection information since adding the key will have
3878cb6f3f7aSJohan Hedberg 	 * fixed up the type in the case of changed combination keys.
3879cb6f3f7aSJohan Hedberg 	 */
3880cb6f3f7aSJohan Hedberg 	if (ev->key_type == HCI_LK_CHANGED_COMBINATION)
3881cb6f3f7aSJohan Hedberg 		conn_set_key(conn, key->type, key->pin_len);
3882cb6f3f7aSJohan Hedberg 
38837652ff6aSJohan Hedberg 	mgmt_new_link_key(hdev, key, persistent);
38847652ff6aSJohan Hedberg 
38856d5650c4SJohan Hedberg 	/* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
38866d5650c4SJohan Hedberg 	 * is set. If it's not set simply remove the key from the kernel
38876d5650c4SJohan Hedberg 	 * list (we've still notified user space about it but with
38886d5650c4SJohan Hedberg 	 * store_hint being 0).
38896d5650c4SJohan Hedberg 	 */
38906d5650c4SJohan Hedberg 	if (key->type == HCI_LK_DEBUG_COMBINATION &&
3891d7a5a11dSMarcel Holtmann 	    !hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS)) {
38920378b597SJohan Hedberg 		list_del_rcu(&key->list);
38930378b597SJohan Hedberg 		kfree_rcu(key, rcu);
389482c13d42SJohan Hedberg 		goto unlock;
389582c13d42SJohan Hedberg 	}
389682c13d42SJohan Hedberg 
3897af6a9c32SJohan Hedberg 	if (persistent)
3898af6a9c32SJohan Hedberg 		clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
3899af6a9c32SJohan Hedberg 	else
3900af6a9c32SJohan Hedberg 		set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
39017652ff6aSJohan Hedberg 
39027652ff6aSJohan Hedberg unlock:
3903052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
39041da177e4SLinus Torvalds }
39051da177e4SLinus Torvalds 
39066039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
390704837f64SMarcel Holtmann {
3908a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
390904837f64SMarcel Holtmann 	struct hci_conn *conn;
391004837f64SMarcel Holtmann 
39119f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
391204837f64SMarcel Holtmann 
391304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
391404837f64SMarcel Holtmann 
391504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
39161da177e4SLinus Torvalds 	if (conn && !ev->status) {
39171da177e4SLinus Torvalds 		struct inquiry_entry *ie;
39181da177e4SLinus Torvalds 
3919cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3920cc11b9c1SAndrei Emeltchenko 		if (ie) {
39211da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
39221da177e4SLinus Torvalds 			ie->timestamp = jiffies;
39231da177e4SLinus Torvalds 		}
39241da177e4SLinus Torvalds 	}
39251da177e4SLinus Torvalds 
39261da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
39271da177e4SLinus Torvalds }
39281da177e4SLinus Torvalds 
39296039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3930a8746417SMarcel Holtmann {
3931a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3932a8746417SMarcel Holtmann 	struct hci_conn *conn;
3933a8746417SMarcel Holtmann 
39349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3935a8746417SMarcel Holtmann 
3936a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
3937a8746417SMarcel Holtmann 
3938a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3939a8746417SMarcel Holtmann 	if (conn && !ev->status)
3940a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3941a8746417SMarcel Holtmann 
3942a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
3943a8746417SMarcel Holtmann }
3944a8746417SMarcel Holtmann 
39456039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
394685a1e930SMarcel Holtmann {
3947a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
394885a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
394985a1e930SMarcel Holtmann 
395085a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
395185a1e930SMarcel Holtmann 
395285a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
395385a1e930SMarcel Holtmann 
3954cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3955cc11b9c1SAndrei Emeltchenko 	if (ie) {
395685a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
395785a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
395885a1e930SMarcel Holtmann 	}
395985a1e930SMarcel Holtmann 
396085a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
396185a1e930SMarcel Holtmann }
396285a1e930SMarcel Holtmann 
39636039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3964807deac2SGustavo Padovan 					     struct sk_buff *skb)
3965a9de9248SMarcel Holtmann {
3966a9de9248SMarcel Holtmann 	struct inquiry_data data;
3967a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
3968a9de9248SMarcel Holtmann 
3969a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3970a9de9248SMarcel Holtmann 
3971a9de9248SMarcel Holtmann 	if (!num_rsp)
3972a9de9248SMarcel Holtmann 		return;
3973a9de9248SMarcel Holtmann 
3974d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
39751519cc17SAndre Guedes 		return;
39761519cc17SAndre Guedes 
3977a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3978a9de9248SMarcel Holtmann 
3979a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3980138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3981138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3982a9de9248SMarcel Holtmann 
3983e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3984af58925cSMarcel Holtmann 			u32 flags;
3985af58925cSMarcel Holtmann 
3986a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3987a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3988a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3989a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3990a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3991a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3992a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
399341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
39943175405bSJohan Hedberg 
3995af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
3996af58925cSMarcel Holtmann 
399748264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3998e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3999af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
4000a9de9248SMarcel Holtmann 		}
4001a9de9248SMarcel Holtmann 	} else {
4002a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
4003a9de9248SMarcel Holtmann 
4004e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
4005af58925cSMarcel Holtmann 			u32 flags;
4006af58925cSMarcel Holtmann 
4007a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
4008a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
4009a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
4010a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
4011a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
4012a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
4013a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
401441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
4015af58925cSMarcel Holtmann 
4016af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
4017af58925cSMarcel Holtmann 
401848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
4019e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
4020af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
4021a9de9248SMarcel Holtmann 		}
4022a9de9248SMarcel Holtmann 	}
4023a9de9248SMarcel Holtmann 
4024a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
4025a9de9248SMarcel Holtmann }
4026a9de9248SMarcel Holtmann 
40276039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
4028807deac2SGustavo Padovan 					struct sk_buff *skb)
4029a9de9248SMarcel Holtmann {
403041a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
403141a96212SMarcel Holtmann 	struct hci_conn *conn;
403241a96212SMarcel Holtmann 
4033a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
403441a96212SMarcel Holtmann 
403541a96212SMarcel Holtmann 	hci_dev_lock(hdev);
403641a96212SMarcel Holtmann 
403741a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
4038ccd556feSJohan Hedberg 	if (!conn)
4039ccd556feSJohan Hedberg 		goto unlock;
4040ccd556feSJohan Hedberg 
4041cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
4042cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
4043cad718edSJohan Hedberg 
4044769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
404541a96212SMarcel Holtmann 		struct inquiry_entry *ie;
404641a96212SMarcel Holtmann 
4047cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
4048cc11b9c1SAndrei Emeltchenko 		if (ie)
404902b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
405041a96212SMarcel Holtmann 
4051bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
405258a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
4053bbb0eadaSJaganath Kanakkassery 		} else {
4054bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
4055bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
4056bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
4057bbb0eadaSJaganath Kanakkassery 			 * this.
4058bbb0eadaSJaganath Kanakkassery 			 *
4059bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
4060bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
4061bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
4062bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
4063bbb0eadaSJaganath Kanakkassery 		}
4064eb9a8f3fSMarcel Holtmann 
4065eb9a8f3fSMarcel Holtmann 		if (ev->features[0] & LMP_HOST_SC)
4066eb9a8f3fSMarcel Holtmann 			set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
406741a96212SMarcel Holtmann 	}
406841a96212SMarcel Holtmann 
4069ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
4070ccd556feSJohan Hedberg 		goto unlock;
4071ccd556feSJohan Hedberg 
4072671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
4073127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
4074127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
4075127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
4076127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
4077127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
4078b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
407948ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
4080392599b9SJohan Hedberg 
4081127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
4082769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
4083539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
408476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
4085769be974SMarcel Holtmann 	}
4086769be974SMarcel Holtmann 
4087ccd556feSJohan Hedberg unlock:
408841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
4089a9de9248SMarcel Holtmann }
4090a9de9248SMarcel Holtmann 
40916039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
4092807deac2SGustavo Padovan 				       struct sk_buff *skb)
4093a9de9248SMarcel Holtmann {
4094b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
4095b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
4096b6a0dc82SMarcel Holtmann 
40979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
4098b6a0dc82SMarcel Holtmann 
4099b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
4100b6a0dc82SMarcel Holtmann 
4101b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
41029dc0a3afSMarcel Holtmann 	if (!conn) {
41039dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
41049dc0a3afSMarcel Holtmann 			goto unlock;
41059dc0a3afSMarcel Holtmann 
4106618353b1SKuba Pawlak 		/* When the link type in the event indicates SCO connection
4107618353b1SKuba Pawlak 		 * and lookup of the connection object fails, then check
4108618353b1SKuba Pawlak 		 * if an eSCO connection object exists.
4109618353b1SKuba Pawlak 		 *
4110618353b1SKuba Pawlak 		 * The core limits the synchronous connections to either
4111618353b1SKuba Pawlak 		 * SCO or eSCO. The eSCO connection is preferred and tried
4112618353b1SKuba Pawlak 		 * to be setup first and until successfully established,
4113618353b1SKuba Pawlak 		 * the link type will be hinted as eSCO.
4114618353b1SKuba Pawlak 		 */
41159dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
4116b6a0dc82SMarcel Holtmann 		if (!conn)
4117b6a0dc82SMarcel Holtmann 			goto unlock;
41189dc0a3afSMarcel Holtmann 	}
41199dc0a3afSMarcel Holtmann 
4120732547f9SMarcel Holtmann 	switch (ev->status) {
4121732547f9SMarcel Holtmann 	case 0x00:
4122732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
4123732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
4124618353b1SKuba Pawlak 		conn->type   = ev->link_type;
4125732547f9SMarcel Holtmann 
412623b9ceb7SMarcel Holtmann 		hci_debugfs_create_conn(conn);
4127732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
4128732547f9SMarcel Holtmann 		break;
4129732547f9SMarcel Holtmann 
413081218d20SNick Pelly 	case 0x10:	/* Connection Accept Timeout */
41311a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
4132705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
4133732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
41341038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
4135732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
413627539bc4SAndrew Earl 	case 0x20:	/* Unsupported LMP Parameter value */
41372dea632fSFrédéric Dalleau 		if (conn->out) {
4138efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
4139efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
41402dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
4141efc7688bSMarcel Holtmann 				goto unlock;
4142efc7688bSMarcel Holtmann 		}
4143732547f9SMarcel Holtmann 		/* fall through */
4144efc7688bSMarcel Holtmann 
4145732547f9SMarcel Holtmann 	default:
4146b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
4147732547f9SMarcel Holtmann 		break;
4148732547f9SMarcel Holtmann 	}
4149b6a0dc82SMarcel Holtmann 
4150539c496dSJohan Hedberg 	hci_connect_cfm(conn, ev->status);
4151b6a0dc82SMarcel Holtmann 	if (ev->status)
4152b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
4153b6a0dc82SMarcel Holtmann 
4154b6a0dc82SMarcel Holtmann unlock:
4155b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
4156a9de9248SMarcel Holtmann }
4157a9de9248SMarcel Holtmann 
4158efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len)
4159efdcf8e3SMarcel Holtmann {
4160efdcf8e3SMarcel Holtmann 	size_t parsed = 0;
4161efdcf8e3SMarcel Holtmann 
4162efdcf8e3SMarcel Holtmann 	while (parsed < eir_len) {
4163efdcf8e3SMarcel Holtmann 		u8 field_len = eir[0];
4164efdcf8e3SMarcel Holtmann 
4165efdcf8e3SMarcel Holtmann 		if (field_len == 0)
4166efdcf8e3SMarcel Holtmann 			return parsed;
4167efdcf8e3SMarcel Holtmann 
4168efdcf8e3SMarcel Holtmann 		parsed += field_len + 1;
4169efdcf8e3SMarcel Holtmann 		eir += field_len + 1;
4170efdcf8e3SMarcel Holtmann 	}
4171efdcf8e3SMarcel Holtmann 
4172efdcf8e3SMarcel Holtmann 	return eir_len;
4173efdcf8e3SMarcel Holtmann }
4174efdcf8e3SMarcel Holtmann 
41756039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
4176807deac2SGustavo Padovan 					    struct sk_buff *skb)
4177a9de9248SMarcel Holtmann {
4178a9de9248SMarcel Holtmann 	struct inquiry_data data;
4179a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
4180a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
41819d939d94SVishal Agarwal 	size_t eir_len;
4182a9de9248SMarcel Holtmann 
4183a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
4184a9de9248SMarcel Holtmann 
4185a9de9248SMarcel Holtmann 	if (!num_rsp)
4186a9de9248SMarcel Holtmann 		return;
4187a9de9248SMarcel Holtmann 
4188d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
41891519cc17SAndre Guedes 		return;
41901519cc17SAndre Guedes 
4191a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
4192a9de9248SMarcel Holtmann 
4193e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
4194af58925cSMarcel Holtmann 		u32 flags;
4195af58925cSMarcel Holtmann 		bool name_known;
4196561aafbcSJohan Hedberg 
4197a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
4198a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
4199a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
4200a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
4201a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
4202a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
4203a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
420441a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
4205561aafbcSJohan Hedberg 
4206d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_MGMT))
42070d3b7f64SJohan Hedberg 			name_known = eir_get_data(info->data,
42084ddb1930SJohan Hedberg 						  sizeof(info->data),
42090d3b7f64SJohan Hedberg 						  EIR_NAME_COMPLETE, NULL);
4210561aafbcSJohan Hedberg 		else
4211561aafbcSJohan Hedberg 			name_known = true;
4212561aafbcSJohan Hedberg 
4213af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, name_known);
4214af58925cSMarcel Holtmann 
42159d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
4216af58925cSMarcel Holtmann 
421748264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
4218af58925cSMarcel Holtmann 				  info->dev_class, info->rssi,
4219af58925cSMarcel Holtmann 				  flags, info->data, eir_len, NULL, 0);
4220a9de9248SMarcel Holtmann 	}
4221a9de9248SMarcel Holtmann 
4222a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
4223a9de9248SMarcel Holtmann }
4224a9de9248SMarcel Holtmann 
42251c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
42261c2e0041SJohan Hedberg 					 struct sk_buff *skb)
42271c2e0041SJohan Hedberg {
42281c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
42291c2e0041SJohan Hedberg 	struct hci_conn *conn;
42301c2e0041SJohan Hedberg 
42319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
42321c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
42331c2e0041SJohan Hedberg 
42341c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
42351c2e0041SJohan Hedberg 
42361c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
42371c2e0041SJohan Hedberg 	if (!conn)
42381c2e0041SJohan Hedberg 		goto unlock;
42391c2e0041SJohan Hedberg 
42409eb1fbfaSJohan Hedberg 	/* For BR/EDR the necessary steps are taken through the
42419eb1fbfaSJohan Hedberg 	 * auth_complete event.
42429eb1fbfaSJohan Hedberg 	 */
42439eb1fbfaSJohan Hedberg 	if (conn->type != LE_LINK)
42449eb1fbfaSJohan Hedberg 		goto unlock;
42459eb1fbfaSJohan Hedberg 
42461c2e0041SJohan Hedberg 	if (!ev->status)
42471c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
42481c2e0041SJohan Hedberg 
42491c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
42501c2e0041SJohan Hedberg 
42511c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
4252bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
425376a68ba0SDavid Herrmann 		hci_conn_drop(conn);
42541c2e0041SJohan Hedberg 		goto unlock;
42551c2e0041SJohan Hedberg 	}
42561c2e0041SJohan Hedberg 
42571c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
42581c2e0041SJohan Hedberg 		if (!ev->status)
42591c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
42601c2e0041SJohan Hedberg 
4261539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
426276a68ba0SDavid Herrmann 		hci_conn_drop(conn);
42631c2e0041SJohan Hedberg 	} else {
42641c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
42651c2e0041SJohan Hedberg 
42661c2e0041SJohan Hedberg 		hci_conn_hold(conn);
42671c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
426876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
42691c2e0041SJohan Hedberg 	}
42701c2e0041SJohan Hedberg 
42711c2e0041SJohan Hedberg unlock:
42721c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
42731c2e0041SJohan Hedberg }
42741c2e0041SJohan Hedberg 
42756039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
427617fa4b9dSJohan Hedberg {
427717fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
4278acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
4279acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
428058797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
428117fa4b9dSJohan Hedberg 
4282b7f94c88SMikel Astiz 	/* If both remote and local have enough IO capabilities, require
4283b7f94c88SMikel Astiz 	 * MITM protection
4284b7f94c88SMikel Astiz 	 */
4285b7f94c88SMikel Astiz 	if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT &&
4286b7f94c88SMikel Astiz 	    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT)
4287b7f94c88SMikel Astiz 		return conn->remote_auth | 0x01;
4288b7f94c88SMikel Astiz 
42897e74170aSTimo Mueller 	/* No MITM protection possible so ignore remote requirement */
42907e74170aSTimo Mueller 	return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01);
429117fa4b9dSJohan Hedberg }
429217fa4b9dSJohan Hedberg 
4293a83ed81eSMarcel Holtmann static u8 bredr_oob_data_present(struct hci_conn *conn)
4294a83ed81eSMarcel Holtmann {
4295a83ed81eSMarcel Holtmann 	struct hci_dev *hdev = conn->hdev;
4296a83ed81eSMarcel Holtmann 	struct oob_data *data;
4297a83ed81eSMarcel Holtmann 
4298a83ed81eSMarcel Holtmann 	data = hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR);
4299a83ed81eSMarcel Holtmann 	if (!data)
4300a83ed81eSMarcel Holtmann 		return 0x00;
4301a83ed81eSMarcel Holtmann 
4302bf21d793SMarcel Holtmann 	if (bredr_sc_enabled(hdev)) {
4303bf21d793SMarcel Holtmann 		/* When Secure Connections is enabled, then just
4304bf21d793SMarcel Holtmann 		 * return the present value stored with the OOB
4305bf21d793SMarcel Holtmann 		 * data. The stored value contains the right present
4306bf21d793SMarcel Holtmann 		 * information. However it can only be trusted when
4307bf21d793SMarcel Holtmann 		 * not in Secure Connection Only mode.
4308aa5b0345SMarcel Holtmann 		 */
4309d7a5a11dSMarcel Holtmann 		if (!hci_dev_test_flag(hdev, HCI_SC_ONLY))
4310bf21d793SMarcel Holtmann 			return data->present;
4311bf21d793SMarcel Holtmann 
4312bf21d793SMarcel Holtmann 		/* When Secure Connections Only mode is enabled, then
4313bf21d793SMarcel Holtmann 		 * the P-256 values are required. If they are not
4314bf21d793SMarcel Holtmann 		 * available, then do not declare that OOB data is
4315bf21d793SMarcel Holtmann 		 * present.
4316bf21d793SMarcel Holtmann 		 */
4317bf21d793SMarcel Holtmann 		if (!memcmp(data->rand256, ZERO_KEY, 16) ||
4318bf21d793SMarcel Holtmann 		    !memcmp(data->hash256, ZERO_KEY, 16))
4319aa5b0345SMarcel Holtmann 			return 0x00;
4320aa5b0345SMarcel Holtmann 
4321bf21d793SMarcel Holtmann 		return 0x02;
4322bf21d793SMarcel Holtmann 	}
4323659c7fb0SMarcel Holtmann 
4324659c7fb0SMarcel Holtmann 	/* When Secure Connections is not enabled or actually
4325659c7fb0SMarcel Holtmann 	 * not supported by the hardware, then check that if
4326659c7fb0SMarcel Holtmann 	 * P-192 data values are present.
4327659c7fb0SMarcel Holtmann 	 */
4328659c7fb0SMarcel Holtmann 	if (!memcmp(data->rand192, ZERO_KEY, 16) ||
4329659c7fb0SMarcel Holtmann 	    !memcmp(data->hash192, ZERO_KEY, 16))
4330659c7fb0SMarcel Holtmann 		return 0x00;
4331659c7fb0SMarcel Holtmann 
4332a83ed81eSMarcel Holtmann 	return 0x01;
4333659c7fb0SMarcel Holtmann }
4334a83ed81eSMarcel Holtmann 
43356039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
43360493684eSMarcel Holtmann {
43370493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
43380493684eSMarcel Holtmann 	struct hci_conn *conn;
43390493684eSMarcel Holtmann 
43400493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
43410493684eSMarcel Holtmann 
43420493684eSMarcel Holtmann 	hci_dev_lock(hdev);
43430493684eSMarcel Holtmann 
43440493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
434503b555e1SJohan Hedberg 	if (!conn)
434603b555e1SJohan Hedberg 		goto unlock;
434703b555e1SJohan Hedberg 
43480493684eSMarcel Holtmann 	hci_conn_hold(conn);
43490493684eSMarcel Holtmann 
4350d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
435103b555e1SJohan Hedberg 		goto unlock;
435203b555e1SJohan Hedberg 
43532f407f0aSJohan Hedberg 	/* Allow pairing if we're pairable, the initiators of the
43542f407f0aSJohan Hedberg 	 * pairing or if the remote is not requesting bonding.
43552f407f0aSJohan Hedberg 	 */
4356d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_BONDABLE) ||
43572f407f0aSJohan Hedberg 	    test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) ||
435803b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
435917fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
436017fa4b9dSJohan Hedberg 
436117fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
43627a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
43637a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
43647a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
4365a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
4366b7f94c88SMikel Astiz 
4367b7f94c88SMikel Astiz 		/* If we are initiators, there is no remote information yet */
4368b7f94c88SMikel Astiz 		if (conn->remote_auth == 0xff) {
4369b16c6604SMikel Astiz 			/* Request MITM protection if our IO caps allow it
43704ad51a75SJohan Hedberg 			 * except for the no-bonding case.
4371b16c6604SMikel Astiz 			 */
43726fd6b915SMikel Astiz 			if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
43739f743d74SJohan Hedberg 			    conn->auth_type != HCI_AT_NO_BONDING)
43746c53823aSJohan Hedberg 				conn->auth_type |= 0x01;
4375b7f94c88SMikel Astiz 		} else {
43767cbc9bd9SJohan Hedberg 			conn->auth_type = hci_get_auth_req(conn);
4377b7f94c88SMikel Astiz 		}
437817fa4b9dSJohan Hedberg 
437982c295b1SJohan Hedberg 		/* If we're not bondable, force one of the non-bondable
438082c295b1SJohan Hedberg 		 * authentication requirement values.
438182c295b1SJohan Hedberg 		 */
4382d7a5a11dSMarcel Holtmann 		if (!hci_dev_test_flag(hdev, HCI_BONDABLE))
438382c295b1SJohan Hedberg 			conn->auth_type &= HCI_AT_NO_BONDING_MITM;
438482c295b1SJohan Hedberg 
438582c295b1SJohan Hedberg 		cp.authentication = conn->auth_type;
4386a83ed81eSMarcel Holtmann 		cp.oob_data = bredr_oob_data_present(conn);
4387ce85ee13SSzymon Janc 
438817fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
438917fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
439003b555e1SJohan Hedberg 	} else {
439103b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
439203b555e1SJohan Hedberg 
439303b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
43949f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
439503b555e1SJohan Hedberg 
439603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
439703b555e1SJohan Hedberg 			     sizeof(cp), &cp);
439803b555e1SJohan Hedberg 	}
439903b555e1SJohan Hedberg 
440003b555e1SJohan Hedberg unlock:
440103b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
440203b555e1SJohan Hedberg }
440303b555e1SJohan Hedberg 
44046039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
440503b555e1SJohan Hedberg {
440603b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
440703b555e1SJohan Hedberg 	struct hci_conn *conn;
440803b555e1SJohan Hedberg 
440903b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
441003b555e1SJohan Hedberg 
441103b555e1SJohan Hedberg 	hci_dev_lock(hdev);
441203b555e1SJohan Hedberg 
441303b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
441403b555e1SJohan Hedberg 	if (!conn)
441503b555e1SJohan Hedberg 		goto unlock;
441603b555e1SJohan Hedberg 
441703b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
441803b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
441903b555e1SJohan Hedberg 
442003b555e1SJohan Hedberg unlock:
44210493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
44220493684eSMarcel Holtmann }
44230493684eSMarcel Holtmann 
44246039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
4425a5c29683SJohan Hedberg 					 struct sk_buff *skb)
4426a5c29683SJohan Hedberg {
4427a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
442855bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
44297a828908SJohan Hedberg 	struct hci_conn *conn;
4430a5c29683SJohan Hedberg 
4431a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
4432a5c29683SJohan Hedberg 
4433a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
4434a5c29683SJohan Hedberg 
4435d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
44367a828908SJohan Hedberg 		goto unlock;
44377a828908SJohan Hedberg 
44387a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
44397a828908SJohan Hedberg 	if (!conn)
44407a828908SJohan Hedberg 		goto unlock;
44417a828908SJohan Hedberg 
44427a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
44437a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
44447a828908SJohan Hedberg 
44457a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
44466c53823aSJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
44476c53823aSJohan Hedberg 	 * request. We check the security level here since it doesn't
44486c53823aSJohan Hedberg 	 * necessarily match conn->auth_type.
44496fd6b915SMikel Astiz 	 */
44506c53823aSJohan Hedberg 	if (conn->pending_sec_level > BT_SECURITY_MEDIUM &&
44516c53823aSJohan Hedberg 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
44527a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
44537a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
44547a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
44557a828908SJohan Hedberg 		goto unlock;
44567a828908SJohan Hedberg 	}
44577a828908SJohan Hedberg 
44587a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
4459a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
4460a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
446155bc1a37SJohan Hedberg 
446255bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
446355bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
4464ba15a58bSJohan Hedberg 		 * confirm_hint set to 1). The exception is if neither
446502f3e254SJohan Hedberg 		 * side had MITM or if the local IO capability is
446602f3e254SJohan Hedberg 		 * NoInputNoOutput, in which case we do auto-accept
4467ba15a58bSJohan Hedberg 		 */
4468ba15a58bSJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
446902f3e254SJohan Hedberg 		    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
4470ba15a58bSJohan Hedberg 		    (loc_mitm || rem_mitm)) {
447155bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
447255bc1a37SJohan Hedberg 			confirm_hint = 1;
447355bc1a37SJohan Hedberg 			goto confirm;
447455bc1a37SJohan Hedberg 		}
447555bc1a37SJohan Hedberg 
44769f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
44779f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
44789f61656aSJohan Hedberg 
44799f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
44809f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
44817bc18d9dSJohan Hedberg 			queue_delayed_work(conn->hdev->workqueue,
44827bc18d9dSJohan Hedberg 					   &conn->auto_accept_work, delay);
44839f61656aSJohan Hedberg 			goto unlock;
44849f61656aSJohan Hedberg 		}
44859f61656aSJohan Hedberg 
44867a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
44877a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
44887a828908SJohan Hedberg 		goto unlock;
44897a828908SJohan Hedberg 	}
44907a828908SJohan Hedberg 
449155bc1a37SJohan Hedberg confirm:
449239adbffeSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0,
449339adbffeSJohan Hedberg 				  le32_to_cpu(ev->passkey), confirm_hint);
4494a5c29683SJohan Hedberg 
44957a828908SJohan Hedberg unlock:
4496a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
4497a5c29683SJohan Hedberg }
4498a5c29683SJohan Hedberg 
44996039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
45001143d458SBrian Gix 					 struct sk_buff *skb)
45011143d458SBrian Gix {
45021143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
45031143d458SBrian Gix 
45041143d458SBrian Gix 	BT_DBG("%s", hdev->name);
45051143d458SBrian Gix 
4506d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
4507272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
45081143d458SBrian Gix }
45091143d458SBrian Gix 
451092a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
451192a25256SJohan Hedberg 					struct sk_buff *skb)
451292a25256SJohan Hedberg {
451392a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
451492a25256SJohan Hedberg 	struct hci_conn *conn;
451592a25256SJohan Hedberg 
451692a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
451792a25256SJohan Hedberg 
451892a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
451992a25256SJohan Hedberg 	if (!conn)
452092a25256SJohan Hedberg 		return;
452192a25256SJohan Hedberg 
452292a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
452392a25256SJohan Hedberg 	conn->passkey_entered = 0;
452492a25256SJohan Hedberg 
4525d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
452692a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
452792a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
452892a25256SJohan Hedberg 					 conn->passkey_entered);
452992a25256SJohan Hedberg }
453092a25256SJohan Hedberg 
453192a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
453292a25256SJohan Hedberg {
453392a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
453492a25256SJohan Hedberg 	struct hci_conn *conn;
453592a25256SJohan Hedberg 
453692a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
453792a25256SJohan Hedberg 
453892a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
453992a25256SJohan Hedberg 	if (!conn)
454092a25256SJohan Hedberg 		return;
454192a25256SJohan Hedberg 
454292a25256SJohan Hedberg 	switch (ev->type) {
454392a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
454492a25256SJohan Hedberg 		conn->passkey_entered = 0;
454592a25256SJohan Hedberg 		return;
454692a25256SJohan Hedberg 
454792a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
454892a25256SJohan Hedberg 		conn->passkey_entered++;
454992a25256SJohan Hedberg 		break;
455092a25256SJohan Hedberg 
455192a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
455292a25256SJohan Hedberg 		conn->passkey_entered--;
455392a25256SJohan Hedberg 		break;
455492a25256SJohan Hedberg 
455592a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
455692a25256SJohan Hedberg 		conn->passkey_entered = 0;
455792a25256SJohan Hedberg 		break;
455892a25256SJohan Hedberg 
455992a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
456092a25256SJohan Hedberg 		return;
456192a25256SJohan Hedberg 	}
456292a25256SJohan Hedberg 
4563d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
456492a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
456592a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
456692a25256SJohan Hedberg 					 conn->passkey_entered);
456792a25256SJohan Hedberg }
456892a25256SJohan Hedberg 
45696039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
4570807deac2SGustavo Padovan 					 struct sk_buff *skb)
45710493684eSMarcel Holtmann {
45720493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
45730493684eSMarcel Holtmann 	struct hci_conn *conn;
45740493684eSMarcel Holtmann 
45750493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
45760493684eSMarcel Holtmann 
45770493684eSMarcel Holtmann 	hci_dev_lock(hdev);
45780493684eSMarcel Holtmann 
45790493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
45802a611692SJohan Hedberg 	if (!conn)
45812a611692SJohan Hedberg 		goto unlock;
45822a611692SJohan Hedberg 
4583c1d4fa7aSJohan Hedberg 	/* Reset the authentication requirement to unknown */
4584c1d4fa7aSJohan Hedberg 	conn->remote_auth = 0xff;
4585c1d4fa7aSJohan Hedberg 
45862a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
45872a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
45882a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
45892a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
45902a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
4591fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
4592e1e930f5SJohan Hedberg 		mgmt_auth_failed(conn, ev->status);
45932a611692SJohan Hedberg 
459476a68ba0SDavid Herrmann 	hci_conn_drop(conn);
45950493684eSMarcel Holtmann 
45962a611692SJohan Hedberg unlock:
45970493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
45980493684eSMarcel Holtmann }
45990493684eSMarcel Holtmann 
46006039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
4601807deac2SGustavo Padovan 					 struct sk_buff *skb)
460241a96212SMarcel Holtmann {
460341a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
460441a96212SMarcel Holtmann 	struct inquiry_entry *ie;
4605cad718edSJohan Hedberg 	struct hci_conn *conn;
460641a96212SMarcel Holtmann 
460741a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
460841a96212SMarcel Holtmann 
460941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
461041a96212SMarcel Holtmann 
4611cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
4612cad718edSJohan Hedberg 	if (conn)
4613cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
4614cad718edSJohan Hedberg 
4615cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
4616cc11b9c1SAndrei Emeltchenko 	if (ie)
461702b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
461841a96212SMarcel Holtmann 
461941a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
462041a96212SMarcel Holtmann }
462141a96212SMarcel Holtmann 
46226039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
46232763eda6SSzymon Janc 					    struct sk_buff *skb)
46242763eda6SSzymon Janc {
46252763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
46262763eda6SSzymon Janc 	struct oob_data *data;
46272763eda6SSzymon Janc 
46282763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
46292763eda6SSzymon Janc 
46302763eda6SSzymon Janc 	hci_dev_lock(hdev);
46312763eda6SSzymon Janc 
4632d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
4633e1ba1f15SSzymon Janc 		goto unlock;
4634e1ba1f15SSzymon Janc 
46356928a924SJohan Hedberg 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR);
46366665d057SMarcel Holtmann 	if (!data) {
46376665d057SMarcel Holtmann 		struct hci_cp_remote_oob_data_neg_reply cp;
46386665d057SMarcel Holtmann 
46396665d057SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
46406665d057SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
46416665d057SMarcel Holtmann 			     sizeof(cp), &cp);
46426665d057SMarcel Holtmann 		goto unlock;
46436665d057SMarcel Holtmann 	}
46446665d057SMarcel Holtmann 
4645710f11c0SJohan Hedberg 	if (bredr_sc_enabled(hdev)) {
4646519ca9d0SMarcel Holtmann 		struct hci_cp_remote_oob_ext_data_reply cp;
4647519ca9d0SMarcel Holtmann 
4648519ca9d0SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
4649d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
46506665d057SMarcel Holtmann 			memset(cp.hash192, 0, sizeof(cp.hash192));
46516665d057SMarcel Holtmann 			memset(cp.rand192, 0, sizeof(cp.rand192));
46526665d057SMarcel Holtmann 		} else {
4653519ca9d0SMarcel Holtmann 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
465438da1703SJohan Hedberg 			memcpy(cp.rand192, data->rand192, sizeof(cp.rand192));
46556665d057SMarcel Holtmann 		}
4656519ca9d0SMarcel Holtmann 		memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
465738da1703SJohan Hedberg 		memcpy(cp.rand256, data->rand256, sizeof(cp.rand256));
4658519ca9d0SMarcel Holtmann 
4659519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
4660519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
4661519ca9d0SMarcel Holtmann 	} else {
46622763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
46632763eda6SSzymon Janc 
46642763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
4665519ca9d0SMarcel Holtmann 		memcpy(cp.hash, data->hash192, sizeof(cp.hash));
466638da1703SJohan Hedberg 		memcpy(cp.rand, data->rand192, sizeof(cp.rand));
46672763eda6SSzymon Janc 
4668519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
4669519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
4670519ca9d0SMarcel Holtmann 	}
46712763eda6SSzymon Janc 
4672e1ba1f15SSzymon Janc unlock:
46732763eda6SSzymon Janc 	hci_dev_unlock(hdev);
46742763eda6SSzymon Janc }
46752763eda6SSzymon Janc 
4676a77a6a14SArron Wang #if IS_ENABLED(CONFIG_BT_HS)
4677a77a6a14SArron Wang static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
4678a77a6a14SArron Wang {
4679a77a6a14SArron Wang 	struct hci_ev_channel_selected *ev = (void *)skb->data;
4680a77a6a14SArron Wang 	struct hci_conn *hcon;
4681a77a6a14SArron Wang 
4682a77a6a14SArron Wang 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
4683a77a6a14SArron Wang 
4684a77a6a14SArron Wang 	skb_pull(skb, sizeof(*ev));
4685a77a6a14SArron Wang 
4686a77a6a14SArron Wang 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
4687a77a6a14SArron Wang 	if (!hcon)
4688a77a6a14SArron Wang 		return;
4689a77a6a14SArron Wang 
4690a77a6a14SArron Wang 	amp_read_loc_assoc_final_data(hdev, hcon);
4691a77a6a14SArron Wang }
4692a77a6a14SArron Wang 
4693d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
4694d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
4695d5e91192SAndrei Emeltchenko {
4696d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
4697d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
4698d5e91192SAndrei Emeltchenko 
4699d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
4700d5e91192SAndrei Emeltchenko 	       ev->status);
4701d5e91192SAndrei Emeltchenko 
4702d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
4703d5e91192SAndrei Emeltchenko 
4704d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
4705d5e91192SAndrei Emeltchenko 	if (!hcon) {
4706d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
4707d5e91192SAndrei Emeltchenko 		return;
4708d5e91192SAndrei Emeltchenko 	}
4709d5e91192SAndrei Emeltchenko 
4710d5e91192SAndrei Emeltchenko 	if (ev->status) {
4711d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
4712d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
4713d5e91192SAndrei Emeltchenko 		return;
4714d5e91192SAndrei Emeltchenko 	}
4715d5e91192SAndrei Emeltchenko 
4716d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
4717d5e91192SAndrei Emeltchenko 
4718d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
4719d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
4720d5e91192SAndrei Emeltchenko 
4721d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
4722d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
472376a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
4724d5e91192SAndrei Emeltchenko 
472523b9ceb7SMarcel Holtmann 	hci_debugfs_create_conn(hcon);
4726d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
4727d5e91192SAndrei Emeltchenko 
4728cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
4729cf70ff22SAndrei Emeltchenko 
4730d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
4731d5e91192SAndrei Emeltchenko }
4732d5e91192SAndrei Emeltchenko 
473327695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
473427695fb4SAndrei Emeltchenko {
473527695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
473627695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
473727695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
473827695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
473927695fb4SAndrei Emeltchenko 
474027695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
474127695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
474227695fb4SAndrei Emeltchenko 	       ev->status);
474327695fb4SAndrei Emeltchenko 
474427695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
474527695fb4SAndrei Emeltchenko 	if (!hcon)
474627695fb4SAndrei Emeltchenko 		return;
474727695fb4SAndrei Emeltchenko 
474827695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
474927695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
475027695fb4SAndrei Emeltchenko 	if (!hchan)
475127695fb4SAndrei Emeltchenko 		return;
475227695fb4SAndrei Emeltchenko 
475327695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
475427695fb4SAndrei Emeltchenko 
475527695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
475627695fb4SAndrei Emeltchenko 
475727695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
475827695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
475927695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
476027695fb4SAndrei Emeltchenko 
476127695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
476227695fb4SAndrei Emeltchenko 
476327695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
476427695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
476527695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
476627695fb4SAndrei Emeltchenko 
476727695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
476827695fb4SAndrei Emeltchenko 	}
476927695fb4SAndrei Emeltchenko }
477027695fb4SAndrei Emeltchenko 
4771606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
4772606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
4773606e2a10SAndrei Emeltchenko {
4774606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
4775606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
4776606e2a10SAndrei Emeltchenko 
4777606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
4778606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
4779606e2a10SAndrei Emeltchenko 
4780606e2a10SAndrei Emeltchenko 	if (ev->status)
4781606e2a10SAndrei Emeltchenko 		return;
4782606e2a10SAndrei Emeltchenko 
4783606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
4784606e2a10SAndrei Emeltchenko 
4785606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
4786606e2a10SAndrei Emeltchenko 	if (!hchan)
4787606e2a10SAndrei Emeltchenko 		goto unlock;
4788606e2a10SAndrei Emeltchenko 
4789606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
4790606e2a10SAndrei Emeltchenko 
4791606e2a10SAndrei Emeltchenko unlock:
4792606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
4793606e2a10SAndrei Emeltchenko }
4794606e2a10SAndrei Emeltchenko 
47959eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
47969eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
47979eef6b3aSAndrei Emeltchenko {
47989eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
47999eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
48009eef6b3aSAndrei Emeltchenko 
48019eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
48029eef6b3aSAndrei Emeltchenko 
48039eef6b3aSAndrei Emeltchenko 	if (ev->status)
48049eef6b3aSAndrei Emeltchenko 		return;
48059eef6b3aSAndrei Emeltchenko 
48069eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
48079eef6b3aSAndrei Emeltchenko 
48089eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
48099eef6b3aSAndrei Emeltchenko 	if (hcon) {
48109eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
48119eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
48129eef6b3aSAndrei Emeltchenko 	}
48139eef6b3aSAndrei Emeltchenko 
48149eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
48159eef6b3aSAndrei Emeltchenko }
4816a77a6a14SArron Wang #endif
48179eef6b3aSAndrei Emeltchenko 
4818d12fb056SJaganath Kanakkassery static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
4819d12fb056SJaganath Kanakkassery 			bdaddr_t *bdaddr, u8 bdaddr_type, u8 role, u16 handle,
4820d12fb056SJaganath Kanakkassery 			u16 interval, u16 latency, u16 supervision_timeout)
4821fcd89c09SVille Tervo {
4822912b42efSJohan Hedberg 	struct hci_conn_params *params;
4823fcd89c09SVille Tervo 	struct hci_conn *conn;
482468d6f6deSJohan Hedberg 	struct smp_irk *irk;
4825837d502eSJohan Hedberg 	u8 addr_type;
4826fcd89c09SVille Tervo 
4827fcd89c09SVille Tervo 	hci_dev_lock(hdev);
4828fcd89c09SVille Tervo 
4829fbd96c15SJohan Hedberg 	/* All controllers implicitly stop advertising in the event of a
4830fbd96c15SJohan Hedberg 	 * connection, so ensure that the state bit is cleared.
4831fbd96c15SJohan Hedberg 	 */
4832a358dc11SMarcel Holtmann 	hci_dev_clear_flag(hdev, HCI_LE_ADV);
4833fbd96c15SJohan Hedberg 
4834e7d9ab73SJakub Pawlowski 	conn = hci_lookup_le_connect(hdev);
4835b62f328bSVille Tervo 	if (!conn) {
4836d12fb056SJaganath Kanakkassery 		conn = hci_conn_add(hdev, LE_LINK, bdaddr, role);
4837b62f328bSVille Tervo 		if (!conn) {
48382064ee33SMarcel Holtmann 			bt_dev_err(hdev, "no memory for new connection");
4839230fd16aSAndre Guedes 			goto unlock;
4840b62f328bSVille Tervo 		}
484129b7988aSAndre Guedes 
4842d12fb056SJaganath Kanakkassery 		conn->dst_type = bdaddr_type;
4843b9b343d2SAndre Guedes 
4844cb1d68f7SJohan Hedberg 		/* If we didn't have a hci_conn object previously
4845cb1d68f7SJohan Hedberg 		 * but we're in master role this must be something
4846cb1d68f7SJohan Hedberg 		 * initiated using a white list. Since white list based
4847cb1d68f7SJohan Hedberg 		 * connections are not "first class citizens" we don't
4848cb1d68f7SJohan Hedberg 		 * have full tracking of them. Therefore, we go ahead
4849cb1d68f7SJohan Hedberg 		 * with a "best effort" approach of determining the
4850cb1d68f7SJohan Hedberg 		 * initiator address based on the HCI_PRIVACY flag.
4851cb1d68f7SJohan Hedberg 		 */
4852cb1d68f7SJohan Hedberg 		if (conn->out) {
4853d12fb056SJaganath Kanakkassery 			conn->resp_addr_type = bdaddr_type;
4854d12fb056SJaganath Kanakkassery 			bacpy(&conn->resp_addr, bdaddr);
4855d7a5a11dSMarcel Holtmann 			if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
4856cb1d68f7SJohan Hedberg 				conn->init_addr_type = ADDR_LE_DEV_RANDOM;
4857cb1d68f7SJohan Hedberg 				bacpy(&conn->init_addr, &hdev->rpa);
4858cb1d68f7SJohan Hedberg 			} else {
4859cb1d68f7SJohan Hedberg 				hci_copy_identity_address(hdev,
4860cb1d68f7SJohan Hedberg 							  &conn->init_addr,
4861cb1d68f7SJohan Hedberg 							  &conn->init_addr_type);
4862cb1d68f7SJohan Hedberg 			}
486380c24ab8SJohan Hedberg 		}
4864cb1d68f7SJohan Hedberg 	} else {
486580c24ab8SJohan Hedberg 		cancel_delayed_work(&conn->le_conn_timeout);
486680c24ab8SJohan Hedberg 	}
486780c24ab8SJohan Hedberg 
486880c24ab8SJohan Hedberg 	if (!conn->out) {
4869cb1d68f7SJohan Hedberg 		/* Set the responder (our side) address type based on
4870cb1d68f7SJohan Hedberg 		 * the advertising address type.
4871cb1d68f7SJohan Hedberg 		 */
4872cb1d68f7SJohan Hedberg 		conn->resp_addr_type = hdev->adv_addr_type;
4873acf0aeaeSJaganath Kanakkassery 		if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) {
4874acf0aeaeSJaganath Kanakkassery 			/* In case of ext adv, resp_addr will be updated in
4875acf0aeaeSJaganath Kanakkassery 			 * Adv Terminated event.
4876acf0aeaeSJaganath Kanakkassery 			 */
4877acf0aeaeSJaganath Kanakkassery 			if (!ext_adv_capable(hdev))
4878cb1d68f7SJohan Hedberg 				bacpy(&conn->resp_addr, &hdev->random_addr);
4879acf0aeaeSJaganath Kanakkassery 		} else {
4880cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &hdev->bdaddr);
4881acf0aeaeSJaganath Kanakkassery 		}
4882cb1d68f7SJohan Hedberg 
4883d12fb056SJaganath Kanakkassery 		conn->init_addr_type = bdaddr_type;
4884d12fb056SJaganath Kanakkassery 		bacpy(&conn->init_addr, bdaddr);
4885a720d735SMarcel Holtmann 
4886a720d735SMarcel Holtmann 		/* For incoming connections, set the default minimum
4887a720d735SMarcel Holtmann 		 * and maximum connection interval. They will be used
4888a720d735SMarcel Holtmann 		 * to check if the parameters are in range and if not
4889a720d735SMarcel Holtmann 		 * trigger the connection update procedure.
4890a720d735SMarcel Holtmann 		 */
4891a720d735SMarcel Holtmann 		conn->le_conn_min_interval = hdev->le_conn_min_interval;
4892a720d735SMarcel Holtmann 		conn->le_conn_max_interval = hdev->le_conn_max_interval;
4893cb1d68f7SJohan Hedberg 	}
48947be2edbbSJohan Hedberg 
4895edb4b466SMarcel Holtmann 	/* Lookup the identity address from the stored connection
4896edb4b466SMarcel Holtmann 	 * address and address type.
4897edb4b466SMarcel Holtmann 	 *
4898edb4b466SMarcel Holtmann 	 * When establishing connections to an identity address, the
4899edb4b466SMarcel Holtmann 	 * connection procedure will store the resolvable random
4900edb4b466SMarcel Holtmann 	 * address first. Now if it can be converted back into the
4901edb4b466SMarcel Holtmann 	 * identity address, start using the identity address from
4902edb4b466SMarcel Holtmann 	 * now on.
4903edb4b466SMarcel Holtmann 	 */
4904edb4b466SMarcel Holtmann 	irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
490568d6f6deSJohan Hedberg 	if (irk) {
490668d6f6deSJohan Hedberg 		bacpy(&conn->dst, &irk->bdaddr);
490768d6f6deSJohan Hedberg 		conn->dst_type = irk->addr_type;
490868d6f6deSJohan Hedberg 	}
490968d6f6deSJohan Hedberg 
4910d12fb056SJaganath Kanakkassery 	if (status) {
4911d12fb056SJaganath Kanakkassery 		hci_le_conn_failed(conn, status);
4912837d502eSJohan Hedberg 		goto unlock;
4913837d502eSJohan Hedberg 	}
4914837d502eSJohan Hedberg 
491508853f18SJohan Hedberg 	if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
491608853f18SJohan Hedberg 		addr_type = BDADDR_LE_PUBLIC;
491708853f18SJohan Hedberg 	else
491808853f18SJohan Hedberg 		addr_type = BDADDR_LE_RANDOM;
491908853f18SJohan Hedberg 
49202d3c2260SJohan Hedberg 	/* Drop the connection if the device is blocked */
49212d3c2260SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) {
49222d3c2260SJohan Hedberg 		hci_conn_drop(conn);
4923cd17decbSAndre Guedes 		goto unlock;
4924cd17decbSAndre Guedes 	}
4925cd17decbSAndre Guedes 
4926b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
492748ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
492883bc71b4SVinicius Costa Gomes 
49297b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
4930d12fb056SJaganath Kanakkassery 	conn->handle = handle;
49310fe29fd1SMarcel Holtmann 	conn->state = BT_CONFIG;
4932fcd89c09SVille Tervo 
4933d12fb056SJaganath Kanakkassery 	conn->le_conn_interval = interval;
4934d12fb056SJaganath Kanakkassery 	conn->le_conn_latency = latency;
4935d12fb056SJaganath Kanakkassery 	conn->le_supv_timeout = supervision_timeout;
4936e04fde60SMarcel Holtmann 
493723b9ceb7SMarcel Holtmann 	hci_debugfs_create_conn(conn);
4938fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
4939fcd89c09SVille Tervo 
49400fe29fd1SMarcel Holtmann 	/* The remote features procedure is defined for master
49410fe29fd1SMarcel Holtmann 	 * role only. So only in case of an initiated connection
49420fe29fd1SMarcel Holtmann 	 * request the remote features.
49430fe29fd1SMarcel Holtmann 	 *
49440fe29fd1SMarcel Holtmann 	 * If the local controller supports slave-initiated features
49450fe29fd1SMarcel Holtmann 	 * exchange, then requesting the remote features in slave
49460fe29fd1SMarcel Holtmann 	 * role is possible. Otherwise just transition into the
49470fe29fd1SMarcel Holtmann 	 * connected state without requesting the remote features.
49480fe29fd1SMarcel Holtmann 	 */
49490fe29fd1SMarcel Holtmann 	if (conn->out ||
49500fe29fd1SMarcel Holtmann 	    (hdev->le_features[0] & HCI_LE_SLAVE_FEATURES)) {
49510fe29fd1SMarcel Holtmann 		struct hci_cp_le_read_remote_features cp;
49520fe29fd1SMarcel Holtmann 
49530fe29fd1SMarcel Holtmann 		cp.handle = __cpu_to_le16(conn->handle);
49540fe29fd1SMarcel Holtmann 
49550fe29fd1SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_LE_READ_REMOTE_FEATURES,
49560fe29fd1SMarcel Holtmann 			     sizeof(cp), &cp);
49570fe29fd1SMarcel Holtmann 
49580fe29fd1SMarcel Holtmann 		hci_conn_hold(conn);
49590fe29fd1SMarcel Holtmann 	} else {
49600fe29fd1SMarcel Holtmann 		conn->state = BT_CONNECTED;
4961d12fb056SJaganath Kanakkassery 		hci_connect_cfm(conn, status);
49620fe29fd1SMarcel Holtmann 	}
4963fcd89c09SVille Tervo 
49645477610fSJohan Hedberg 	params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
49655477610fSJohan Hedberg 					   conn->dst_type);
4966f161dd41SJohan Hedberg 	if (params) {
496795305baaSJohan Hedberg 		list_del_init(&params->action);
4968f161dd41SJohan Hedberg 		if (params->conn) {
4969f161dd41SJohan Hedberg 			hci_conn_drop(params->conn);
4970f8aaf9b6SJohan Hedberg 			hci_conn_put(params->conn);
4971f161dd41SJohan Hedberg 			params->conn = NULL;
4972f161dd41SJohan Hedberg 		}
4973f161dd41SJohan Hedberg 	}
4974a4790dbdSAndre Guedes 
4975fcd89c09SVille Tervo unlock:
4976223683a5SJohan Hedberg 	hci_update_background_scan(hdev);
4977fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
4978fcd89c09SVille Tervo }
4979fcd89c09SVille Tervo 
4980d12fb056SJaganath Kanakkassery static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
4981d12fb056SJaganath Kanakkassery {
4982d12fb056SJaganath Kanakkassery 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
4983d12fb056SJaganath Kanakkassery 
4984d12fb056SJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
4985d12fb056SJaganath Kanakkassery 
4986d12fb056SJaganath Kanakkassery 	le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
4987d12fb056SJaganath Kanakkassery 			     ev->role, le16_to_cpu(ev->handle),
4988d12fb056SJaganath Kanakkassery 			     le16_to_cpu(ev->interval),
4989d12fb056SJaganath Kanakkassery 			     le16_to_cpu(ev->latency),
4990d12fb056SJaganath Kanakkassery 			     le16_to_cpu(ev->supervision_timeout));
4991d12fb056SJaganath Kanakkassery }
4992d12fb056SJaganath Kanakkassery 
49934d94f95dSJaganath Kanakkassery static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
49944d94f95dSJaganath Kanakkassery 					 struct sk_buff *skb)
49954d94f95dSJaganath Kanakkassery {
49964d94f95dSJaganath Kanakkassery 	struct hci_ev_le_enh_conn_complete *ev = (void *) skb->data;
49974d94f95dSJaganath Kanakkassery 
49984d94f95dSJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
49994d94f95dSJaganath Kanakkassery 
50004d94f95dSJaganath Kanakkassery 	le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
50014d94f95dSJaganath Kanakkassery 			     ev->role, le16_to_cpu(ev->handle),
50024d94f95dSJaganath Kanakkassery 			     le16_to_cpu(ev->interval),
50034d94f95dSJaganath Kanakkassery 			     le16_to_cpu(ev->latency),
50044d94f95dSJaganath Kanakkassery 			     le16_to_cpu(ev->supervision_timeout));
50054d94f95dSJaganath Kanakkassery }
50064d94f95dSJaganath Kanakkassery 
5007acf0aeaeSJaganath Kanakkassery static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
5008acf0aeaeSJaganath Kanakkassery {
5009acf0aeaeSJaganath Kanakkassery 	struct hci_evt_le_ext_adv_set_term *ev = (void *) skb->data;
5010acf0aeaeSJaganath Kanakkassery 	struct hci_conn *conn;
5011acf0aeaeSJaganath Kanakkassery 
5012acf0aeaeSJaganath Kanakkassery 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
5013acf0aeaeSJaganath Kanakkassery 
5014acf0aeaeSJaganath Kanakkassery 	if (ev->status)
5015acf0aeaeSJaganath Kanakkassery 		return;
5016acf0aeaeSJaganath Kanakkassery 
5017acf0aeaeSJaganath Kanakkassery 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->conn_handle));
5018acf0aeaeSJaganath Kanakkassery 	if (conn) {
5019acf0aeaeSJaganath Kanakkassery 		struct adv_info *adv_instance;
5020acf0aeaeSJaganath Kanakkassery 
5021acf0aeaeSJaganath Kanakkassery 		if (hdev->adv_addr_type != ADDR_LE_DEV_RANDOM)
5022acf0aeaeSJaganath Kanakkassery 			return;
5023acf0aeaeSJaganath Kanakkassery 
5024acf0aeaeSJaganath Kanakkassery 		if (!hdev->cur_adv_instance) {
5025acf0aeaeSJaganath Kanakkassery 			bacpy(&conn->resp_addr, &hdev->random_addr);
5026acf0aeaeSJaganath Kanakkassery 			return;
5027acf0aeaeSJaganath Kanakkassery 		}
5028acf0aeaeSJaganath Kanakkassery 
5029acf0aeaeSJaganath Kanakkassery 		adv_instance = hci_find_adv_instance(hdev, hdev->cur_adv_instance);
5030acf0aeaeSJaganath Kanakkassery 		if (adv_instance)
5031acf0aeaeSJaganath Kanakkassery 			bacpy(&conn->resp_addr, &adv_instance->random_addr);
5032acf0aeaeSJaganath Kanakkassery 	}
5033acf0aeaeSJaganath Kanakkassery }
5034acf0aeaeSJaganath Kanakkassery 
50351855d92dSMarcel Holtmann static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
50361855d92dSMarcel Holtmann 					    struct sk_buff *skb)
50371855d92dSMarcel Holtmann {
50381855d92dSMarcel Holtmann 	struct hci_ev_le_conn_update_complete *ev = (void *) skb->data;
50391855d92dSMarcel Holtmann 	struct hci_conn *conn;
50401855d92dSMarcel Holtmann 
50411855d92dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
50421855d92dSMarcel Holtmann 
50431855d92dSMarcel Holtmann 	if (ev->status)
50441855d92dSMarcel Holtmann 		return;
50451855d92dSMarcel Holtmann 
50461855d92dSMarcel Holtmann 	hci_dev_lock(hdev);
50471855d92dSMarcel Holtmann 
50481855d92dSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
50491855d92dSMarcel Holtmann 	if (conn) {
50501855d92dSMarcel Holtmann 		conn->le_conn_interval = le16_to_cpu(ev->interval);
50511855d92dSMarcel Holtmann 		conn->le_conn_latency = le16_to_cpu(ev->latency);
50521855d92dSMarcel Holtmann 		conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
50531855d92dSMarcel Holtmann 	}
50541855d92dSMarcel Holtmann 
50551855d92dSMarcel Holtmann 	hci_dev_unlock(hdev);
50561855d92dSMarcel Holtmann }
50571855d92dSMarcel Holtmann 
5058a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */
5059fd45ada9SAlfonso Acosta static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
5060fd45ada9SAlfonso Acosta 					      bdaddr_t *addr,
5061082f2300SSzymon Janc 					      u8 addr_type, u8 adv_type,
5062082f2300SSzymon Janc 					      bdaddr_t *direct_rpa)
5063a4790dbdSAndre Guedes {
5064a4790dbdSAndre Guedes 	struct hci_conn *conn;
50654b9e7e75SMarcel Holtmann 	struct hci_conn_params *params;
5066a4790dbdSAndre Guedes 
50671c1abcabSJohan Hedberg 	/* If the event is not connectable don't proceed further */
50681c1abcabSJohan Hedberg 	if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND)
5069fd45ada9SAlfonso Acosta 		return NULL;
50701c1abcabSJohan Hedberg 
50711c1abcabSJohan Hedberg 	/* Ignore if the device is blocked */
5072dcc36c16SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type))
5073fd45ada9SAlfonso Acosta 		return NULL;
50741c1abcabSJohan Hedberg 
5075f99353cfSJohan Hedberg 	/* Most controller will fail if we try to create new connections
5076f99353cfSJohan Hedberg 	 * while we have an existing one in slave role.
5077f99353cfSJohan Hedberg 	 */
5078f99353cfSJohan Hedberg 	if (hdev->conn_hash.le_num_slave > 0)
5079fd45ada9SAlfonso Acosta 		return NULL;
5080f99353cfSJohan Hedberg 
50811c1abcabSJohan Hedberg 	/* If we're not connectable only connect devices that we have in
50821c1abcabSJohan Hedberg 	 * our pend_le_conns list.
50831c1abcabSJohan Hedberg 	 */
508449c50922SJohan Hedberg 	params = hci_pend_le_action_lookup(&hdev->pend_le_conns, addr,
508549c50922SJohan Hedberg 					   addr_type);
50864b9e7e75SMarcel Holtmann 	if (!params)
5087fd45ada9SAlfonso Acosta 		return NULL;
5088a4790dbdSAndre Guedes 
508928a667c9SJakub Pawlowski 	if (!params->explicit_connect) {
50904b9e7e75SMarcel Holtmann 		switch (params->auto_connect) {
50914b9e7e75SMarcel Holtmann 		case HCI_AUTO_CONN_DIRECT:
50924b9e7e75SMarcel Holtmann 			/* Only devices advertising with ADV_DIRECT_IND are
50934b9e7e75SMarcel Holtmann 			 * triggering a connection attempt. This is allowing
50944b9e7e75SMarcel Holtmann 			 * incoming connections from slave devices.
50954b9e7e75SMarcel Holtmann 			 */
50964b9e7e75SMarcel Holtmann 			if (adv_type != LE_ADV_DIRECT_IND)
5097fd45ada9SAlfonso Acosta 				return NULL;
50984b9e7e75SMarcel Holtmann 			break;
50994b9e7e75SMarcel Holtmann 		case HCI_AUTO_CONN_ALWAYS:
51004b9e7e75SMarcel Holtmann 			/* Devices advertising with ADV_IND or ADV_DIRECT_IND
51014b9e7e75SMarcel Holtmann 			 * are triggering a connection attempt. This means
51024b9e7e75SMarcel Holtmann 			 * that incoming connectioms from slave device are
51034b9e7e75SMarcel Holtmann 			 * accepted and also outgoing connections to slave
51044b9e7e75SMarcel Holtmann 			 * devices are established when found.
51054b9e7e75SMarcel Holtmann 			 */
51064b9e7e75SMarcel Holtmann 			break;
51074b9e7e75SMarcel Holtmann 		default:
5108fd45ada9SAlfonso Acosta 			return NULL;
51094b9e7e75SMarcel Holtmann 		}
511028a667c9SJakub Pawlowski 	}
51114b9e7e75SMarcel Holtmann 
5112a4790dbdSAndre Guedes 	conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
5113082f2300SSzymon Janc 			      HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER,
5114082f2300SSzymon Janc 			      direct_rpa);
5115f161dd41SJohan Hedberg 	if (!IS_ERR(conn)) {
511628a667c9SJakub Pawlowski 		/* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned
511728a667c9SJakub Pawlowski 		 * by higher layer that tried to connect, if no then
511828a667c9SJakub Pawlowski 		 * store the pointer since we don't really have any
5119f161dd41SJohan Hedberg 		 * other owner of the object besides the params that
5120f161dd41SJohan Hedberg 		 * triggered it. This way we can abort the connection if
5121f161dd41SJohan Hedberg 		 * the parameters get removed and keep the reference
5122f161dd41SJohan Hedberg 		 * count consistent once the connection is established.
5123f161dd41SJohan Hedberg 		 */
512428a667c9SJakub Pawlowski 
512528a667c9SJakub Pawlowski 		if (!params->explicit_connect)
5126f8aaf9b6SJohan Hedberg 			params->conn = hci_conn_get(conn);
512728a667c9SJakub Pawlowski 
5128fd45ada9SAlfonso Acosta 		return conn;
5129f161dd41SJohan Hedberg 	}
5130a4790dbdSAndre Guedes 
5131a4790dbdSAndre Guedes 	switch (PTR_ERR(conn)) {
5132a4790dbdSAndre Guedes 	case -EBUSY:
5133a4790dbdSAndre Guedes 		/* If hci_connect() returns -EBUSY it means there is already
5134a4790dbdSAndre Guedes 		 * an LE connection attempt going on. Since controllers don't
5135a4790dbdSAndre Guedes 		 * support more than one connection attempt at the time, we
5136a4790dbdSAndre Guedes 		 * don't consider this an error case.
5137a4790dbdSAndre Guedes 		 */
5138a4790dbdSAndre Guedes 		break;
5139a4790dbdSAndre Guedes 	default:
5140a4790dbdSAndre Guedes 		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
5141fd45ada9SAlfonso Acosta 		return NULL;
5142a4790dbdSAndre Guedes 	}
5143fd45ada9SAlfonso Acosta 
5144fd45ada9SAlfonso Acosta 	return NULL;
5145a4790dbdSAndre Guedes }
5146a4790dbdSAndre Guedes 
51474af605d8SJohan Hedberg static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
51482f010b55SMarcel Holtmann 			       u8 bdaddr_type, bdaddr_t *direct_addr,
51492f010b55SMarcel Holtmann 			       u8 direct_addr_type, s8 rssi, u8 *data, u8 len)
51504af605d8SJohan Hedberg {
5151b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
51521c1abcabSJohan Hedberg 	struct smp_irk *irk;
5153fd45ada9SAlfonso Acosta 	struct hci_conn *conn;
5154474ee066SJohan Hedberg 	bool match;
5155c70a7e4cSMarcel Holtmann 	u32 flags;
51566818375eSSzymon Janc 	u8 *ptr, real_len;
51576818375eSSzymon Janc 
515856b40fbfSJohan Hedberg 	switch (type) {
515956b40fbfSJohan Hedberg 	case LE_ADV_IND:
516056b40fbfSJohan Hedberg 	case LE_ADV_DIRECT_IND:
516156b40fbfSJohan Hedberg 	case LE_ADV_SCAN_IND:
516256b40fbfSJohan Hedberg 	case LE_ADV_NONCONN_IND:
516356b40fbfSJohan Hedberg 	case LE_ADV_SCAN_RSP:
516456b40fbfSJohan Hedberg 		break;
516556b40fbfSJohan Hedberg 	default:
51662064ee33SMarcel Holtmann 		bt_dev_err_ratelimited(hdev, "unknown advertising packet "
51672064ee33SMarcel Holtmann 				       "type: 0x%02x", type);
516856b40fbfSJohan Hedberg 		return;
516956b40fbfSJohan Hedberg 	}
517056b40fbfSJohan Hedberg 
51716818375eSSzymon Janc 	/* Find the end of the data in case the report contains padded zero
51726818375eSSzymon Janc 	 * bytes at the end causing an invalid length value.
51736818375eSSzymon Janc 	 *
51746818375eSSzymon Janc 	 * When data is NULL, len is 0 so there is no need for extra ptr
51756818375eSSzymon Janc 	 * check as 'ptr < data + 0' is already false in such case.
51766818375eSSzymon Janc 	 */
51776818375eSSzymon Janc 	for (ptr = data; ptr < data + len && *ptr; ptr += *ptr + 1) {
51786818375eSSzymon Janc 		if (ptr + 1 + *ptr > data + len)
51796818375eSSzymon Janc 			break;
51806818375eSSzymon Janc 	}
51816818375eSSzymon Janc 
51826818375eSSzymon Janc 	real_len = ptr - data;
51836818375eSSzymon Janc 
51846818375eSSzymon Janc 	/* Adjust for actual length */
51856818375eSSzymon Janc 	if (len != real_len) {
51862064ee33SMarcel Holtmann 		bt_dev_err_ratelimited(hdev, "advertising data len corrected");
51876818375eSSzymon Janc 		len = real_len;
51886818375eSSzymon Janc 	}
5189b9a6328fSJohan Hedberg 
51902f010b55SMarcel Holtmann 	/* If the direct address is present, then this report is from
51912f010b55SMarcel Holtmann 	 * a LE Direct Advertising Report event. In that case it is
51922f010b55SMarcel Holtmann 	 * important to see if the address is matching the local
51932f010b55SMarcel Holtmann 	 * controller address.
51942f010b55SMarcel Holtmann 	 */
51952f010b55SMarcel Holtmann 	if (direct_addr) {
51962f010b55SMarcel Holtmann 		/* Only resolvable random addresses are valid for these
51972f010b55SMarcel Holtmann 		 * kind of reports and others can be ignored.
51982f010b55SMarcel Holtmann 		 */
51992f010b55SMarcel Holtmann 		if (!hci_bdaddr_is_rpa(direct_addr, direct_addr_type))
52002f010b55SMarcel Holtmann 			return;
52012f010b55SMarcel Holtmann 
52022f010b55SMarcel Holtmann 		/* If the controller is not using resolvable random
52032f010b55SMarcel Holtmann 		 * addresses, then this report can be ignored.
52042f010b55SMarcel Holtmann 		 */
5205d7a5a11dSMarcel Holtmann 		if (!hci_dev_test_flag(hdev, HCI_PRIVACY))
52062f010b55SMarcel Holtmann 			return;
52072f010b55SMarcel Holtmann 
52082f010b55SMarcel Holtmann 		/* If the local IRK of the controller does not match
52092f010b55SMarcel Holtmann 		 * with the resolvable random address provided, then
52102f010b55SMarcel Holtmann 		 * this report can be ignored.
52112f010b55SMarcel Holtmann 		 */
52122f010b55SMarcel Holtmann 		if (!smp_irk_matches(hdev, hdev->irk, direct_addr))
52132f010b55SMarcel Holtmann 			return;
52142f010b55SMarcel Holtmann 	}
52152f010b55SMarcel Holtmann 
5216435a13d8SJohan Hedberg 	/* Check if we need to convert to identity address */
5217435a13d8SJohan Hedberg 	irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
5218435a13d8SJohan Hedberg 	if (irk) {
5219435a13d8SJohan Hedberg 		bdaddr = &irk->bdaddr;
5220435a13d8SJohan Hedberg 		bdaddr_type = irk->addr_type;
5221435a13d8SJohan Hedberg 	}
5222435a13d8SJohan Hedberg 
5223082f2300SSzymon Janc 	/* Check if we have been requested to connect to this device.
5224082f2300SSzymon Janc 	 *
5225082f2300SSzymon Janc 	 * direct_addr is set only for directed advertising reports (it is NULL
5226082f2300SSzymon Janc 	 * for advertising reports) and is already verified to be RPA above.
5227082f2300SSzymon Janc 	 */
5228082f2300SSzymon Janc 	conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type,
5229082f2300SSzymon Janc 								direct_addr);
5230fd45ada9SAlfonso Acosta 	if (conn && type == LE_ADV_IND) {
5231fd45ada9SAlfonso Acosta 		/* Store report for later inclusion by
5232fd45ada9SAlfonso Acosta 		 * mgmt_device_connected
5233fd45ada9SAlfonso Acosta 		 */
5234fd45ada9SAlfonso Acosta 		memcpy(conn->le_adv_data, data, len);
5235fd45ada9SAlfonso Acosta 		conn->le_adv_data_len = len;
5236fd45ada9SAlfonso Acosta 	}
523799a6768eSJohan Hedberg 
52381c1abcabSJohan Hedberg 	/* Passive scanning shouldn't trigger any device found events,
52391c1abcabSJohan Hedberg 	 * except for devices marked as CONN_REPORT for which we do send
52401c1abcabSJohan Hedberg 	 * device found events.
52411c1abcabSJohan Hedberg 	 */
52421c1abcabSJohan Hedberg 	if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
52430d2bf134SJohan Hedberg 		if (type == LE_ADV_DIRECT_IND)
52440d2bf134SJohan Hedberg 			return;
52450d2bf134SJohan Hedberg 
52463a19b6feSJohan Hedberg 		if (!hci_pend_le_action_lookup(&hdev->pend_le_reports,
52473a19b6feSJohan Hedberg 					       bdaddr, bdaddr_type))
52480d2bf134SJohan Hedberg 			return;
52490d2bf134SJohan Hedberg 
52500d2bf134SJohan Hedberg 		if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND)
52510d2bf134SJohan Hedberg 			flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
52520d2bf134SJohan Hedberg 		else
52530d2bf134SJohan Hedberg 			flags = 0;
52540d2bf134SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
52550d2bf134SJohan Hedberg 				  rssi, flags, data, len, NULL, 0);
525697bf2e99SJohan Hedberg 		return;
5257ca5c4be7SJohan Hedberg 	}
52584af605d8SJohan Hedberg 
5259c70a7e4cSMarcel Holtmann 	/* When receiving non-connectable or scannable undirected
5260c70a7e4cSMarcel Holtmann 	 * advertising reports, this means that the remote device is
5261c70a7e4cSMarcel Holtmann 	 * not connectable and then clearly indicate this in the
5262c70a7e4cSMarcel Holtmann 	 * device found event.
5263c70a7e4cSMarcel Holtmann 	 *
5264c70a7e4cSMarcel Holtmann 	 * When receiving a scan response, then there is no way to
5265c70a7e4cSMarcel Holtmann 	 * know if the remote device is connectable or not. However
5266c70a7e4cSMarcel Holtmann 	 * since scan responses are merged with a previously seen
5267c70a7e4cSMarcel Holtmann 	 * advertising report, the flags field from that report
5268c70a7e4cSMarcel Holtmann 	 * will be used.
5269c70a7e4cSMarcel Holtmann 	 *
5270c70a7e4cSMarcel Holtmann 	 * In the really unlikely case that a controller get confused
5271c70a7e4cSMarcel Holtmann 	 * and just sends a scan response event, then it is marked as
5272c70a7e4cSMarcel Holtmann 	 * not connectable as well.
5273c70a7e4cSMarcel Holtmann 	 */
5274c70a7e4cSMarcel Holtmann 	if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND ||
5275c70a7e4cSMarcel Holtmann 	    type == LE_ADV_SCAN_RSP)
5276c70a7e4cSMarcel Holtmann 		flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
5277c70a7e4cSMarcel Holtmann 	else
5278c70a7e4cSMarcel Holtmann 		flags = 0;
5279c70a7e4cSMarcel Holtmann 
5280b9a6328fSJohan Hedberg 	/* If there's nothing pending either store the data from this
5281b9a6328fSJohan Hedberg 	 * event or send an immediate device found event if the data
5282b9a6328fSJohan Hedberg 	 * should not be stored for later.
5283b9a6328fSJohan Hedberg 	 */
5284b9a6328fSJohan Hedberg 	if (!has_pending_adv_report(hdev)) {
5285b9a6328fSJohan Hedberg 		/* If the report will trigger a SCAN_REQ store it for
5286b9a6328fSJohan Hedberg 		 * later merging.
5287b9a6328fSJohan Hedberg 		 */
5288b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
5289b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
5290c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
5291b9a6328fSJohan Hedberg 			return;
5292b9a6328fSJohan Hedberg 		}
5293b9a6328fSJohan Hedberg 
5294b9a6328fSJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
5295c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
5296b9a6328fSJohan Hedberg 		return;
5297b9a6328fSJohan Hedberg 	}
5298b9a6328fSJohan Hedberg 
5299474ee066SJohan Hedberg 	/* Check if the pending report is for the same device as the new one */
5300474ee066SJohan Hedberg 	match = (!bacmp(bdaddr, &d->last_adv_addr) &&
5301474ee066SJohan Hedberg 		 bdaddr_type == d->last_adv_addr_type);
5302474ee066SJohan Hedberg 
5303b9a6328fSJohan Hedberg 	/* If the pending data doesn't match this report or this isn't a
5304b9a6328fSJohan Hedberg 	 * scan response (e.g. we got a duplicate ADV_IND) then force
5305b9a6328fSJohan Hedberg 	 * sending of the pending data.
5306b9a6328fSJohan Hedberg 	 */
5307474ee066SJohan Hedberg 	if (type != LE_ADV_SCAN_RSP || !match) {
5308474ee066SJohan Hedberg 		/* Send out whatever is in the cache, but skip duplicates */
5309474ee066SJohan Hedberg 		if (!match)
5310b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
5311ff5cd29fSJohan Hedberg 					  d->last_adv_addr_type, NULL,
5312c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
5313ff5cd29fSJohan Hedberg 					  d->last_adv_data,
5314474ee066SJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
5315b9a6328fSJohan Hedberg 
5316b9a6328fSJohan Hedberg 		/* If the new report will trigger a SCAN_REQ store it for
5317b9a6328fSJohan Hedberg 		 * later merging.
5318b9a6328fSJohan Hedberg 		 */
5319b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
5320b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
5321c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
5322b9a6328fSJohan Hedberg 			return;
5323b9a6328fSJohan Hedberg 		}
5324b9a6328fSJohan Hedberg 
5325b9a6328fSJohan Hedberg 		/* The advertising reports cannot be merged, so clear
5326b9a6328fSJohan Hedberg 		 * the pending report and send out a device found event.
5327b9a6328fSJohan Hedberg 		 */
5328b9a6328fSJohan Hedberg 		clear_pending_adv_report(hdev);
53295c5b93e4SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
5330c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
5331b9a6328fSJohan Hedberg 		return;
5332b9a6328fSJohan Hedberg 	}
5333b9a6328fSJohan Hedberg 
5334b9a6328fSJohan Hedberg 	/* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
5335b9a6328fSJohan Hedberg 	 * the new event is a SCAN_RSP. We can therefore proceed with
5336b9a6328fSJohan Hedberg 	 * sending a merged device found event.
5337b9a6328fSJohan Hedberg 	 */
5338b9a6328fSJohan Hedberg 	mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
5339c70a7e4cSMarcel Holtmann 			  d->last_adv_addr_type, NULL, rssi, d->last_adv_flags,
534042bd6a56SMarcel Holtmann 			  d->last_adv_data, d->last_adv_data_len, data, len);
5341b9a6328fSJohan Hedberg 	clear_pending_adv_report(hdev);
53424af605d8SJohan Hedberg }
53434af605d8SJohan Hedberg 
53446039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
53459aa04c91SAndre Guedes {
5346e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
5347e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
53489aa04c91SAndre Guedes 
5349a4790dbdSAndre Guedes 	hci_dev_lock(hdev);
5350a4790dbdSAndre Guedes 
5351e95beb41SAndre Guedes 	while (num_reports--) {
5352e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
53534af605d8SJohan Hedberg 		s8 rssi;
5354a4790dbdSAndre Guedes 
5355ee649346SChriz Chow 		if (ev->length <= HCI_MAX_AD_LENGTH) {
53563c9e9195SAndre Guedes 			rssi = ev->data[ev->length];
53574af605d8SJohan Hedberg 			process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
53582f010b55SMarcel Holtmann 					   ev->bdaddr_type, NULL, 0, rssi,
53592f010b55SMarcel Holtmann 					   ev->data, ev->length);
5360ee649346SChriz Chow 		} else {
5361ee649346SChriz Chow 			bt_dev_err(hdev, "Dropping invalid advertising data");
5362ee649346SChriz Chow 		}
53633c9e9195SAndre Guedes 
5364e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
53659aa04c91SAndre Guedes 	}
5366a4790dbdSAndre Guedes 
5367a4790dbdSAndre Guedes 	hci_dev_unlock(hdev);
53689aa04c91SAndre Guedes }
53699aa04c91SAndre Guedes 
5370b2cc9761SJaganath Kanakkassery static u8 ext_evt_type_to_legacy(u16 evt_type)
5371c215e939SJaganath Kanakkassery {
5372b2cc9761SJaganath Kanakkassery 	if (evt_type & LE_EXT_ADV_LEGACY_PDU) {
5373c215e939SJaganath Kanakkassery 		switch (evt_type) {
5374c215e939SJaganath Kanakkassery 		case LE_LEGACY_ADV_IND:
5375c215e939SJaganath Kanakkassery 			return LE_ADV_IND;
5376c215e939SJaganath Kanakkassery 		case LE_LEGACY_ADV_DIRECT_IND:
5377c215e939SJaganath Kanakkassery 			return LE_ADV_DIRECT_IND;
5378c215e939SJaganath Kanakkassery 		case LE_LEGACY_ADV_SCAN_IND:
5379c215e939SJaganath Kanakkassery 			return LE_ADV_SCAN_IND;
5380c215e939SJaganath Kanakkassery 		case LE_LEGACY_NONCONN_IND:
5381c215e939SJaganath Kanakkassery 			return LE_ADV_NONCONN_IND;
5382c215e939SJaganath Kanakkassery 		case LE_LEGACY_SCAN_RSP_ADV:
5383c215e939SJaganath Kanakkassery 		case LE_LEGACY_SCAN_RSP_ADV_SCAN:
5384c215e939SJaganath Kanakkassery 			return LE_ADV_SCAN_RSP;
5385c215e939SJaganath Kanakkassery 		}
5386c215e939SJaganath Kanakkassery 
5387c215e939SJaganath Kanakkassery 		BT_ERR_RATELIMITED("Unknown advertising packet type: 0x%02x",
5388c215e939SJaganath Kanakkassery 				   evt_type);
5389c215e939SJaganath Kanakkassery 
5390c215e939SJaganath Kanakkassery 		return LE_ADV_INVALID;
5391c215e939SJaganath Kanakkassery 	}
5392c215e939SJaganath Kanakkassery 
5393b2cc9761SJaganath Kanakkassery 	if (evt_type & LE_EXT_ADV_CONN_IND) {
5394b2cc9761SJaganath Kanakkassery 		if (evt_type & LE_EXT_ADV_DIRECT_IND)
5395b2cc9761SJaganath Kanakkassery 			return LE_ADV_DIRECT_IND;
5396b2cc9761SJaganath Kanakkassery 
5397b2cc9761SJaganath Kanakkassery 		return LE_ADV_IND;
5398b2cc9761SJaganath Kanakkassery 	}
5399b2cc9761SJaganath Kanakkassery 
5400b2cc9761SJaganath Kanakkassery 	if (evt_type & LE_EXT_ADV_SCAN_RSP)
5401b2cc9761SJaganath Kanakkassery 		return LE_ADV_SCAN_RSP;
5402b2cc9761SJaganath Kanakkassery 
5403b2cc9761SJaganath Kanakkassery 	if (evt_type & LE_EXT_ADV_SCAN_IND)
5404b2cc9761SJaganath Kanakkassery 		return LE_ADV_SCAN_IND;
5405b2cc9761SJaganath Kanakkassery 
5406b2cc9761SJaganath Kanakkassery 	if (evt_type == LE_EXT_ADV_NON_CONN_IND ||
5407b2cc9761SJaganath Kanakkassery 	    evt_type & LE_EXT_ADV_DIRECT_IND)
5408b2cc9761SJaganath Kanakkassery 		return LE_ADV_NONCONN_IND;
5409b2cc9761SJaganath Kanakkassery 
5410b2cc9761SJaganath Kanakkassery 	BT_ERR_RATELIMITED("Unknown advertising packet type: 0x%02x",
5411b2cc9761SJaganath Kanakkassery 				   evt_type);
5412b2cc9761SJaganath Kanakkassery 
5413b2cc9761SJaganath Kanakkassery 	return LE_ADV_INVALID;
5414b2cc9761SJaganath Kanakkassery }
5415b2cc9761SJaganath Kanakkassery 
5416c215e939SJaganath Kanakkassery static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
5417c215e939SJaganath Kanakkassery {
5418c215e939SJaganath Kanakkassery 	u8 num_reports = skb->data[0];
5419c215e939SJaganath Kanakkassery 	void *ptr = &skb->data[1];
5420c215e939SJaganath Kanakkassery 
5421c215e939SJaganath Kanakkassery 	hci_dev_lock(hdev);
5422c215e939SJaganath Kanakkassery 
5423c215e939SJaganath Kanakkassery 	while (num_reports--) {
5424c215e939SJaganath Kanakkassery 		struct hci_ev_le_ext_adv_report *ev = ptr;
5425c215e939SJaganath Kanakkassery 		u8 legacy_evt_type;
5426c215e939SJaganath Kanakkassery 		u16 evt_type;
5427c215e939SJaganath Kanakkassery 
5428c215e939SJaganath Kanakkassery 		evt_type = __le16_to_cpu(ev->evt_type);
5429b2cc9761SJaganath Kanakkassery 		legacy_evt_type = ext_evt_type_to_legacy(evt_type);
5430c215e939SJaganath Kanakkassery 		if (legacy_evt_type != LE_ADV_INVALID) {
5431c215e939SJaganath Kanakkassery 			process_adv_report(hdev, legacy_evt_type, &ev->bdaddr,
5432c215e939SJaganath Kanakkassery 					   ev->bdaddr_type, NULL, 0, ev->rssi,
5433c215e939SJaganath Kanakkassery 					   ev->data, ev->length);
5434c215e939SJaganath Kanakkassery 		}
5435c215e939SJaganath Kanakkassery 
5436cd9151b6SJaganath Kanakkassery 		ptr += sizeof(*ev) + ev->length;
5437c215e939SJaganath Kanakkassery 	}
5438c215e939SJaganath Kanakkassery 
5439c215e939SJaganath Kanakkassery 	hci_dev_unlock(hdev);
5440c215e939SJaganath Kanakkassery }
5441c215e939SJaganath Kanakkassery 
54420fe29fd1SMarcel Holtmann static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
54430fe29fd1SMarcel Holtmann 					    struct sk_buff *skb)
54440fe29fd1SMarcel Holtmann {
54450fe29fd1SMarcel Holtmann 	struct hci_ev_le_remote_feat_complete *ev = (void *)skb->data;
54460fe29fd1SMarcel Holtmann 	struct hci_conn *conn;
54470fe29fd1SMarcel Holtmann 
54480fe29fd1SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
54490fe29fd1SMarcel Holtmann 
54500fe29fd1SMarcel Holtmann 	hci_dev_lock(hdev);
54510fe29fd1SMarcel Holtmann 
54520fe29fd1SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
54530fe29fd1SMarcel Holtmann 	if (conn) {
54540fe29fd1SMarcel Holtmann 		if (!ev->status)
54550fe29fd1SMarcel Holtmann 			memcpy(conn->features[0], ev->features, 8);
54560fe29fd1SMarcel Holtmann 
54570fe29fd1SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
54580fe29fd1SMarcel Holtmann 			__u8 status;
54590fe29fd1SMarcel Holtmann 
54600fe29fd1SMarcel Holtmann 			/* If the local controller supports slave-initiated
54610fe29fd1SMarcel Holtmann 			 * features exchange, but the remote controller does
54620fe29fd1SMarcel Holtmann 			 * not, then it is possible that the error code 0x1a
54630fe29fd1SMarcel Holtmann 			 * for unsupported remote feature gets returned.
54640fe29fd1SMarcel Holtmann 			 *
54650fe29fd1SMarcel Holtmann 			 * In this specific case, allow the connection to
54660fe29fd1SMarcel Holtmann 			 * transition into connected state and mark it as
54670fe29fd1SMarcel Holtmann 			 * successful.
54680fe29fd1SMarcel Holtmann 			 */
54690fe29fd1SMarcel Holtmann 			if ((hdev->le_features[0] & HCI_LE_SLAVE_FEATURES) &&
54700fe29fd1SMarcel Holtmann 			    !conn->out && ev->status == 0x1a)
54710fe29fd1SMarcel Holtmann 				status = 0x00;
54720fe29fd1SMarcel Holtmann 			else
54730fe29fd1SMarcel Holtmann 				status = ev->status;
54740fe29fd1SMarcel Holtmann 
54750fe29fd1SMarcel Holtmann 			conn->state = BT_CONNECTED;
54760fe29fd1SMarcel Holtmann 			hci_connect_cfm(conn, status);
54770fe29fd1SMarcel Holtmann 			hci_conn_drop(conn);
54780fe29fd1SMarcel Holtmann 		}
54790fe29fd1SMarcel Holtmann 	}
54800fe29fd1SMarcel Holtmann 
54810fe29fd1SMarcel Holtmann 	hci_dev_unlock(hdev);
54820fe29fd1SMarcel Holtmann }
54830fe29fd1SMarcel Holtmann 
54846039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
5485a7a595f6SVinicius Costa Gomes {
5486a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
5487a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
5488bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
5489a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
5490c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
5491a7a595f6SVinicius Costa Gomes 
54929f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
5493a7a595f6SVinicius Costa Gomes 
5494a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
5495a7a595f6SVinicius Costa Gomes 
5496a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
5497bea710feSVinicius Costa Gomes 	if (conn == NULL)
5498bea710feSVinicius Costa Gomes 		goto not_found;
5499a7a595f6SVinicius Costa Gomes 
5500f3a73d97SJohan Hedberg 	ltk = hci_find_ltk(hdev, &conn->dst, conn->dst_type, conn->role);
55015378bc56SJohan Hedberg 	if (!ltk)
5502bea710feSVinicius Costa Gomes 		goto not_found;
5503bea710feSVinicius Costa Gomes 
55045378bc56SJohan Hedberg 	if (smp_ltk_is_sc(ltk)) {
55055378bc56SJohan Hedberg 		/* With SC both EDiv and Rand are set to zero */
55065378bc56SJohan Hedberg 		if (ev->ediv || ev->rand)
55075378bc56SJohan Hedberg 			goto not_found;
55085378bc56SJohan Hedberg 	} else {
55095378bc56SJohan Hedberg 		/* For non-SC keys check that EDiv and Rand match */
55105378bc56SJohan Hedberg 		if (ev->ediv != ltk->ediv || ev->rand != ltk->rand)
55115378bc56SJohan Hedberg 			goto not_found;
55125378bc56SJohan Hedberg 	}
55135378bc56SJohan Hedberg 
55148b76ce34SJohan Hedberg 	memcpy(cp.ltk, ltk->val, ltk->enc_size);
55158b76ce34SJohan Hedberg 	memset(cp.ltk + ltk->enc_size, 0, sizeof(cp.ltk) - ltk->enc_size);
5516a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
5517c9839a11SVinicius Costa Gomes 
5518a6f7833cSJohan Hedberg 	conn->pending_sec_level = smp_ltk_sec_level(ltk);
5519a7a595f6SVinicius Costa Gomes 
552089cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
5521a7a595f6SVinicius Costa Gomes 
5522a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
5523a7a595f6SVinicius Costa Gomes 
55245981a882SClaudio Takahasi 	/* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a
55255981a882SClaudio Takahasi 	 * temporary key used to encrypt a connection following
55265981a882SClaudio Takahasi 	 * pairing. It is used during the Encrypted Session Setup to
55275981a882SClaudio Takahasi 	 * distribute the keys. Later, security can be re-established
55285981a882SClaudio Takahasi 	 * using a distributed LTK.
55295981a882SClaudio Takahasi 	 */
55302ceba539SJohan Hedberg 	if (ltk->type == SMP_STK) {
5531fe59a05fSJohan Hedberg 		set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
5532970d0f1bSJohan Hedberg 		list_del_rcu(&ltk->list);
5533970d0f1bSJohan Hedberg 		kfree_rcu(ltk, rcu);
5534fe59a05fSJohan Hedberg 	} else {
5535fe59a05fSJohan Hedberg 		clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
5536c9839a11SVinicius Costa Gomes 	}
5537c9839a11SVinicius Costa Gomes 
5538a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
5539bea710feSVinicius Costa Gomes 
5540bea710feSVinicius Costa Gomes 	return;
5541bea710feSVinicius Costa Gomes 
5542bea710feSVinicius Costa Gomes not_found:
5543bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
5544bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
5545bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
5546a7a595f6SVinicius Costa Gomes }
5547a7a595f6SVinicius Costa Gomes 
55488e75b46aSAndre Guedes static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
55498e75b46aSAndre Guedes 				      u8 reason)
55508e75b46aSAndre Guedes {
55518e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_neg_reply cp;
55528e75b46aSAndre Guedes 
55538e75b46aSAndre Guedes 	cp.handle = cpu_to_le16(handle);
55548e75b46aSAndre Guedes 	cp.reason = reason;
55558e75b46aSAndre Guedes 
55568e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp),
55578e75b46aSAndre Guedes 		     &cp);
55588e75b46aSAndre Guedes }
55598e75b46aSAndre Guedes 
55608e75b46aSAndre Guedes static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
55618e75b46aSAndre Guedes 					     struct sk_buff *skb)
55628e75b46aSAndre Guedes {
55638e75b46aSAndre Guedes 	struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data;
55648e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_reply cp;
55658e75b46aSAndre Guedes 	struct hci_conn *hcon;
55668e75b46aSAndre Guedes 	u16 handle, min, max, latency, timeout;
55678e75b46aSAndre Guedes 
55688e75b46aSAndre Guedes 	handle = le16_to_cpu(ev->handle);
55698e75b46aSAndre Guedes 	min = le16_to_cpu(ev->interval_min);
55708e75b46aSAndre Guedes 	max = le16_to_cpu(ev->interval_max);
55718e75b46aSAndre Guedes 	latency = le16_to_cpu(ev->latency);
55728e75b46aSAndre Guedes 	timeout = le16_to_cpu(ev->timeout);
55738e75b46aSAndre Guedes 
55748e75b46aSAndre Guedes 	hcon = hci_conn_hash_lookup_handle(hdev, handle);
55758e75b46aSAndre Guedes 	if (!hcon || hcon->state != BT_CONNECTED)
55768e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
55778e75b46aSAndre Guedes 						 HCI_ERROR_UNKNOWN_CONN_ID);
55788e75b46aSAndre Guedes 
55798e75b46aSAndre Guedes 	if (hci_check_conn_params(min, max, latency, timeout))
55808e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
55818e75b46aSAndre Guedes 						 HCI_ERROR_INVALID_LL_PARAMS);
55828e75b46aSAndre Guedes 
558340bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_MASTER) {
5584348d50b8SJohan Hedberg 		struct hci_conn_params *params;
5585f4869e2aSJohan Hedberg 		u8 store_hint;
5586348d50b8SJohan Hedberg 
5587348d50b8SJohan Hedberg 		hci_dev_lock(hdev);
5588348d50b8SJohan Hedberg 
5589348d50b8SJohan Hedberg 		params = hci_conn_params_lookup(hdev, &hcon->dst,
5590348d50b8SJohan Hedberg 						hcon->dst_type);
5591348d50b8SJohan Hedberg 		if (params) {
5592348d50b8SJohan Hedberg 			params->conn_min_interval = min;
5593348d50b8SJohan Hedberg 			params->conn_max_interval = max;
5594348d50b8SJohan Hedberg 			params->conn_latency = latency;
5595348d50b8SJohan Hedberg 			params->supervision_timeout = timeout;
5596f4869e2aSJohan Hedberg 			store_hint = 0x01;
5597f4869e2aSJohan Hedberg 		} else{
5598f4869e2aSJohan Hedberg 			store_hint = 0x00;
5599348d50b8SJohan Hedberg 		}
5600348d50b8SJohan Hedberg 
5601348d50b8SJohan Hedberg 		hci_dev_unlock(hdev);
5602348d50b8SJohan Hedberg 
5603f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type,
5604f4869e2aSJohan Hedberg 				    store_hint, min, max, latency, timeout);
5605348d50b8SJohan Hedberg 	}
5606ffb5a827SAndre Guedes 
56078e75b46aSAndre Guedes 	cp.handle = ev->handle;
56088e75b46aSAndre Guedes 	cp.interval_min = ev->interval_min;
56098e75b46aSAndre Guedes 	cp.interval_max = ev->interval_max;
56108e75b46aSAndre Guedes 	cp.latency = ev->latency;
56118e75b46aSAndre Guedes 	cp.timeout = ev->timeout;
56128e75b46aSAndre Guedes 	cp.min_ce_len = 0;
56138e75b46aSAndre Guedes 	cp.max_ce_len = 0;
56148e75b46aSAndre Guedes 
56158e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
56168e75b46aSAndre Guedes }
56178e75b46aSAndre Guedes 
56182f010b55SMarcel Holtmann static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
56192f010b55SMarcel Holtmann 					 struct sk_buff *skb)
56202f010b55SMarcel Holtmann {
56212f010b55SMarcel Holtmann 	u8 num_reports = skb->data[0];
56222f010b55SMarcel Holtmann 	void *ptr = &skb->data[1];
56232f010b55SMarcel Holtmann 
56242f010b55SMarcel Holtmann 	hci_dev_lock(hdev);
56252f010b55SMarcel Holtmann 
56262f010b55SMarcel Holtmann 	while (num_reports--) {
56272f010b55SMarcel Holtmann 		struct hci_ev_le_direct_adv_info *ev = ptr;
56282f010b55SMarcel Holtmann 
56292f010b55SMarcel Holtmann 		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
56302f010b55SMarcel Holtmann 				   ev->bdaddr_type, &ev->direct_addr,
56312f010b55SMarcel Holtmann 				   ev->direct_addr_type, ev->rssi, NULL, 0);
56322f010b55SMarcel Holtmann 
56332f010b55SMarcel Holtmann 		ptr += sizeof(*ev);
56342f010b55SMarcel Holtmann 	}
56352f010b55SMarcel Holtmann 
56362f010b55SMarcel Holtmann 	hci_dev_unlock(hdev);
56372f010b55SMarcel Holtmann }
56382f010b55SMarcel Holtmann 
56396039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
5640fcd89c09SVille Tervo {
5641fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
5642fcd89c09SVille Tervo 
5643fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
5644fcd89c09SVille Tervo 
5645fcd89c09SVille Tervo 	switch (le_ev->subevent) {
5646fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
5647fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
5648fcd89c09SVille Tervo 		break;
5649fcd89c09SVille Tervo 
56501855d92dSMarcel Holtmann 	case HCI_EV_LE_CONN_UPDATE_COMPLETE:
56511855d92dSMarcel Holtmann 		hci_le_conn_update_complete_evt(hdev, skb);
56521855d92dSMarcel Holtmann 		break;
56531855d92dSMarcel Holtmann 
56549aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
56559aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
56569aa04c91SAndre Guedes 		break;
56579aa04c91SAndre Guedes 
56580fe29fd1SMarcel Holtmann 	case HCI_EV_LE_REMOTE_FEAT_COMPLETE:
56590fe29fd1SMarcel Holtmann 		hci_le_remote_feat_complete_evt(hdev, skb);
56600fe29fd1SMarcel Holtmann 		break;
56610fe29fd1SMarcel Holtmann 
5662a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
5663a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
5664a7a595f6SVinicius Costa Gomes 		break;
5665a7a595f6SVinicius Costa Gomes 
56668e75b46aSAndre Guedes 	case HCI_EV_LE_REMOTE_CONN_PARAM_REQ:
56678e75b46aSAndre Guedes 		hci_le_remote_conn_param_req_evt(hdev, skb);
56688e75b46aSAndre Guedes 		break;
56698e75b46aSAndre Guedes 
56702f010b55SMarcel Holtmann 	case HCI_EV_LE_DIRECT_ADV_REPORT:
56712f010b55SMarcel Holtmann 		hci_le_direct_adv_report_evt(hdev, skb);
56722f010b55SMarcel Holtmann 		break;
56732f010b55SMarcel Holtmann 
5674c215e939SJaganath Kanakkassery 	case HCI_EV_LE_EXT_ADV_REPORT:
5675c215e939SJaganath Kanakkassery 		hci_le_ext_adv_report_evt(hdev, skb);
5676c215e939SJaganath Kanakkassery 		break;
5677c215e939SJaganath Kanakkassery 
56784d94f95dSJaganath Kanakkassery 	case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
56794d94f95dSJaganath Kanakkassery 		hci_le_enh_conn_complete_evt(hdev, skb);
56804d94f95dSJaganath Kanakkassery 		break;
56814d94f95dSJaganath Kanakkassery 
5682acf0aeaeSJaganath Kanakkassery 	case HCI_EV_LE_EXT_ADV_SET_TERM:
5683acf0aeaeSJaganath Kanakkassery 		hci_le_ext_adv_term_evt(hdev, skb);
5684acf0aeaeSJaganath Kanakkassery 		break;
5685acf0aeaeSJaganath Kanakkassery 
5686fcd89c09SVille Tervo 	default:
5687fcd89c09SVille Tervo 		break;
5688fcd89c09SVille Tervo 	}
5689fcd89c09SVille Tervo }
5690fcd89c09SVille Tervo 
5691757aa0b5SJohan Hedberg static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
5692757aa0b5SJohan Hedberg 				 u8 event, struct sk_buff *skb)
5693757aa0b5SJohan Hedberg {
5694757aa0b5SJohan Hedberg 	struct hci_ev_cmd_complete *ev;
5695757aa0b5SJohan Hedberg 	struct hci_event_hdr *hdr;
5696757aa0b5SJohan Hedberg 
5697757aa0b5SJohan Hedberg 	if (!skb)
5698757aa0b5SJohan Hedberg 		return false;
5699757aa0b5SJohan Hedberg 
5700757aa0b5SJohan Hedberg 	if (skb->len < sizeof(*hdr)) {
57012064ee33SMarcel Holtmann 		bt_dev_err(hdev, "too short HCI event");
5702757aa0b5SJohan Hedberg 		return false;
5703757aa0b5SJohan Hedberg 	}
5704757aa0b5SJohan Hedberg 
5705757aa0b5SJohan Hedberg 	hdr = (void *) skb->data;
5706757aa0b5SJohan Hedberg 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
5707757aa0b5SJohan Hedberg 
5708757aa0b5SJohan Hedberg 	if (event) {
5709757aa0b5SJohan Hedberg 		if (hdr->evt != event)
5710757aa0b5SJohan Hedberg 			return false;
5711757aa0b5SJohan Hedberg 		return true;
5712757aa0b5SJohan Hedberg 	}
5713757aa0b5SJohan Hedberg 
57141629db9cSJohan Hedberg 	/* Check if request ended in Command Status - no way to retreive
57151629db9cSJohan Hedberg 	 * any extra parameters in this case.
57161629db9cSJohan Hedberg 	 */
57171629db9cSJohan Hedberg 	if (hdr->evt == HCI_EV_CMD_STATUS)
57181629db9cSJohan Hedberg 		return false;
57191629db9cSJohan Hedberg 
5720757aa0b5SJohan Hedberg 	if (hdr->evt != HCI_EV_CMD_COMPLETE) {
57212064ee33SMarcel Holtmann 		bt_dev_err(hdev, "last event is not cmd complete (0x%2.2x)",
57222064ee33SMarcel Holtmann 			   hdr->evt);
5723757aa0b5SJohan Hedberg 		return false;
5724757aa0b5SJohan Hedberg 	}
5725757aa0b5SJohan Hedberg 
5726757aa0b5SJohan Hedberg 	if (skb->len < sizeof(*ev)) {
57272064ee33SMarcel Holtmann 		bt_dev_err(hdev, "too short cmd_complete event");
5728757aa0b5SJohan Hedberg 		return false;
5729757aa0b5SJohan Hedberg 	}
5730757aa0b5SJohan Hedberg 
5731757aa0b5SJohan Hedberg 	ev = (void *) skb->data;
5732757aa0b5SJohan Hedberg 	skb_pull(skb, sizeof(*ev));
5733757aa0b5SJohan Hedberg 
5734757aa0b5SJohan Hedberg 	if (opcode != __le16_to_cpu(ev->opcode)) {
5735757aa0b5SJohan Hedberg 		BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode,
5736757aa0b5SJohan Hedberg 		       __le16_to_cpu(ev->opcode));
5737757aa0b5SJohan Hedberg 		return false;
5738757aa0b5SJohan Hedberg 	}
5739757aa0b5SJohan Hedberg 
5740757aa0b5SJohan Hedberg 	return true;
5741757aa0b5SJohan Hedberg }
5742757aa0b5SJohan Hedberg 
57431da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
57441da177e4SLinus Torvalds {
5745a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
5746e6214487SJohan Hedberg 	hci_req_complete_t req_complete = NULL;
5747e6214487SJohan Hedberg 	hci_req_complete_skb_t req_complete_skb = NULL;
5748e6214487SJohan Hedberg 	struct sk_buff *orig_skb = NULL;
5749757aa0b5SJohan Hedberg 	u8 status = 0, event = hdr->evt, req_evt = 0;
5750e6214487SJohan Hedberg 	u16 opcode = HCI_OP_NOP;
57511da177e4SLinus Torvalds 
5752242c0ebdSMarcel Holtmann 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->hci.req_event == event) {
5753c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
5754e6214487SJohan Hedberg 		opcode = __le16_to_cpu(cmd_hdr->opcode);
5755e6214487SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, status, &req_complete,
5756e6214487SJohan Hedberg 				     &req_complete_skb);
5757757aa0b5SJohan Hedberg 		req_evt = event;
575802350a72SJohan Hedberg 	}
575902350a72SJohan Hedberg 
5760e6214487SJohan Hedberg 	/* If it looks like we might end up having to call
5761e6214487SJohan Hedberg 	 * req_complete_skb, store a pristine copy of the skb since the
5762e6214487SJohan Hedberg 	 * various handlers may modify the original one through
5763e6214487SJohan Hedberg 	 * skb_pull() calls, etc.
5764e6214487SJohan Hedberg 	 */
5765e6214487SJohan Hedberg 	if (req_complete_skb || event == HCI_EV_CMD_STATUS ||
5766e6214487SJohan Hedberg 	    event == HCI_EV_CMD_COMPLETE)
5767e6214487SJohan Hedberg 		orig_skb = skb_clone(skb, GFP_KERNEL);
5768e6214487SJohan Hedberg 
5769e6214487SJohan Hedberg 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
5770e6214487SJohan Hedberg 
5771a9de9248SMarcel Holtmann 	switch (event) {
57721da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
57731da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
57741da177e4SLinus Torvalds 		break;
57751da177e4SLinus Torvalds 
57761da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
57771da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
57781da177e4SLinus Torvalds 		break;
57791da177e4SLinus Torvalds 
5780a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
5781a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
578221d9e30eSMarcel Holtmann 		break;
578321d9e30eSMarcel Holtmann 
57841da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
57851da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
57861da177e4SLinus Torvalds 		break;
57871da177e4SLinus Torvalds 
57881da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
57891da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
57901da177e4SLinus Torvalds 		break;
57911da177e4SLinus Torvalds 
57921da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
57931da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
57941da177e4SLinus Torvalds 		break;
57951da177e4SLinus Torvalds 
5796a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
5797a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
5798a9de9248SMarcel Holtmann 		break;
5799a9de9248SMarcel Holtmann 
58001da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
58011da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
58021da177e4SLinus Torvalds 		break;
58031da177e4SLinus Torvalds 
5804a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
5805a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
5806a9de9248SMarcel Holtmann 		break;
5807a9de9248SMarcel Holtmann 
5808a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
5809a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
5810a9de9248SMarcel Holtmann 		break;
5811a9de9248SMarcel Holtmann 
5812a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
5813e6214487SJohan Hedberg 		hci_cmd_complete_evt(hdev, skb, &opcode, &status,
5814e6214487SJohan Hedberg 				     &req_complete, &req_complete_skb);
5815a9de9248SMarcel Holtmann 		break;
5816a9de9248SMarcel Holtmann 
5817a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
5818e6214487SJohan Hedberg 		hci_cmd_status_evt(hdev, skb, &opcode, &status, &req_complete,
5819e6214487SJohan Hedberg 				   &req_complete_skb);
5820a9de9248SMarcel Holtmann 		break;
5821a9de9248SMarcel Holtmann 
582224dfa343SMarcel Holtmann 	case HCI_EV_HARDWARE_ERROR:
582324dfa343SMarcel Holtmann 		hci_hardware_error_evt(hdev, skb);
582424dfa343SMarcel Holtmann 		break;
582524dfa343SMarcel Holtmann 
5826a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
5827a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
5828a9de9248SMarcel Holtmann 		break;
5829a9de9248SMarcel Holtmann 
5830a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
5831a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
5832a9de9248SMarcel Holtmann 		break;
5833a9de9248SMarcel Holtmann 
5834a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
5835a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
58361da177e4SLinus Torvalds 		break;
58371da177e4SLinus Torvalds 
58381da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
58391da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
58401da177e4SLinus Torvalds 		break;
58411da177e4SLinus Torvalds 
58421da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
58431da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
58441da177e4SLinus Torvalds 		break;
58451da177e4SLinus Torvalds 
58461da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
58471da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
58481da177e4SLinus Torvalds 		break;
58491da177e4SLinus Torvalds 
58501da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
58511da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
58521da177e4SLinus Torvalds 		break;
58531da177e4SLinus Torvalds 
5854a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
5855a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
5856a8746417SMarcel Holtmann 		break;
5857a8746417SMarcel Holtmann 
585885a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
585985a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
586085a1e930SMarcel Holtmann 		break;
586185a1e930SMarcel Holtmann 
5862a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
5863a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
5864a9de9248SMarcel Holtmann 		break;
5865a9de9248SMarcel Holtmann 
5866a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
5867a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
5868a9de9248SMarcel Holtmann 		break;
5869a9de9248SMarcel Holtmann 
5870a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
5871a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
5872a9de9248SMarcel Holtmann 		break;
5873a9de9248SMarcel Holtmann 
5874a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
5875a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
58761da177e4SLinus Torvalds 		break;
58771da177e4SLinus Torvalds 
58781c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
58791c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
58801c2e0041SJohan Hedberg 		break;
58811c2e0041SJohan Hedberg 
58820493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
58830493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
58840493684eSMarcel Holtmann 		break;
58850493684eSMarcel Holtmann 
588603b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
588703b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
588803b555e1SJohan Hedberg 		break;
588903b555e1SJohan Hedberg 
5890a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
5891a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
5892a5c29683SJohan Hedberg 		break;
5893a5c29683SJohan Hedberg 
58941143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
58951143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
58961143d458SBrian Gix 		break;
58971143d458SBrian Gix 
589892a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
589992a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
590092a25256SJohan Hedberg 		break;
590192a25256SJohan Hedberg 
590292a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
590392a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
590492a25256SJohan Hedberg 		break;
590592a25256SJohan Hedberg 
59060493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
59070493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
59080493684eSMarcel Holtmann 		break;
59090493684eSMarcel Holtmann 
591041a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
591141a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
591241a96212SMarcel Holtmann 		break;
591341a96212SMarcel Holtmann 
5914fcd89c09SVille Tervo 	case HCI_EV_LE_META:
5915fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
5916fcd89c09SVille Tervo 		break;
5917fcd89c09SVille Tervo 
59182763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
59192763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
59202763eda6SSzymon Janc 		break;
59212763eda6SSzymon Janc 
5922a77a6a14SArron Wang #if IS_ENABLED(CONFIG_BT_HS)
5923a77a6a14SArron Wang 	case HCI_EV_CHANNEL_SELECTED:
5924a77a6a14SArron Wang 		hci_chan_selected_evt(hdev, skb);
5925a77a6a14SArron Wang 		break;
5926a77a6a14SArron Wang 
5927d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
5928d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
5929d5e91192SAndrei Emeltchenko 		break;
5930d5e91192SAndrei Emeltchenko 
593127695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
593227695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
593327695fb4SAndrei Emeltchenko 		break;
593427695fb4SAndrei Emeltchenko 
5935606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
5936606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
5937606e2a10SAndrei Emeltchenko 		break;
5938606e2a10SAndrei Emeltchenko 
59399eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
59409eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
59419eef6b3aSAndrei Emeltchenko 		break;
5942a77a6a14SArron Wang #endif
59439eef6b3aSAndrei Emeltchenko 
594425e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
594525e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
594625e89e99SAndrei Emeltchenko 		break;
594725e89e99SAndrei Emeltchenko 
59481da177e4SLinus Torvalds 	default:
59499f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
59501da177e4SLinus Torvalds 		break;
59511da177e4SLinus Torvalds 	}
59521da177e4SLinus Torvalds 
5953757aa0b5SJohan Hedberg 	if (req_complete) {
5954e6214487SJohan Hedberg 		req_complete(hdev, status, opcode);
5955757aa0b5SJohan Hedberg 	} else if (req_complete_skb) {
5956757aa0b5SJohan Hedberg 		if (!hci_get_cmd_complete(hdev, opcode, req_evt, orig_skb)) {
5957757aa0b5SJohan Hedberg 			kfree_skb(orig_skb);
5958757aa0b5SJohan Hedberg 			orig_skb = NULL;
5959757aa0b5SJohan Hedberg 		}
5960e6214487SJohan Hedberg 		req_complete_skb(hdev, status, opcode, orig_skb);
5961757aa0b5SJohan Hedberg 	}
5962e6214487SJohan Hedberg 
5963e6214487SJohan Hedberg 	kfree_skb(orig_skb);
59641da177e4SLinus Torvalds 	kfree_skb(skb);
59651da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
59661da177e4SLinus Torvalds }
5967