xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 5d667ef6)
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);
5850143a43SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
5950143a43SJohan Hedberg 	hci_dev_unlock(hdev);
6050143a43SJohan Hedberg 
61a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
621da177e4SLinus Torvalds }
636bd57416SMarcel Holtmann 
644d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
654d93483bSAndre Guedes {
664d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
674d93483bSAndre Guedes 
689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
69ae854a70SAndre Guedes 
70ae854a70SAndre Guedes 	if (status)
71ae854a70SAndre Guedes 		return;
72ae854a70SAndre Guedes 
73a1536da2SMarcel Holtmann 	hci_dev_set_flag(hdev, HCI_PERIODIC_INQ);
744d93483bSAndre Guedes }
754d93483bSAndre Guedes 
76a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
771da177e4SLinus Torvalds {
78a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
79a9de9248SMarcel Holtmann 
809f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
81a9de9248SMarcel Holtmann 
82a9de9248SMarcel Holtmann 	if (status)
83a9de9248SMarcel Holtmann 		return;
84a9de9248SMarcel Holtmann 
85a358dc11SMarcel Holtmann 	hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ);
86ae854a70SAndre Guedes 
87a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
88a9de9248SMarcel Holtmann }
89a9de9248SMarcel Holtmann 
90807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
91807deac2SGustavo Padovan 					  struct sk_buff *skb)
92a9de9248SMarcel Holtmann {
93a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
94a9de9248SMarcel Holtmann }
95a9de9248SMarcel Holtmann 
96a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
97a9de9248SMarcel Holtmann {
98a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
991da177e4SLinus Torvalds 	struct hci_conn *conn;
1001da177e4SLinus Torvalds 
1019f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1021da177e4SLinus Torvalds 
103a9de9248SMarcel Holtmann 	if (rp->status)
104a9de9248SMarcel Holtmann 		return;
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1071da177e4SLinus Torvalds 
108a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
10940bef302SJohan Hedberg 	if (conn)
11040bef302SJohan Hedberg 		conn->role = rp->role;
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
113a9de9248SMarcel Holtmann }
1141da177e4SLinus Torvalds 
115e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
116e4e8e37cSMarcel Holtmann {
117e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
118e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
119e4e8e37cSMarcel Holtmann 
1209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
121e4e8e37cSMarcel Holtmann 
122e4e8e37cSMarcel Holtmann 	if (rp->status)
123e4e8e37cSMarcel Holtmann 		return;
124e4e8e37cSMarcel Holtmann 
125e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
126e4e8e37cSMarcel Holtmann 
127e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
128e4e8e37cSMarcel Holtmann 	if (conn)
129e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
130e4e8e37cSMarcel Holtmann 
131e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
132e4e8e37cSMarcel Holtmann }
133e4e8e37cSMarcel Holtmann 
134a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
135a9de9248SMarcel Holtmann {
136a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
137a9de9248SMarcel Holtmann 	struct hci_conn *conn;
138a9de9248SMarcel Holtmann 	void *sent;
139a9de9248SMarcel Holtmann 
1409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
141a9de9248SMarcel Holtmann 
142a9de9248SMarcel Holtmann 	if (rp->status)
143a9de9248SMarcel Holtmann 		return;
144a9de9248SMarcel Holtmann 
145a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14604837f64SMarcel Holtmann 	if (!sent)
147a9de9248SMarcel Holtmann 		return;
14804837f64SMarcel Holtmann 
14904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
15004837f64SMarcel Holtmann 
151a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
152e4e8e37cSMarcel Holtmann 	if (conn)
15383985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15404837f64SMarcel Holtmann 
15504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1561da177e4SLinus Torvalds }
1571da177e4SLinus Torvalds 
158807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
159807deac2SGustavo Padovan 					struct sk_buff *skb)
160e4e8e37cSMarcel Holtmann {
161e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
162e4e8e37cSMarcel Holtmann 
1639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
164e4e8e37cSMarcel Holtmann 
165e4e8e37cSMarcel Holtmann 	if (rp->status)
166e4e8e37cSMarcel Holtmann 		return;
167e4e8e37cSMarcel Holtmann 
168e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
169e4e8e37cSMarcel Holtmann }
170e4e8e37cSMarcel Holtmann 
171807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
172807deac2SGustavo Padovan 					 struct sk_buff *skb)
173e4e8e37cSMarcel Holtmann {
174e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
175e4e8e37cSMarcel Holtmann 	void *sent;
176e4e8e37cSMarcel Holtmann 
1779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
178e4e8e37cSMarcel Holtmann 
17945296acdSMarcel Holtmann 	if (status)
18045296acdSMarcel Holtmann 		return;
18145296acdSMarcel Holtmann 
182e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
183e4e8e37cSMarcel Holtmann 	if (!sent)
184e4e8e37cSMarcel Holtmann 		return;
185e4e8e37cSMarcel Holtmann 
186e4e8e37cSMarcel Holtmann 	hdev->link_policy = get_unaligned_le16(sent);
187e4e8e37cSMarcel Holtmann }
188e4e8e37cSMarcel Holtmann 
189a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1901da177e4SLinus Torvalds {
191a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
192a9de9248SMarcel Holtmann 
1939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
194a9de9248SMarcel Holtmann 
19510572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19610572132SGustavo F. Padovan 
1978761f9d6SMarcel Holtmann 	if (status)
1988761f9d6SMarcel Holtmann 		return;
1998761f9d6SMarcel Holtmann 
200a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
201eacb44dfSMarcel Holtmann 	hci_dev_clear_volatile_flags(hdev);
20269775ff6SAndre Guedes 
20339c5d970SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
20439c5d970SJohan Hedberg 
205bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
206bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
2073f0f524bSJohan Hedberg 
2083f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
2093f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
210f8e808bdSMarcel Holtmann 
211f8e808bdSMarcel Holtmann 	memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data));
212f8e808bdSMarcel Holtmann 	hdev->scan_rsp_data_len = 0;
21306f5b778SMarcel Holtmann 
214533553f8SMarcel Holtmann 	hdev->le_scan_type = LE_SCAN_PASSIVE;
215533553f8SMarcel Holtmann 
21606f5b778SMarcel Holtmann 	hdev->ssp_debug_mode = 0;
217a4d5504dSMarcel Holtmann 
218a4d5504dSMarcel Holtmann 	hci_bdaddr_list_clear(&hdev->le_white_list);
219a9de9248SMarcel Holtmann }
220a9de9248SMarcel Holtmann 
221c2f0f979SMarcel Holtmann static void hci_cc_read_stored_link_key(struct hci_dev *hdev,
222c2f0f979SMarcel Holtmann 					struct sk_buff *skb)
223c2f0f979SMarcel Holtmann {
224c2f0f979SMarcel Holtmann 	struct hci_rp_read_stored_link_key *rp = (void *)skb->data;
225c2f0f979SMarcel Holtmann 	struct hci_cp_read_stored_link_key *sent;
226c2f0f979SMarcel Holtmann 
227c2f0f979SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
228c2f0f979SMarcel Holtmann 
229c2f0f979SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY);
230c2f0f979SMarcel Holtmann 	if (!sent)
231c2f0f979SMarcel Holtmann 		return;
232c2f0f979SMarcel Holtmann 
233c2f0f979SMarcel Holtmann 	if (!rp->status && sent->read_all == 0x01) {
234c2f0f979SMarcel Holtmann 		hdev->stored_max_keys = rp->max_keys;
235c2f0f979SMarcel Holtmann 		hdev->stored_num_keys = rp->num_keys;
236c2f0f979SMarcel Holtmann 	}
237c2f0f979SMarcel Holtmann }
238c2f0f979SMarcel Holtmann 
239a9366120SMarcel Holtmann static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
240a9366120SMarcel Holtmann 					  struct sk_buff *skb)
241a9366120SMarcel Holtmann {
242a9366120SMarcel Holtmann 	struct hci_rp_delete_stored_link_key *rp = (void *)skb->data;
243a9366120SMarcel Holtmann 
244a9366120SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
245a9366120SMarcel Holtmann 
246a9366120SMarcel Holtmann 	if (rp->status)
247a9366120SMarcel Holtmann 		return;
248a9366120SMarcel Holtmann 
249a9366120SMarcel Holtmann 	if (rp->num_keys <= hdev->stored_num_keys)
250a9366120SMarcel Holtmann 		hdev->stored_num_keys -= rp->num_keys;
251a9366120SMarcel Holtmann 	else
252a9366120SMarcel Holtmann 		hdev->stored_num_keys = 0;
253a9366120SMarcel Holtmann }
254a9366120SMarcel Holtmann 
255a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
256a9de9248SMarcel Holtmann {
257a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2581da177e4SLinus Torvalds 	void *sent;
2591da177e4SLinus Torvalds 
2609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2611da177e4SLinus Torvalds 
262a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2631da177e4SLinus Torvalds 	if (!sent)
264a9de9248SMarcel Holtmann 		return;
2651da177e4SLinus Torvalds 
26656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
26756e5cb86SJohan Hedberg 
268d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
269f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
27028cc7bdeSJohan Hedberg 	else if (!status)
27128cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
272f51d5b24SJohan Hedberg 
27356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
274a9de9248SMarcel Holtmann }
275a9de9248SMarcel Holtmann 
276a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
277a9de9248SMarcel Holtmann {
278a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
279a9de9248SMarcel Holtmann 
2809f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
281a9de9248SMarcel Holtmann 
282a9de9248SMarcel Holtmann 	if (rp->status)
283a9de9248SMarcel Holtmann 		return;
284a9de9248SMarcel Holtmann 
285d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
286d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hdev, HCI_CONFIG))
2871f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
288a9de9248SMarcel Holtmann }
289a9de9248SMarcel Holtmann 
290a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
291a9de9248SMarcel Holtmann {
292a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
293a9de9248SMarcel Holtmann 	void *sent;
294a9de9248SMarcel Holtmann 
2959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
296a9de9248SMarcel Holtmann 
297a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
298a9de9248SMarcel Holtmann 	if (!sent)
299a9de9248SMarcel Holtmann 		return;
3001da177e4SLinus Torvalds 
3015c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
3025c1a4c8fSJaganath Kanakkassery 
3031da177e4SLinus Torvalds 	if (!status) {
304a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
305a9de9248SMarcel Holtmann 
3061da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
3071da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
3081da177e4SLinus Torvalds 		else
3091da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
3101da177e4SLinus Torvalds 	}
311a9de9248SMarcel Holtmann 
312d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
31333ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
3145c1a4c8fSJaganath Kanakkassery 
3155c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
316a9de9248SMarcel Holtmann }
3171da177e4SLinus Torvalds 
318a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
319a9de9248SMarcel Holtmann {
320a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
32145296acdSMarcel Holtmann 	__u8 param;
322a9de9248SMarcel Holtmann 	void *sent;
323a9de9248SMarcel Holtmann 
3249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
325a9de9248SMarcel Holtmann 
32645296acdSMarcel Holtmann 	if (status)
32745296acdSMarcel Holtmann 		return;
32845296acdSMarcel Holtmann 
329a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
3301da177e4SLinus Torvalds 	if (!sent)
331a9de9248SMarcel Holtmann 		return;
3321da177e4SLinus Torvalds 
33345296acdSMarcel Holtmann 	param = *((__u8 *) sent);
334a9de9248SMarcel Holtmann 
3351da177e4SLinus Torvalds 	if (param)
3361da177e4SLinus Torvalds 		set_bit(HCI_ENCRYPT, &hdev->flags);
3371da177e4SLinus Torvalds 	else
3381da177e4SLinus Torvalds 		clear_bit(HCI_ENCRYPT, &hdev->flags);
3391da177e4SLinus Torvalds }
3401da177e4SLinus Torvalds 
341a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
342a9de9248SMarcel Holtmann {
34345296acdSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
34445296acdSMarcel Holtmann 	__u8 param;
345a9de9248SMarcel Holtmann 	void *sent;
3461da177e4SLinus Torvalds 
3479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
348a9de9248SMarcel Holtmann 
349a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3501da177e4SLinus Torvalds 	if (!sent)
351a9de9248SMarcel Holtmann 		return;
3521da177e4SLinus Torvalds 
35336f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
354a9de9248SMarcel Holtmann 
35556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
35656e5cb86SJohan Hedberg 
357fa1bd918SMikel Astiz 	if (status) {
3582d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3592d7cee58SJohan Hedberg 		goto done;
3602d7cee58SJohan Hedberg 	}
3612d7cee58SJohan Hedberg 
362bc6d2d04SJohan Hedberg 	if (param & SCAN_INQUIRY)
3631da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
364bc6d2d04SJohan Hedberg 	else
365bc6d2d04SJohan Hedberg 		clear_bit(HCI_ISCAN, &hdev->flags);
3661da177e4SLinus Torvalds 
367031547d8SJohan Hedberg 	if (param & SCAN_PAGE)
3681da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
369bc6d2d04SJohan Hedberg 	else
370204e3990SJohan Hedberg 		clear_bit(HCI_PSCAN, &hdev->flags);
371a9de9248SMarcel Holtmann 
37236f7fc7eSJohan Hedberg done:
37356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
3741da177e4SLinus Torvalds }
3751da177e4SLinus Torvalds 
376a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
377a9de9248SMarcel Holtmann {
378a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
379a9de9248SMarcel Holtmann 
3809f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
381a9de9248SMarcel Holtmann 
382a9de9248SMarcel Holtmann 	if (rp->status)
383a9de9248SMarcel Holtmann 		return;
384a9de9248SMarcel Holtmann 
385a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
386a9de9248SMarcel Holtmann 
387a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
388a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
389a9de9248SMarcel Holtmann }
390a9de9248SMarcel Holtmann 
391a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
392a9de9248SMarcel Holtmann {
393a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
394a9de9248SMarcel Holtmann 	void *sent;
395a9de9248SMarcel Holtmann 
3969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
397a9de9248SMarcel Holtmann 
398a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
399a9de9248SMarcel Holtmann 	if (!sent)
400a9de9248SMarcel Holtmann 		return;
401a9de9248SMarcel Holtmann 
4027f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
4037f9a903cSMarcel Holtmann 
4047f9a903cSMarcel Holtmann 	if (status == 0)
405a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
4067f9a903cSMarcel Holtmann 
407d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
4087f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
4097f9a903cSMarcel Holtmann 
4107f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
411a9de9248SMarcel Holtmann }
412a9de9248SMarcel Holtmann 
413a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
414a9de9248SMarcel Holtmann {
415a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
416a9de9248SMarcel Holtmann 	__u16 setting;
417a9de9248SMarcel Holtmann 
4189f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
419a9de9248SMarcel Holtmann 
420a9de9248SMarcel Holtmann 	if (rp->status)
421a9de9248SMarcel Holtmann 		return;
422a9de9248SMarcel Holtmann 
423a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
424a9de9248SMarcel Holtmann 
425a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
426a9de9248SMarcel Holtmann 		return;
427a9de9248SMarcel Holtmann 
428a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
429a9de9248SMarcel Holtmann 
4309f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
431a9de9248SMarcel Holtmann 
4323c54711cSGustavo F. Padovan 	if (hdev->notify)
433a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
434a9de9248SMarcel Holtmann }
435a9de9248SMarcel Holtmann 
4368fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
4378fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
438a9de9248SMarcel Holtmann {
439a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
440f383f275SMarcel Holtmann 	__u16 setting;
441a9de9248SMarcel Holtmann 	void *sent;
442a9de9248SMarcel Holtmann 
4439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
444a9de9248SMarcel Holtmann 
445f383f275SMarcel Holtmann 	if (status)
446f383f275SMarcel Holtmann 		return;
447f383f275SMarcel Holtmann 
448a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
449a9de9248SMarcel Holtmann 	if (!sent)
450a9de9248SMarcel Holtmann 		return;
451a9de9248SMarcel Holtmann 
452f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4531da177e4SLinus Torvalds 
454f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
455f383f275SMarcel Holtmann 		return;
456f383f275SMarcel Holtmann 
4571da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4581da177e4SLinus Torvalds 
4599f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4601da177e4SLinus Torvalds 
4613c54711cSGustavo F. Padovan 	if (hdev->notify)
4621da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4631da177e4SLinus Torvalds }
4641da177e4SLinus Torvalds 
465b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev,
466b4cb9fb2SMarcel Holtmann 					  struct sk_buff *skb)
467b4cb9fb2SMarcel Holtmann {
468b4cb9fb2SMarcel Holtmann 	struct hci_rp_read_num_supported_iac *rp = (void *) skb->data;
469b4cb9fb2SMarcel Holtmann 
470b4cb9fb2SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
471b4cb9fb2SMarcel Holtmann 
472b4cb9fb2SMarcel Holtmann 	if (rp->status)
473b4cb9fb2SMarcel Holtmann 		return;
474b4cb9fb2SMarcel Holtmann 
475b4cb9fb2SMarcel Holtmann 	hdev->num_iac = rp->num_iac;
476b4cb9fb2SMarcel Holtmann 
477b4cb9fb2SMarcel Holtmann 	BT_DBG("%s num iac %d", hdev->name, hdev->num_iac);
478b4cb9fb2SMarcel Holtmann }
479b4cb9fb2SMarcel Holtmann 
480333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
481333140b5SMarcel Holtmann {
482333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4835ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
484333140b5SMarcel Holtmann 
4859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
486333140b5SMarcel Holtmann 
487333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
488333140b5SMarcel Holtmann 	if (!sent)
489333140b5SMarcel Holtmann 		return;
490333140b5SMarcel Holtmann 
4915c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
4925c1a4c8fSJaganath Kanakkassery 
4935ed8eb2fSJohan Hedberg 	if (!status) {
4945ed8eb2fSJohan Hedberg 		if (sent->mode)
495cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_SSP;
4965ed8eb2fSJohan Hedberg 		else
497cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_SSP;
4985ed8eb2fSJohan Hedberg 	}
4995ed8eb2fSJohan Hedberg 
500d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
5015ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
502c0ecddc2SJohan Hedberg 	else if (!status) {
5035ed8eb2fSJohan Hedberg 		if (sent->mode)
504a1536da2SMarcel Holtmann 			hci_dev_set_flag(hdev, HCI_SSP_ENABLED);
50584bde9d6SJohan Hedberg 		else
506a358dc11SMarcel Holtmann 			hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
507c0ecddc2SJohan Hedberg 	}
5085c1a4c8fSJaganath Kanakkassery 
5095c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
510333140b5SMarcel Holtmann }
511333140b5SMarcel Holtmann 
512eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
513eac83dc6SMarcel Holtmann {
514eac83dc6SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
515eac83dc6SMarcel Holtmann 	struct hci_cp_write_sc_support *sent;
516eac83dc6SMarcel Holtmann 
517eac83dc6SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
518eac83dc6SMarcel Holtmann 
519eac83dc6SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
520eac83dc6SMarcel Holtmann 	if (!sent)
521eac83dc6SMarcel Holtmann 		return;
522eac83dc6SMarcel Holtmann 
5235c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
5245c1a4c8fSJaganath Kanakkassery 
525eac83dc6SMarcel Holtmann 	if (!status) {
526eac83dc6SMarcel Holtmann 		if (sent->support)
527eac83dc6SMarcel Holtmann 			hdev->features[1][0] |= LMP_HOST_SC;
528eac83dc6SMarcel Holtmann 		else
529eac83dc6SMarcel Holtmann 			hdev->features[1][0] &= ~LMP_HOST_SC;
530eac83dc6SMarcel Holtmann 	}
531eac83dc6SMarcel Holtmann 
532d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT) && !status) {
533eac83dc6SMarcel Holtmann 		if (sent->support)
534a1536da2SMarcel Holtmann 			hci_dev_set_flag(hdev, HCI_SC_ENABLED);
535eac83dc6SMarcel Holtmann 		else
536a358dc11SMarcel Holtmann 			hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
537eac83dc6SMarcel Holtmann 	}
5385c1a4c8fSJaganath Kanakkassery 
5395c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
540eac83dc6SMarcel Holtmann }
541eac83dc6SMarcel Holtmann 
542a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
543a9de9248SMarcel Holtmann {
544a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
5451143e5a6SMarcel Holtmann 
5469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5471143e5a6SMarcel Holtmann 
548a9de9248SMarcel Holtmann 	if (rp->status)
54942c6b129SJohan Hedberg 		return;
5501143e5a6SMarcel Holtmann 
551d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
552d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hdev, HCI_CONFIG)) {
553a9de9248SMarcel Holtmann 		hdev->hci_ver = rp->hci_ver;
554e4e8e37cSMarcel Holtmann 		hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
555d5859e22SJohan Hedberg 		hdev->lmp_ver = rp->lmp_ver;
556e4e8e37cSMarcel Holtmann 		hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
557d5859e22SJohan Hedberg 		hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5580d5551f5SMarcel Holtmann 	}
559d5859e22SJohan Hedberg }
560d5859e22SJohan Hedberg 
5618fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
5628fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
563a9de9248SMarcel Holtmann {
564a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
565a9de9248SMarcel Holtmann 
5669f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
567a9de9248SMarcel Holtmann 
5686a070e6eSMarcel Holtmann 	if (rp->status)
5696a070e6eSMarcel Holtmann 		return;
5706a070e6eSMarcel Holtmann 
571d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
572d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hdev, HCI_CONFIG))
573a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
574a9de9248SMarcel Holtmann }
575a9de9248SMarcel Holtmann 
5768fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
5778fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
578a9de9248SMarcel Holtmann {
579a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
580a9de9248SMarcel Holtmann 
5819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
582a9de9248SMarcel Holtmann 
583a9de9248SMarcel Holtmann 	if (rp->status)
584a9de9248SMarcel Holtmann 		return;
585a9de9248SMarcel Holtmann 
586a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
5871da177e4SLinus Torvalds 
5881da177e4SLinus Torvalds 	/* Adjust default settings according to features
5891da177e4SLinus Torvalds 	 * supported by device. */
590a9de9248SMarcel Holtmann 
591cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_3SLOT)
5921da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
5931da177e4SLinus Torvalds 
594cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_5SLOT)
5951da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
5961da177e4SLinus Torvalds 
597cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV2) {
5981da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
5995b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6005b7f9909SMarcel Holtmann 	}
6011da177e4SLinus Torvalds 
602cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV3) {
6031da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6045b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6055b7f9909SMarcel Holtmann 	}
6065b7f9909SMarcel Holtmann 
60745db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
6085b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6095b7f9909SMarcel Holtmann 
610cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV4)
6115b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6125b7f9909SMarcel Holtmann 
613cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV5)
6145b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6151da177e4SLinus Torvalds 
616cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
617efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
618efc7688bSMarcel Holtmann 
619cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
620efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
621efc7688bSMarcel Holtmann 
622cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
623efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
6241da177e4SLinus Torvalds }
6251da177e4SLinus Torvalds 
626971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
627971e3a4bSAndre Guedes 					   struct sk_buff *skb)
628971e3a4bSAndre Guedes {
629971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
630971e3a4bSAndre Guedes 
6319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
632971e3a4bSAndre Guedes 
633971e3a4bSAndre Guedes 	if (rp->status)
63442c6b129SJohan Hedberg 		return;
635971e3a4bSAndre Guedes 
63657af75a8SMarcel Holtmann 	if (hdev->max_page < rp->max_page)
637d2c5d77fSJohan Hedberg 		hdev->max_page = rp->max_page;
638d2c5d77fSJohan Hedberg 
639cad718edSJohan Hedberg 	if (rp->page < HCI_MAX_PAGES)
640cad718edSJohan Hedberg 		memcpy(hdev->features[rp->page], rp->features, 8);
641971e3a4bSAndre Guedes }
642971e3a4bSAndre Guedes 
6431e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
6441e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
6451e89cffbSAndrei Emeltchenko {
6461e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
6471e89cffbSAndrei Emeltchenko 
6489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
6491e89cffbSAndrei Emeltchenko 
65045296acdSMarcel Holtmann 	if (rp->status)
65145296acdSMarcel Holtmann 		return;
65245296acdSMarcel Holtmann 
6531e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
6541e89cffbSAndrei Emeltchenko }
6551e89cffbSAndrei Emeltchenko 
656a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
657a9de9248SMarcel Holtmann {
658a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
659a9de9248SMarcel Holtmann 
6609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
661a9de9248SMarcel Holtmann 
662a9de9248SMarcel Holtmann 	if (rp->status)
663a9de9248SMarcel Holtmann 		return;
664a9de9248SMarcel Holtmann 
665a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
666a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
667a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
668a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
669da1f5198SMarcel Holtmann 
670da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
671da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
672da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
673da1f5198SMarcel Holtmann 	}
674da1f5198SMarcel Holtmann 
675da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
676da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
6771da177e4SLinus Torvalds 
678807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
679807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
6801da177e4SLinus Torvalds }
6811da177e4SLinus Torvalds 
682a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
683a9de9248SMarcel Holtmann {
684a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6851da177e4SLinus Torvalds 
6869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
687a9de9248SMarcel Holtmann 
688e30d3f5fSMarcel Holtmann 	if (rp->status)
689e30d3f5fSMarcel Holtmann 		return;
690e30d3f5fSMarcel Holtmann 
691e30d3f5fSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
692a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
693e30d3f5fSMarcel Holtmann 
694d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SETUP))
695e30d3f5fSMarcel Holtmann 		bacpy(&hdev->setup_addr, &rp->bdaddr);
69623bb5763SJohan Hedberg }
69723bb5763SJohan Hedberg 
698f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
699f332ec66SJohan Hedberg 					   struct sk_buff *skb)
700f332ec66SJohan Hedberg {
701f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
702f332ec66SJohan Hedberg 
703f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
704f332ec66SJohan Hedberg 
70545296acdSMarcel Holtmann 	if (rp->status)
70645296acdSMarcel Holtmann 		return;
70745296acdSMarcel Holtmann 
70845296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags)) {
709f332ec66SJohan Hedberg 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
710f332ec66SJohan Hedberg 		hdev->page_scan_window = __le16_to_cpu(rp->window);
711f332ec66SJohan Hedberg 	}
712f332ec66SJohan Hedberg }
713f332ec66SJohan Hedberg 
7144a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
7154a3ee763SJohan Hedberg 					    struct sk_buff *skb)
7164a3ee763SJohan Hedberg {
7174a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
7184a3ee763SJohan Hedberg 	struct hci_cp_write_page_scan_activity *sent;
7194a3ee763SJohan Hedberg 
7204a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
7214a3ee763SJohan Hedberg 
7224a3ee763SJohan Hedberg 	if (status)
7234a3ee763SJohan Hedberg 		return;
7244a3ee763SJohan Hedberg 
7254a3ee763SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
7264a3ee763SJohan Hedberg 	if (!sent)
7274a3ee763SJohan Hedberg 		return;
7284a3ee763SJohan Hedberg 
7294a3ee763SJohan Hedberg 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
7304a3ee763SJohan Hedberg 	hdev->page_scan_window = __le16_to_cpu(sent->window);
7314a3ee763SJohan Hedberg }
7324a3ee763SJohan Hedberg 
733f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
734f332ec66SJohan Hedberg 					   struct sk_buff *skb)
735f332ec66SJohan Hedberg {
736f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
737f332ec66SJohan Hedberg 
738f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
739f332ec66SJohan Hedberg 
74045296acdSMarcel Holtmann 	if (rp->status)
74145296acdSMarcel Holtmann 		return;
74245296acdSMarcel Holtmann 
74345296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
744f332ec66SJohan Hedberg 		hdev->page_scan_type = rp->type;
745f332ec66SJohan Hedberg }
746f332ec66SJohan Hedberg 
7474a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
7484a3ee763SJohan Hedberg 					struct sk_buff *skb)
7494a3ee763SJohan Hedberg {
7504a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
7514a3ee763SJohan Hedberg 	u8 *type;
7524a3ee763SJohan Hedberg 
7534a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
7544a3ee763SJohan Hedberg 
7554a3ee763SJohan Hedberg 	if (status)
7564a3ee763SJohan Hedberg 		return;
7574a3ee763SJohan Hedberg 
7584a3ee763SJohan Hedberg 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
7594a3ee763SJohan Hedberg 	if (type)
7604a3ee763SJohan Hedberg 		hdev->page_scan_type = *type;
7614a3ee763SJohan Hedberg }
7624a3ee763SJohan Hedberg 
763350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
764350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
765350ee4cfSAndrei Emeltchenko {
766350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
767350ee4cfSAndrei Emeltchenko 
7689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
769350ee4cfSAndrei Emeltchenko 
770350ee4cfSAndrei Emeltchenko 	if (rp->status)
771350ee4cfSAndrei Emeltchenko 		return;
772350ee4cfSAndrei Emeltchenko 
773350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
774350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
775350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
776350ee4cfSAndrei Emeltchenko 
777350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
778350ee4cfSAndrei Emeltchenko 
779350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
780350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
781350ee4cfSAndrei Emeltchenko }
782350ee4cfSAndrei Emeltchenko 
78333f35721SJohan Hedberg static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb)
78433f35721SJohan Hedberg {
78533f35721SJohan Hedberg 	struct hci_rp_read_clock *rp = (void *) skb->data;
78633f35721SJohan Hedberg 	struct hci_cp_read_clock *cp;
78733f35721SJohan Hedberg 	struct hci_conn *conn;
78833f35721SJohan Hedberg 
78933f35721SJohan Hedberg 	BT_DBG("%s", hdev->name);
79033f35721SJohan Hedberg 
79133f35721SJohan Hedberg 	if (skb->len < sizeof(*rp))
79233f35721SJohan Hedberg 		return;
79333f35721SJohan Hedberg 
79433f35721SJohan Hedberg 	if (rp->status)
79533f35721SJohan Hedberg 		return;
79633f35721SJohan Hedberg 
79733f35721SJohan Hedberg 	hci_dev_lock(hdev);
79833f35721SJohan Hedberg 
79933f35721SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
80033f35721SJohan Hedberg 	if (!cp)
80133f35721SJohan Hedberg 		goto unlock;
80233f35721SJohan Hedberg 
80333f35721SJohan Hedberg 	if (cp->which == 0x00) {
80433f35721SJohan Hedberg 		hdev->clock = le32_to_cpu(rp->clock);
80533f35721SJohan Hedberg 		goto unlock;
80633f35721SJohan Hedberg 	}
80733f35721SJohan Hedberg 
80833f35721SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
80933f35721SJohan Hedberg 	if (conn) {
81033f35721SJohan Hedberg 		conn->clock = le32_to_cpu(rp->clock);
81133f35721SJohan Hedberg 		conn->clock_accuracy = le16_to_cpu(rp->accuracy);
81233f35721SJohan Hedberg 	}
81333f35721SJohan Hedberg 
81433f35721SJohan Hedberg unlock:
81533f35721SJohan Hedberg 	hci_dev_unlock(hdev);
81633f35721SJohan Hedberg }
81733f35721SJohan Hedberg 
818928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
819928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
820928abaa7SAndrei Emeltchenko {
821928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
822928abaa7SAndrei Emeltchenko 
8239f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
824928abaa7SAndrei Emeltchenko 
825928abaa7SAndrei Emeltchenko 	if (rp->status)
8268e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
827928abaa7SAndrei Emeltchenko 
828928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
829928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
830928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
831928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
832928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
833928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
834928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
835928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
836928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
837928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
838928abaa7SAndrei Emeltchenko 
8398e2a0d92SAndrei Emeltchenko a2mp_rsp:
8408e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
841928abaa7SAndrei Emeltchenko }
842928abaa7SAndrei Emeltchenko 
843903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
844903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
845903e4541SAndrei Emeltchenko {
846903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
847903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
848903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
849903e4541SAndrei Emeltchenko 
850903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
851903e4541SAndrei Emeltchenko 
852903e4541SAndrei Emeltchenko 	if (rp->status)
853903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
854903e4541SAndrei Emeltchenko 
855903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
856903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
857903e4541SAndrei Emeltchenko 
858903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
8592e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
860903e4541SAndrei Emeltchenko 
861903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
862903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
863903e4541SAndrei Emeltchenko 
864903e4541SAndrei Emeltchenko 		/* Read other fragments */
865903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
866903e4541SAndrei Emeltchenko 
867903e4541SAndrei Emeltchenko 		return;
868903e4541SAndrei Emeltchenko 	}
869903e4541SAndrei Emeltchenko 
870903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
871903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
872903e4541SAndrei Emeltchenko 	assoc->offset = 0;
873903e4541SAndrei Emeltchenko 
874903e4541SAndrei Emeltchenko a2mp_rsp:
875903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
876903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
8779495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
878903e4541SAndrei Emeltchenko }
879903e4541SAndrei Emeltchenko 
880d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
881d5859e22SJohan Hedberg 					 struct sk_buff *skb)
882d5859e22SJohan Hedberg {
88391c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
884d5859e22SJohan Hedberg 
8859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
886d5859e22SJohan Hedberg 
88745296acdSMarcel Holtmann 	if (rp->status)
88845296acdSMarcel Holtmann 		return;
88945296acdSMarcel Holtmann 
89091c4e9b1SMarcel Holtmann 	hdev->inq_tx_power = rp->tx_power;
891d5859e22SJohan Hedberg }
892d5859e22SJohan Hedberg 
893980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
894980e1a53SJohan Hedberg {
895980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
896980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
897980e1a53SJohan Hedberg 	struct hci_conn *conn;
898980e1a53SJohan Hedberg 
8999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
900980e1a53SJohan Hedberg 
90156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
90256e5cb86SJohan Hedberg 
903d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
904744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
905980e1a53SJohan Hedberg 
906fa1bd918SMikel Astiz 	if (rp->status)
90756e5cb86SJohan Hedberg 		goto unlock;
908980e1a53SJohan Hedberg 
909980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
910980e1a53SJohan Hedberg 	if (!cp)
91156e5cb86SJohan Hedberg 		goto unlock;
912980e1a53SJohan Hedberg 
913980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
914980e1a53SJohan Hedberg 	if (conn)
915980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
91656e5cb86SJohan Hedberg 
91756e5cb86SJohan Hedberg unlock:
91856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
919980e1a53SJohan Hedberg }
920980e1a53SJohan Hedberg 
921980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
922980e1a53SJohan Hedberg {
923980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
924980e1a53SJohan Hedberg 
9259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
926980e1a53SJohan Hedberg 
92756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92856e5cb86SJohan Hedberg 
929d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
930744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
931980e1a53SJohan Hedberg 						 rp->status);
93256e5cb86SJohan Hedberg 
93356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
934980e1a53SJohan Hedberg }
93556e5cb86SJohan Hedberg 
9366ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9376ed58ec5SVille Tervo 				       struct sk_buff *skb)
9386ed58ec5SVille Tervo {
9396ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9406ed58ec5SVille Tervo 
9419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9426ed58ec5SVille Tervo 
9436ed58ec5SVille Tervo 	if (rp->status)
9446ed58ec5SVille Tervo 		return;
9456ed58ec5SVille Tervo 
9466ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9476ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9486ed58ec5SVille Tervo 
9496ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9506ed58ec5SVille Tervo 
9516ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9526ed58ec5SVille Tervo }
953980e1a53SJohan Hedberg 
95460e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
95560e77321SJohan Hedberg 					  struct sk_buff *skb)
95660e77321SJohan Hedberg {
95760e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
95860e77321SJohan Hedberg 
95960e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
96060e77321SJohan Hedberg 
96145296acdSMarcel Holtmann 	if (rp->status)
96245296acdSMarcel Holtmann 		return;
96345296acdSMarcel Holtmann 
96460e77321SJohan Hedberg 	memcpy(hdev->le_features, rp->features, 8);
96560e77321SJohan Hedberg }
96660e77321SJohan Hedberg 
9678fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
9688fa19098SJohan Hedberg 					struct sk_buff *skb)
9698fa19098SJohan Hedberg {
9708fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
9718fa19098SJohan Hedberg 
9728fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9738fa19098SJohan Hedberg 
97445296acdSMarcel Holtmann 	if (rp->status)
97545296acdSMarcel Holtmann 		return;
97645296acdSMarcel Holtmann 
9778fa19098SJohan Hedberg 	hdev->adv_tx_power = rp->tx_power;
9788fa19098SJohan Hedberg }
9798fa19098SJohan Hedberg 
980a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
981a5c29683SJohan Hedberg {
982a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
983a5c29683SJohan Hedberg 
9849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
985a5c29683SJohan Hedberg 
98656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
98756e5cb86SJohan Hedberg 
988d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
98904124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
99004124681SGustavo F. Padovan 						 rp->status);
99156e5cb86SJohan Hedberg 
99256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
993a5c29683SJohan Hedberg }
994a5c29683SJohan Hedberg 
995a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
996a5c29683SJohan Hedberg 					  struct sk_buff *skb)
997a5c29683SJohan Hedberg {
998a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
999a5c29683SJohan Hedberg 
10009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1001a5c29683SJohan Hedberg 
100256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
100356e5cb86SJohan Hedberg 
1004d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
1005744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
100604124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
100756e5cb86SJohan Hedberg 
100856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1009a5c29683SJohan Hedberg }
1010a5c29683SJohan Hedberg 
10111143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
10121143d458SBrian Gix {
10131143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10141143d458SBrian Gix 
10159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10161143d458SBrian Gix 
10171143d458SBrian Gix 	hci_dev_lock(hdev);
10181143d458SBrian Gix 
1019d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
1020272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1021272d90dfSJohan Hedberg 						 0, rp->status);
10221143d458SBrian Gix 
10231143d458SBrian Gix 	hci_dev_unlock(hdev);
10241143d458SBrian Gix }
10251143d458SBrian Gix 
10261143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10271143d458SBrian Gix 					  struct sk_buff *skb)
10281143d458SBrian Gix {
10291143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10301143d458SBrian Gix 
10319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10321143d458SBrian Gix 
10331143d458SBrian Gix 	hci_dev_lock(hdev);
10341143d458SBrian Gix 
1035d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
10361143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
103704124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
10381143d458SBrian Gix 
10391143d458SBrian Gix 	hci_dev_unlock(hdev);
10401143d458SBrian Gix }
10411143d458SBrian Gix 
10424d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
1043c35938b2SSzymon Janc 				       struct sk_buff *skb)
1044c35938b2SSzymon Janc {
1045c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1046c35938b2SSzymon Janc 
10479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10484d2d2796SMarcel Holtmann }
10494d2d2796SMarcel Holtmann 
10504d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
10514d2d2796SMarcel Holtmann 					   struct sk_buff *skb)
10524d2d2796SMarcel Holtmann {
10534d2d2796SMarcel Holtmann 	struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
10544d2d2796SMarcel Holtmann 
10554d2d2796SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1056c35938b2SSzymon Janc }
1057c35938b2SSzymon Janc 
10587a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
10597a4cd51dSMarcel Holtmann {
10607a4cd51dSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
10617a4cd51dSMarcel Holtmann 	bdaddr_t *sent;
10627a4cd51dSMarcel Holtmann 
10637a4cd51dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10647a4cd51dSMarcel Holtmann 
106545296acdSMarcel Holtmann 	if (status)
106645296acdSMarcel Holtmann 		return;
106745296acdSMarcel Holtmann 
10687a4cd51dSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
10697a4cd51dSMarcel Holtmann 	if (!sent)
10707a4cd51dSMarcel Holtmann 		return;
10717a4cd51dSMarcel Holtmann 
10727a4cd51dSMarcel Holtmann 	hci_dev_lock(hdev);
10737a4cd51dSMarcel Holtmann 
10747a4cd51dSMarcel Holtmann 	bacpy(&hdev->random_addr, sent);
10757a4cd51dSMarcel Holtmann 
10767a4cd51dSMarcel Holtmann 	hci_dev_unlock(hdev);
10777a4cd51dSMarcel Holtmann }
10787a4cd51dSMarcel Holtmann 
1079c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1080c1d5dc4aSJohan Hedberg {
1081c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
1082c1d5dc4aSJohan Hedberg 
1083c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1084c1d5dc4aSJohan Hedberg 
108545296acdSMarcel Holtmann 	if (status)
1086c1d5dc4aSJohan Hedberg 		return;
1087c1d5dc4aSJohan Hedberg 
108845296acdSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
108945296acdSMarcel Holtmann 	if (!sent)
10903c857757SJohan Hedberg 		return;
10913c857757SJohan Hedberg 
1092c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
1093c1d5dc4aSJohan Hedberg 
109449c922bbSStephen Hemminger 	/* If we're doing connection initiation as peripheral. Set a
10953c857757SJohan Hedberg 	 * timeout in case something goes wrong.
10963c857757SJohan Hedberg 	 */
10973c857757SJohan Hedberg 	if (*sent) {
10983c857757SJohan Hedberg 		struct hci_conn *conn;
10993c857757SJohan Hedberg 
1100a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_LE_ADV);
110166c417c1SJohan Hedberg 
11023c857757SJohan Hedberg 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
11033c857757SJohan Hedberg 		if (conn)
11043c857757SJohan Hedberg 			queue_delayed_work(hdev->workqueue,
11053c857757SJohan Hedberg 					   &conn->le_conn_timeout,
110609ae260bSJohan Hedberg 					   conn->conn_timeout);
110766c417c1SJohan Hedberg 	} else {
1108a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_LE_ADV);
11093c857757SJohan Hedberg 	}
11103c857757SJohan Hedberg 
111104b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
1112c1d5dc4aSJohan Hedberg }
1113c1d5dc4aSJohan Hedberg 
1114533553f8SMarcel Holtmann static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1115533553f8SMarcel Holtmann {
1116533553f8SMarcel Holtmann 	struct hci_cp_le_set_scan_param *cp;
1117533553f8SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1118533553f8SMarcel Holtmann 
1119533553f8SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1120533553f8SMarcel Holtmann 
112145296acdSMarcel Holtmann 	if (status)
112245296acdSMarcel Holtmann 		return;
112345296acdSMarcel Holtmann 
1124533553f8SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM);
1125533553f8SMarcel Holtmann 	if (!cp)
1126533553f8SMarcel Holtmann 		return;
1127533553f8SMarcel Holtmann 
1128533553f8SMarcel Holtmann 	hci_dev_lock(hdev);
1129533553f8SMarcel Holtmann 
1130533553f8SMarcel Holtmann 	hdev->le_scan_type = cp->type;
1131533553f8SMarcel Holtmann 
1132533553f8SMarcel Holtmann 	hci_dev_unlock(hdev);
1133533553f8SMarcel Holtmann }
1134533553f8SMarcel Holtmann 
1135b9a6328fSJohan Hedberg static bool has_pending_adv_report(struct hci_dev *hdev)
1136b9a6328fSJohan Hedberg {
1137b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1138b9a6328fSJohan Hedberg 
1139b9a6328fSJohan Hedberg 	return bacmp(&d->last_adv_addr, BDADDR_ANY);
1140b9a6328fSJohan Hedberg }
1141b9a6328fSJohan Hedberg 
1142b9a6328fSJohan Hedberg static void clear_pending_adv_report(struct hci_dev *hdev)
1143b9a6328fSJohan Hedberg {
1144b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1145b9a6328fSJohan Hedberg 
1146b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, BDADDR_ANY);
1147b9a6328fSJohan Hedberg 	d->last_adv_data_len = 0;
1148b9a6328fSJohan Hedberg }
1149b9a6328fSJohan Hedberg 
1150b9a6328fSJohan Hedberg static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
1151c70a7e4cSMarcel Holtmann 				     u8 bdaddr_type, s8 rssi, u32 flags,
1152c70a7e4cSMarcel Holtmann 				     u8 *data, u8 len)
1153b9a6328fSJohan Hedberg {
1154b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1155b9a6328fSJohan Hedberg 
1156b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, bdaddr);
1157b9a6328fSJohan Hedberg 	d->last_adv_addr_type = bdaddr_type;
1158ff5cd29fSJohan Hedberg 	d->last_adv_rssi = rssi;
1159c70a7e4cSMarcel Holtmann 	d->last_adv_flags = flags;
1160b9a6328fSJohan Hedberg 	memcpy(d->last_adv_data, data, len);
1161b9a6328fSJohan Hedberg 	d->last_adv_data_len = len;
1162b9a6328fSJohan Hedberg }
1163b9a6328fSJohan Hedberg 
1164eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1165eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1166eb9d91f5SAndre Guedes {
1167eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1168eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1169eb9d91f5SAndre Guedes 
11709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1171eb9d91f5SAndre Guedes 
117245296acdSMarcel Holtmann 	if (status)
1173eb9d91f5SAndre Guedes 		return;
1174eb9d91f5SAndre Guedes 
117545296acdSMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
117645296acdSMarcel Holtmann 	if (!cp)
11777ba8b4beSAndre Guedes 		return;
11787ba8b4beSAndre Guedes 
11795c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
11805c1a4c8fSJaganath Kanakkassery 
11813fd319b8SAndre Guedes 	switch (cp->enable) {
11823fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
1183a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_LE_SCAN);
1184b9a6328fSJohan Hedberg 		if (hdev->le_scan_type == LE_SCAN_ACTIVE)
1185b9a6328fSJohan Hedberg 			clear_pending_adv_report(hdev);
118668a8aea4SAndrei Emeltchenko 		break;
118768a8aea4SAndrei Emeltchenko 
118876a388beSAndre Guedes 	case LE_SCAN_DISABLE:
1189b9a6328fSJohan Hedberg 		/* We do this here instead of when setting DISCOVERY_STOPPED
1190b9a6328fSJohan Hedberg 		 * since the latter would potentially require waiting for
1191b9a6328fSJohan Hedberg 		 * inquiry to stop too.
1192b9a6328fSJohan Hedberg 		 */
1193b9a6328fSJohan Hedberg 		if (has_pending_adv_report(hdev)) {
1194b9a6328fSJohan Hedberg 			struct discovery_state *d = &hdev->discovery;
1195b9a6328fSJohan Hedberg 
1196b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
1197ab0aa433SJohan Hedberg 					  d->last_adv_addr_type, NULL,
1198c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
1199ab0aa433SJohan Hedberg 					  d->last_adv_data,
1200b9a6328fSJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
1201b9a6328fSJohan Hedberg 		}
1202b9a6328fSJohan Hedberg 
1203317ac8cbSJohan Hedberg 		/* Cancel this timer so that we don't try to disable scanning
1204317ac8cbSJohan Hedberg 		 * when it's already disabled.
1205317ac8cbSJohan Hedberg 		 */
1206317ac8cbSJohan Hedberg 		cancel_delayed_work(&hdev->le_scan_disable);
1207317ac8cbSJohan Hedberg 
1208a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_LE_SCAN);
1209e8bb6b97SJohan Hedberg 
121081ad6fd9SJohan Hedberg 		/* The HCI_LE_SCAN_INTERRUPTED flag indicates that we
121181ad6fd9SJohan Hedberg 		 * interrupted scanning due to a connect request. Mark
1212e8bb6b97SJohan Hedberg 		 * therefore discovery as stopped. If this was not
1213e8bb6b97SJohan Hedberg 		 * because of a connect request advertising might have
1214e8bb6b97SJohan Hedberg 		 * been disabled because of active scanning, so
1215e8bb6b97SJohan Hedberg 		 * re-enable it again if necessary.
121681ad6fd9SJohan Hedberg 		 */
1217a69d8927SMarcel Holtmann 		if (hci_dev_test_and_clear_flag(hdev, HCI_LE_SCAN_INTERRUPTED))
121881ad6fd9SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1219d7a5a11dSMarcel Holtmann 		else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) &&
122034722277SJohan Hedberg 			 hdev->discovery.state == DISCOVERY_FINDING)
1221e8bb6b97SJohan Hedberg 			mgmt_reenable_advertising(hdev);
1222e8bb6b97SJohan Hedberg 
122368a8aea4SAndrei Emeltchenko 		break;
122468a8aea4SAndrei Emeltchenko 
122568a8aea4SAndrei Emeltchenko 	default:
122668a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
122768a8aea4SAndrei Emeltchenko 		break;
122835815085SAndre Guedes 	}
12295c1a4c8fSJaganath Kanakkassery 
12305c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
1231eb9d91f5SAndre Guedes }
1232eb9d91f5SAndre Guedes 
1233cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1234cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
1235cf1d081fSJohan Hedberg {
1236cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1237cf1d081fSJohan Hedberg 
1238cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1239cf1d081fSJohan Hedberg 
124045296acdSMarcel Holtmann 	if (rp->status)
124145296acdSMarcel Holtmann 		return;
124245296acdSMarcel Holtmann 
1243cf1d081fSJohan Hedberg 	hdev->le_white_list_size = rp->size;
1244cf1d081fSJohan Hedberg }
1245cf1d081fSJohan Hedberg 
12460f36b589SMarcel Holtmann static void hci_cc_le_clear_white_list(struct hci_dev *hdev,
12470f36b589SMarcel Holtmann 				       struct sk_buff *skb)
12480f36b589SMarcel Holtmann {
12490f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12500f36b589SMarcel Holtmann 
12510f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12520f36b589SMarcel Holtmann 
125345296acdSMarcel Holtmann 	if (status)
125445296acdSMarcel Holtmann 		return;
125545296acdSMarcel Holtmann 
1256dcc36c16SJohan Hedberg 	hci_bdaddr_list_clear(&hdev->le_white_list);
12570f36b589SMarcel Holtmann }
12580f36b589SMarcel Holtmann 
12590f36b589SMarcel Holtmann static void hci_cc_le_add_to_white_list(struct hci_dev *hdev,
12600f36b589SMarcel Holtmann 					struct sk_buff *skb)
12610f36b589SMarcel Holtmann {
12620f36b589SMarcel Holtmann 	struct hci_cp_le_add_to_white_list *sent;
12630f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12640f36b589SMarcel Holtmann 
12650f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12660f36b589SMarcel Holtmann 
126745296acdSMarcel Holtmann 	if (status)
126845296acdSMarcel Holtmann 		return;
126945296acdSMarcel Holtmann 
12700f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST);
12710f36b589SMarcel Holtmann 	if (!sent)
12720f36b589SMarcel Holtmann 		return;
12730f36b589SMarcel Holtmann 
1274dcc36c16SJohan Hedberg 	hci_bdaddr_list_add(&hdev->le_white_list, &sent->bdaddr,
1275dcc36c16SJohan Hedberg 			   sent->bdaddr_type);
12760f36b589SMarcel Holtmann }
12770f36b589SMarcel Holtmann 
12780f36b589SMarcel Holtmann static void hci_cc_le_del_from_white_list(struct hci_dev *hdev,
12790f36b589SMarcel Holtmann 					  struct sk_buff *skb)
12800f36b589SMarcel Holtmann {
12810f36b589SMarcel Holtmann 	struct hci_cp_le_del_from_white_list *sent;
12820f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12830f36b589SMarcel Holtmann 
12840f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12850f36b589SMarcel Holtmann 
128645296acdSMarcel Holtmann 	if (status)
128745296acdSMarcel Holtmann 		return;
128845296acdSMarcel Holtmann 
12890f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST);
12900f36b589SMarcel Holtmann 	if (!sent)
12910f36b589SMarcel Holtmann 		return;
12920f36b589SMarcel Holtmann 
1293dcc36c16SJohan Hedberg 	hci_bdaddr_list_del(&hdev->le_white_list, &sent->bdaddr,
1294dcc36c16SJohan Hedberg 			    sent->bdaddr_type);
12950f36b589SMarcel Holtmann }
12960f36b589SMarcel Holtmann 
12979b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
12989b008c04SJohan Hedberg 					    struct sk_buff *skb)
12999b008c04SJohan Hedberg {
13009b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
13019b008c04SJohan Hedberg 
13029b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
13039b008c04SJohan Hedberg 
130445296acdSMarcel Holtmann 	if (rp->status)
130545296acdSMarcel Holtmann 		return;
130645296acdSMarcel Holtmann 
13079b008c04SJohan Hedberg 	memcpy(hdev->le_states, rp->le_states, 8);
13089b008c04SJohan Hedberg }
13099b008c04SJohan Hedberg 
1310a8e1bfaaSMarcel Holtmann static void hci_cc_le_read_def_data_len(struct hci_dev *hdev,
1311a8e1bfaaSMarcel Holtmann 					struct sk_buff *skb)
1312a8e1bfaaSMarcel Holtmann {
1313a8e1bfaaSMarcel Holtmann 	struct hci_rp_le_read_def_data_len *rp = (void *) skb->data;
1314a8e1bfaaSMarcel Holtmann 
1315a8e1bfaaSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1316a8e1bfaaSMarcel Holtmann 
1317a8e1bfaaSMarcel Holtmann 	if (rp->status)
1318a8e1bfaaSMarcel Holtmann 		return;
1319a8e1bfaaSMarcel Holtmann 
1320a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_len = le16_to_cpu(rp->tx_len);
1321a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_time = le16_to_cpu(rp->tx_time);
1322a8e1bfaaSMarcel Holtmann }
1323a8e1bfaaSMarcel Holtmann 
1324a8e1bfaaSMarcel Holtmann static void hci_cc_le_write_def_data_len(struct hci_dev *hdev,
1325a8e1bfaaSMarcel Holtmann 					 struct sk_buff *skb)
1326a8e1bfaaSMarcel Holtmann {
1327a8e1bfaaSMarcel Holtmann 	struct hci_cp_le_write_def_data_len *sent;
1328a8e1bfaaSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1329a8e1bfaaSMarcel Holtmann 
1330a8e1bfaaSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1331a8e1bfaaSMarcel Holtmann 
1332a8e1bfaaSMarcel Holtmann 	if (status)
1333a8e1bfaaSMarcel Holtmann 		return;
1334a8e1bfaaSMarcel Holtmann 
1335a8e1bfaaSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN);
1336a8e1bfaaSMarcel Holtmann 	if (!sent)
1337a8e1bfaaSMarcel Holtmann 		return;
1338a8e1bfaaSMarcel Holtmann 
1339a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_len = le16_to_cpu(sent->tx_len);
1340a8e1bfaaSMarcel Holtmann 	hdev->le_def_tx_time = le16_to_cpu(sent->tx_time);
1341a8e1bfaaSMarcel Holtmann }
1342a8e1bfaaSMarcel Holtmann 
1343a8e1bfaaSMarcel Holtmann static void hci_cc_le_read_max_data_len(struct hci_dev *hdev,
1344a8e1bfaaSMarcel Holtmann 					struct sk_buff *skb)
1345a8e1bfaaSMarcel Holtmann {
1346a8e1bfaaSMarcel Holtmann 	struct hci_rp_le_read_max_data_len *rp = (void *) skb->data;
1347a8e1bfaaSMarcel Holtmann 
1348a8e1bfaaSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1349a8e1bfaaSMarcel Holtmann 
1350a8e1bfaaSMarcel Holtmann 	if (rp->status)
1351a8e1bfaaSMarcel Holtmann 		return;
1352a8e1bfaaSMarcel Holtmann 
1353a8e1bfaaSMarcel Holtmann 	hdev->le_max_tx_len = le16_to_cpu(rp->tx_len);
1354a8e1bfaaSMarcel Holtmann 	hdev->le_max_tx_time = le16_to_cpu(rp->tx_time);
1355a8e1bfaaSMarcel Holtmann 	hdev->le_max_rx_len = le16_to_cpu(rp->rx_len);
1356a8e1bfaaSMarcel Holtmann 	hdev->le_max_rx_time = le16_to_cpu(rp->rx_time);
1357a8e1bfaaSMarcel Holtmann }
1358a8e1bfaaSMarcel Holtmann 
13596039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1360f9b49306SAndre Guedes 					   struct sk_buff *skb)
1361f9b49306SAndre Guedes {
136206199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1363f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1364f9b49306SAndre Guedes 
13659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1366f9b49306SAndre Guedes 
136745296acdSMarcel Holtmann 	if (status)
136845296acdSMarcel Holtmann 		return;
136945296acdSMarcel Holtmann 
137006199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
13718f984dfaSJohan Hedberg 	if (!sent)
1372f9b49306SAndre Guedes 		return;
1373f9b49306SAndre Guedes 
13745c1a4c8fSJaganath Kanakkassery 	hci_dev_lock(hdev);
13755c1a4c8fSJaganath Kanakkassery 
1376416a4ae5SJohan Hedberg 	if (sent->le) {
1377cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE;
1378a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_LE_ENABLED);
1379416a4ae5SJohan Hedberg 	} else {
1380cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE;
1381a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_LE_ENABLED);
1382a358dc11SMarcel Holtmann 		hci_dev_clear_flag(hdev, HCI_ADVERTISING);
1383416a4ae5SJohan Hedberg 	}
138453b2caabSJohan Hedberg 
138553b2caabSJohan Hedberg 	if (sent->simul)
1386cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE_BREDR;
138753b2caabSJohan Hedberg 	else
1388cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
13895c1a4c8fSJaganath Kanakkassery 
13905c1a4c8fSJaganath Kanakkassery 	hci_dev_unlock(hdev);
13918f984dfaSJohan Hedberg }
1392f9b49306SAndre Guedes 
139356ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
139456ed2cb8SJohan Hedberg {
139556ed2cb8SJohan Hedberg 	struct hci_cp_le_set_adv_param *cp;
139656ed2cb8SJohan Hedberg 	u8 status = *((u8 *) skb->data);
139756ed2cb8SJohan Hedberg 
139856ed2cb8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
139956ed2cb8SJohan Hedberg 
140056ed2cb8SJohan Hedberg 	if (status)
140156ed2cb8SJohan Hedberg 		return;
140256ed2cb8SJohan Hedberg 
140356ed2cb8SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
140456ed2cb8SJohan Hedberg 	if (!cp)
140556ed2cb8SJohan Hedberg 		return;
140656ed2cb8SJohan Hedberg 
140756ed2cb8SJohan Hedberg 	hci_dev_lock(hdev);
140856ed2cb8SJohan Hedberg 	hdev->adv_addr_type = cp->own_address_type;
140956ed2cb8SJohan Hedberg 	hci_dev_unlock(hdev);
141056ed2cb8SJohan Hedberg }
141156ed2cb8SJohan Hedberg 
141293c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
141393c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
141493c284eeSAndrei Emeltchenko {
141593c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
141693c284eeSAndrei Emeltchenko 
141793c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
141893c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
141993c284eeSAndrei Emeltchenko 
142093c284eeSAndrei Emeltchenko 	if (rp->status)
142193c284eeSAndrei Emeltchenko 		return;
142293c284eeSAndrei Emeltchenko 
142393c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
142493c284eeSAndrei Emeltchenko }
142593c284eeSAndrei Emeltchenko 
14265ae76a94SAndrzej Kaczmarek static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
14275ae76a94SAndrzej Kaczmarek {
14285ae76a94SAndrzej Kaczmarek 	struct hci_rp_read_rssi *rp = (void *) skb->data;
14295ae76a94SAndrzej Kaczmarek 	struct hci_conn *conn;
14305ae76a94SAndrzej Kaczmarek 
14315ae76a94SAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
14325ae76a94SAndrzej Kaczmarek 
14335ae76a94SAndrzej Kaczmarek 	if (rp->status)
14345ae76a94SAndrzej Kaczmarek 		return;
14355ae76a94SAndrzej Kaczmarek 
14365ae76a94SAndrzej Kaczmarek 	hci_dev_lock(hdev);
14375ae76a94SAndrzej Kaczmarek 
14385ae76a94SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
14395ae76a94SAndrzej Kaczmarek 	if (conn)
14405ae76a94SAndrzej Kaczmarek 		conn->rssi = rp->rssi;
14415ae76a94SAndrzej Kaczmarek 
14425ae76a94SAndrzej Kaczmarek 	hci_dev_unlock(hdev);
14435ae76a94SAndrzej Kaczmarek }
14445ae76a94SAndrzej Kaczmarek 
14455a134faeSAndrzej Kaczmarek static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb)
14465a134faeSAndrzej Kaczmarek {
14475a134faeSAndrzej Kaczmarek 	struct hci_cp_read_tx_power *sent;
14485a134faeSAndrzej Kaczmarek 	struct hci_rp_read_tx_power *rp = (void *) skb->data;
14495a134faeSAndrzej Kaczmarek 	struct hci_conn *conn;
14505a134faeSAndrzej Kaczmarek 
14515a134faeSAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
14525a134faeSAndrzej Kaczmarek 
14535a134faeSAndrzej Kaczmarek 	if (rp->status)
14545a134faeSAndrzej Kaczmarek 		return;
14555a134faeSAndrzej Kaczmarek 
14565a134faeSAndrzej Kaczmarek 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
14575a134faeSAndrzej Kaczmarek 	if (!sent)
14585a134faeSAndrzej Kaczmarek 		return;
14595a134faeSAndrzej Kaczmarek 
14605a134faeSAndrzej Kaczmarek 	hci_dev_lock(hdev);
14615a134faeSAndrzej Kaczmarek 
14625a134faeSAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1463d0455ed9SAndrzej Kaczmarek 	if (!conn)
1464d0455ed9SAndrzej Kaczmarek 		goto unlock;
14655a134faeSAndrzej Kaczmarek 
1466d0455ed9SAndrzej Kaczmarek 	switch (sent->type) {
1467d0455ed9SAndrzej Kaczmarek 	case 0x00:
1468d0455ed9SAndrzej Kaczmarek 		conn->tx_power = rp->tx_power;
1469d0455ed9SAndrzej Kaczmarek 		break;
1470d0455ed9SAndrzej Kaczmarek 	case 0x01:
1471d0455ed9SAndrzej Kaczmarek 		conn->max_tx_power = rp->tx_power;
1472d0455ed9SAndrzej Kaczmarek 		break;
1473d0455ed9SAndrzej Kaczmarek 	}
1474d0455ed9SAndrzej Kaczmarek 
1475d0455ed9SAndrzej Kaczmarek unlock:
14765a134faeSAndrzej Kaczmarek 	hci_dev_unlock(hdev);
14775a134faeSAndrzej Kaczmarek }
14785a134faeSAndrzej Kaczmarek 
1479c50b33c8SMarcel Holtmann static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb)
1480c50b33c8SMarcel Holtmann {
1481c50b33c8SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
1482c50b33c8SMarcel Holtmann 	u8 *mode;
1483c50b33c8SMarcel Holtmann 
1484c50b33c8SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1485c50b33c8SMarcel Holtmann 
1486c50b33c8SMarcel Holtmann 	if (status)
1487c50b33c8SMarcel Holtmann 		return;
1488c50b33c8SMarcel Holtmann 
1489c50b33c8SMarcel Holtmann 	mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE);
1490c50b33c8SMarcel Holtmann 	if (mode)
1491c50b33c8SMarcel Holtmann 		hdev->ssp_debug_mode = *mode;
1492c50b33c8SMarcel Holtmann }
1493c50b33c8SMarcel Holtmann 
14946039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1495a9de9248SMarcel Holtmann {
14969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1497a9de9248SMarcel Holtmann 
1498a9de9248SMarcel Holtmann 	if (status) {
1499a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1500314b2381SJohan Hedberg 		return;
1501314b2381SJohan Hedberg 	}
1502314b2381SJohan Hedberg 
150389352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1504a9de9248SMarcel Holtmann }
1505a9de9248SMarcel Holtmann 
15066039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
15071da177e4SLinus Torvalds {
1508a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
15091da177e4SLinus Torvalds 	struct hci_conn *conn;
15101da177e4SLinus Torvalds 
15119f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1512a9de9248SMarcel Holtmann 
1513a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
15141da177e4SLinus Torvalds 	if (!cp)
15151da177e4SLinus Torvalds 		return;
15161da177e4SLinus Torvalds 
15171da177e4SLinus Torvalds 	hci_dev_lock(hdev);
15181da177e4SLinus Torvalds 
15191da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
15201da177e4SLinus Torvalds 
15216ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
15221da177e4SLinus Torvalds 
15231da177e4SLinus Torvalds 	if (status) {
15241da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
15254c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
15261da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
1527539c496dSJohan Hedberg 				hci_connect_cfm(conn, status);
15281da177e4SLinus Torvalds 				hci_conn_del(conn);
15294c67bc74SMarcel Holtmann 			} else
15304c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
15311da177e4SLinus Torvalds 		}
15321da177e4SLinus Torvalds 	} else {
15331da177e4SLinus Torvalds 		if (!conn) {
1534a5c4e309SJohan Hedberg 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr,
1535a5c4e309SJohan Hedberg 					    HCI_ROLE_MASTER);
1536a5c4e309SJohan Hedberg 			if (!conn)
1537893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
15381da177e4SLinus Torvalds 		}
15391da177e4SLinus Torvalds 	}
15401da177e4SLinus Torvalds 
15411da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15421da177e4SLinus Torvalds }
15431da177e4SLinus Torvalds 
1544a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
15451da177e4SLinus Torvalds {
1546a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
15471da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
15481da177e4SLinus Torvalds 	__u16 handle;
15491da177e4SLinus Torvalds 
15509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1551b6a0dc82SMarcel Holtmann 
1552a9de9248SMarcel Holtmann 	if (!status)
1553a9de9248SMarcel Holtmann 		return;
1554a9de9248SMarcel Holtmann 
1555a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
15561da177e4SLinus Torvalds 	if (!cp)
1557a9de9248SMarcel Holtmann 		return;
15581da177e4SLinus Torvalds 
15591da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
15601da177e4SLinus Torvalds 
15619f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
15621da177e4SLinus Torvalds 
15631da177e4SLinus Torvalds 	hci_dev_lock(hdev);
15641da177e4SLinus Torvalds 
15651da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15665a08ecceSAndrei Emeltchenko 	if (acl) {
15675a08ecceSAndrei Emeltchenko 		sco = acl->link;
15685a08ecceSAndrei Emeltchenko 		if (sco) {
15691da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
15701da177e4SLinus Torvalds 
1571539c496dSJohan Hedberg 			hci_connect_cfm(sco, status);
15721da177e4SLinus Torvalds 			hci_conn_del(sco);
15731da177e4SLinus Torvalds 		}
15745a08ecceSAndrei Emeltchenko 	}
15751da177e4SLinus Torvalds 
15761da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15771da177e4SLinus Torvalds }
15781da177e4SLinus Torvalds 
1579f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1580f8558555SMarcel Holtmann {
1581f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1582f8558555SMarcel Holtmann 	struct hci_conn *conn;
1583f8558555SMarcel Holtmann 
15849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1585f8558555SMarcel Holtmann 
1586f8558555SMarcel Holtmann 	if (!status)
1587f8558555SMarcel Holtmann 		return;
1588f8558555SMarcel Holtmann 
1589f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1590f8558555SMarcel Holtmann 	if (!cp)
1591f8558555SMarcel Holtmann 		return;
1592f8558555SMarcel Holtmann 
1593f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1594f8558555SMarcel Holtmann 
1595f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1596f8558555SMarcel Holtmann 	if (conn) {
1597f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1598539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
159976a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1600f8558555SMarcel Holtmann 		}
1601f8558555SMarcel Holtmann 	}
1602f8558555SMarcel Holtmann 
1603f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1604f8558555SMarcel Holtmann }
1605f8558555SMarcel Holtmann 
1606f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1607f8558555SMarcel Holtmann {
1608f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1609f8558555SMarcel Holtmann 	struct hci_conn *conn;
1610f8558555SMarcel Holtmann 
16119f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1612f8558555SMarcel Holtmann 
1613f8558555SMarcel Holtmann 	if (!status)
1614f8558555SMarcel Holtmann 		return;
1615f8558555SMarcel Holtmann 
1616f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1617f8558555SMarcel Holtmann 	if (!cp)
1618f8558555SMarcel Holtmann 		return;
1619f8558555SMarcel Holtmann 
1620f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1621f8558555SMarcel Holtmann 
1622f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1623f8558555SMarcel Holtmann 	if (conn) {
1624f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1625539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
162676a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1627f8558555SMarcel Holtmann 		}
1628f8558555SMarcel Holtmann 	}
1629f8558555SMarcel Holtmann 
1630f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1631f8558555SMarcel Holtmann }
1632f8558555SMarcel Holtmann 
1633127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1634392599b9SJohan Hedberg 				    struct hci_conn *conn)
1635392599b9SJohan Hedberg {
1636392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1637392599b9SJohan Hedberg 		return 0;
1638392599b9SJohan Hedberg 
1639765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1640392599b9SJohan Hedberg 		return 0;
1641392599b9SJohan Hedberg 
1642392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1643264b8b4eSJohan Hedberg 	 * devices with sec_level MEDIUM or HIGH or if MITM protection
1644264b8b4eSJohan Hedberg 	 * is requested.
1645264b8b4eSJohan Hedberg 	 */
1646807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
16477e3691e1SJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_FIPS &&
1648264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
1649264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
1650392599b9SJohan Hedberg 		return 0;
1651392599b9SJohan Hedberg 
1652392599b9SJohan Hedberg 	return 1;
1653392599b9SJohan Hedberg }
1654392599b9SJohan Hedberg 
16556039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
165600abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
165730dc78e1SJohan Hedberg {
165830dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
165930dc78e1SJohan Hedberg 
166030dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
166130dc78e1SJohan Hedberg 
166230dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
166330dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
166430dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
166530dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
166630dc78e1SJohan Hedberg 
166730dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
166830dc78e1SJohan Hedberg }
166930dc78e1SJohan Hedberg 
1670b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
167130dc78e1SJohan Hedberg {
167230dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
167330dc78e1SJohan Hedberg 	struct inquiry_entry *e;
167430dc78e1SJohan Hedberg 
1675b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1676b644ba33SJohan Hedberg 		return false;
1677b644ba33SJohan Hedberg 
1678b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1679c810089cSRam Malovany 	if (!e)
1680c810089cSRam Malovany 		return false;
1681c810089cSRam Malovany 
1682b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1683b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1684b644ba33SJohan Hedberg 		return true;
1685b644ba33SJohan Hedberg 	}
1686b644ba33SJohan Hedberg 
1687b644ba33SJohan Hedberg 	return false;
1688b644ba33SJohan Hedberg }
1689b644ba33SJohan Hedberg 
1690b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1691b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1692b644ba33SJohan Hedberg {
1693b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1694b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1695b644ba33SJohan Hedberg 
169660cb49d2SJohan Hedberg 	/* Update the mgmt connected state if necessary. Be careful with
169760cb49d2SJohan Hedberg 	 * conn objects that exist but are not (yet) connected however.
169860cb49d2SJohan Hedberg 	 * Only those in BT_CONFIG or BT_CONNECTED states can be
169960cb49d2SJohan Hedberg 	 * considered connected.
170060cb49d2SJohan Hedberg 	 */
170160cb49d2SJohan Hedberg 	if (conn &&
170260cb49d2SJohan Hedberg 	    (conn->state == BT_CONFIG || conn->state == BT_CONNECTED) &&
1703cb77c3ecSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
170448ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, name, name_len);
1705b644ba33SJohan Hedberg 
1706b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1707b644ba33SJohan Hedberg 		return;
1708b644ba33SJohan Hedberg 
170930dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
171030dc78e1SJohan Hedberg 		goto discov_complete;
171130dc78e1SJohan Hedberg 
171230dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
171330dc78e1SJohan Hedberg 		return;
171430dc78e1SJohan Hedberg 
171530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
17167cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
17177cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
17187cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
17197cc8380eSRam Malovany 	 * Event */
17207cc8380eSRam Malovany 	if (!e)
17217cc8380eSRam Malovany 		return;
17227cc8380eSRam Malovany 
172330dc78e1SJohan Hedberg 	list_del(&e->list);
17247cc8380eSRam Malovany 	if (name) {
17257cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1726b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1727b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1728c3e7c0d9SRam Malovany 	} else {
1729c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
173030dc78e1SJohan Hedberg 	}
173130dc78e1SJohan Hedberg 
1732b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
173330dc78e1SJohan Hedberg 		return;
173430dc78e1SJohan Hedberg 
173530dc78e1SJohan Hedberg discov_complete:
173630dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
173730dc78e1SJohan Hedberg }
173830dc78e1SJohan Hedberg 
1739a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
17401da177e4SLinus Torvalds {
1741127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1742127178d2SJohan Hedberg 	struct hci_conn *conn;
1743127178d2SJohan Hedberg 
17449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1745127178d2SJohan Hedberg 
1746127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1747127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1748127178d2SJohan Hedberg 	if (!status)
1749127178d2SJohan Hedberg 		return;
1750127178d2SJohan Hedberg 
1751127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1752127178d2SJohan Hedberg 	if (!cp)
1753127178d2SJohan Hedberg 		return;
1754127178d2SJohan Hedberg 
1755127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1756127178d2SJohan Hedberg 
1757127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1758b644ba33SJohan Hedberg 
1759d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
1760b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1761b644ba33SJohan Hedberg 
176279c6c70cSJohan Hedberg 	if (!conn)
176379c6c70cSJohan Hedberg 		goto unlock;
176479c6c70cSJohan Hedberg 
176579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
176679c6c70cSJohan Hedberg 		goto unlock;
176779c6c70cSJohan Hedberg 
176851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1769c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
1770c1f23a2bSJohannes Berg 
1771977f8fceSJohan Hedberg 		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
1772977f8fceSJohan Hedberg 
1773c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
1774c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1775c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
1776127178d2SJohan Hedberg 	}
1777127178d2SJohan Hedberg 
177879c6c70cSJohan Hedberg unlock:
1779127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1780a9de9248SMarcel Holtmann }
17811da177e4SLinus Torvalds 
1782769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1783769be974SMarcel Holtmann {
1784769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1785769be974SMarcel Holtmann 	struct hci_conn *conn;
1786769be974SMarcel Holtmann 
17879f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1788769be974SMarcel Holtmann 
1789769be974SMarcel Holtmann 	if (!status)
1790769be974SMarcel Holtmann 		return;
1791769be974SMarcel Holtmann 
1792769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1793769be974SMarcel Holtmann 	if (!cp)
1794769be974SMarcel Holtmann 		return;
1795769be974SMarcel Holtmann 
1796769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1797769be974SMarcel Holtmann 
1798769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1799769be974SMarcel Holtmann 	if (conn) {
1800769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1801539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
180276a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1803769be974SMarcel Holtmann 		}
1804769be974SMarcel Holtmann 	}
1805769be974SMarcel Holtmann 
1806769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1807769be974SMarcel Holtmann }
1808769be974SMarcel Holtmann 
1809769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1810769be974SMarcel Holtmann {
1811769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1812769be974SMarcel Holtmann 	struct hci_conn *conn;
1813769be974SMarcel Holtmann 
18149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1815769be974SMarcel Holtmann 
1816769be974SMarcel Holtmann 	if (!status)
1817769be974SMarcel Holtmann 		return;
1818769be974SMarcel Holtmann 
1819769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1820769be974SMarcel Holtmann 	if (!cp)
1821769be974SMarcel Holtmann 		return;
1822769be974SMarcel Holtmann 
1823769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1824769be974SMarcel Holtmann 
1825769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1826769be974SMarcel Holtmann 	if (conn) {
1827769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1828539c496dSJohan Hedberg 			hci_connect_cfm(conn, status);
182976a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1830769be974SMarcel Holtmann 		}
1831769be974SMarcel Holtmann 	}
1832769be974SMarcel Holtmann 
1833769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1834769be974SMarcel Holtmann }
1835769be974SMarcel Holtmann 
1836a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1837a9de9248SMarcel Holtmann {
1838b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1839b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1840b6a0dc82SMarcel Holtmann 	__u16 handle;
1841b6a0dc82SMarcel Holtmann 
18429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1843b6a0dc82SMarcel Holtmann 
1844b6a0dc82SMarcel Holtmann 	if (!status)
1845b6a0dc82SMarcel Holtmann 		return;
1846b6a0dc82SMarcel Holtmann 
1847b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1848b6a0dc82SMarcel Holtmann 	if (!cp)
1849b6a0dc82SMarcel Holtmann 		return;
1850b6a0dc82SMarcel Holtmann 
1851b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1852b6a0dc82SMarcel Holtmann 
18539f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1854b6a0dc82SMarcel Holtmann 
1855b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1856b6a0dc82SMarcel Holtmann 
1857b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
18585a08ecceSAndrei Emeltchenko 	if (acl) {
18595a08ecceSAndrei Emeltchenko 		sco = acl->link;
18605a08ecceSAndrei Emeltchenko 		if (sco) {
1861b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1862b6a0dc82SMarcel Holtmann 
1863539c496dSJohan Hedberg 			hci_connect_cfm(sco, status);
1864b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1865b6a0dc82SMarcel Holtmann 		}
18665a08ecceSAndrei Emeltchenko 	}
1867b6a0dc82SMarcel Holtmann 
1868b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1869a9de9248SMarcel Holtmann }
1870a9de9248SMarcel Holtmann 
1871a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1872a9de9248SMarcel Holtmann {
1873a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
187404837f64SMarcel Holtmann 	struct hci_conn *conn;
187504837f64SMarcel Holtmann 
18769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1877a9de9248SMarcel Holtmann 
1878a9de9248SMarcel Holtmann 	if (!status)
1879a9de9248SMarcel Holtmann 		return;
1880a9de9248SMarcel Holtmann 
1881a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
188204837f64SMarcel Holtmann 	if (!cp)
1883a9de9248SMarcel Holtmann 		return;
188404837f64SMarcel Holtmann 
188504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
188604837f64SMarcel Holtmann 
188704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1888e73439d8SMarcel Holtmann 	if (conn) {
188951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
189004837f64SMarcel Holtmann 
189151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1892e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1893e73439d8SMarcel Holtmann 	}
1894e73439d8SMarcel Holtmann 
189504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
189604837f64SMarcel Holtmann }
189704837f64SMarcel Holtmann 
1898a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1899a9de9248SMarcel Holtmann {
1900a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
190104837f64SMarcel Holtmann 	struct hci_conn *conn;
190204837f64SMarcel Holtmann 
19039f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1904a9de9248SMarcel Holtmann 
1905a9de9248SMarcel Holtmann 	if (!status)
1906a9de9248SMarcel Holtmann 		return;
1907a9de9248SMarcel Holtmann 
1908a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
190904837f64SMarcel Holtmann 	if (!cp)
1910a9de9248SMarcel Holtmann 		return;
191104837f64SMarcel Holtmann 
191204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
191304837f64SMarcel Holtmann 
191404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1915e73439d8SMarcel Holtmann 	if (conn) {
191651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
191704837f64SMarcel Holtmann 
191851a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1919e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1920e73439d8SMarcel Holtmann 	}
1921e73439d8SMarcel Holtmann 
192204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
192304837f64SMarcel Holtmann }
192404837f64SMarcel Holtmann 
192588c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
192688c3df13SJohan Hedberg {
192788c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
192888c3df13SJohan Hedberg 	struct hci_conn *conn;
192988c3df13SJohan Hedberg 
193088c3df13SJohan Hedberg 	if (!status)
193188c3df13SJohan Hedberg 		return;
193288c3df13SJohan Hedberg 
193388c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
193488c3df13SJohan Hedberg 	if (!cp)
193588c3df13SJohan Hedberg 		return;
193688c3df13SJohan Hedberg 
193788c3df13SJohan Hedberg 	hci_dev_lock(hdev);
193888c3df13SJohan Hedberg 
193988c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
194088c3df13SJohan Hedberg 	if (conn)
194188c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
194288c3df13SJohan Hedberg 				       conn->dst_type, status);
194388c3df13SJohan Hedberg 
194488c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
194588c3df13SJohan Hedberg }
194688c3df13SJohan Hedberg 
1947a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1948a02226d6SAndrei Emeltchenko {
194993c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
195093c284eeSAndrei Emeltchenko 
1951a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
195293c284eeSAndrei Emeltchenko 
195393c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
195493c284eeSAndrei Emeltchenko 	if (!cp)
195593c284eeSAndrei Emeltchenko 		return;
195693c284eeSAndrei Emeltchenko 
1957e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1958e58917b9SAndrei Emeltchenko 
1959e58917b9SAndrei Emeltchenko 	if (status) {
1960e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1961e58917b9SAndrei Emeltchenko 
1962e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1963e58917b9SAndrei Emeltchenko 		if (hcon)
1964e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1965e58917b9SAndrei Emeltchenko 	} else {
196693c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1967a02226d6SAndrei Emeltchenko 	}
1968a02226d6SAndrei Emeltchenko 
1969e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1970e58917b9SAndrei Emeltchenko }
1971e58917b9SAndrei Emeltchenko 
19720b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
19730b26ab9dSAndrei Emeltchenko {
19740b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
19750b26ab9dSAndrei Emeltchenko 
19760b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
19770b26ab9dSAndrei Emeltchenko 
19780b26ab9dSAndrei Emeltchenko 	if (status)
19790b26ab9dSAndrei Emeltchenko 		return;
19800b26ab9dSAndrei Emeltchenko 
19810b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
19820b26ab9dSAndrei Emeltchenko 	if (!cp)
19830b26ab9dSAndrei Emeltchenko 		return;
19840b26ab9dSAndrei Emeltchenko 
19850b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
19860b26ab9dSAndrei Emeltchenko }
19870b26ab9dSAndrei Emeltchenko 
1988cb1d68f7SJohan Hedberg static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
1989cb1d68f7SJohan Hedberg {
1990cb1d68f7SJohan Hedberg 	struct hci_cp_le_create_conn *cp;
1991cb1d68f7SJohan Hedberg 	struct hci_conn *conn;
1992cb1d68f7SJohan Hedberg 
1993cb1d68f7SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1994cb1d68f7SJohan Hedberg 
1995cb1d68f7SJohan Hedberg 	/* All connection failure handling is taken care of by the
1996cb1d68f7SJohan Hedberg 	 * hci_le_conn_failed function which is triggered by the HCI
1997cb1d68f7SJohan Hedberg 	 * request completion callbacks used for connecting.
1998cb1d68f7SJohan Hedberg 	 */
1999cb1d68f7SJohan Hedberg 	if (status)
2000cb1d68f7SJohan Hedberg 		return;
2001cb1d68f7SJohan Hedberg 
2002cb1d68f7SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
2003cb1d68f7SJohan Hedberg 	if (!cp)
2004cb1d68f7SJohan Hedberg 		return;
2005cb1d68f7SJohan Hedberg 
2006cb1d68f7SJohan Hedberg 	hci_dev_lock(hdev);
2007cb1d68f7SJohan Hedberg 
2008cb1d68f7SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
2009cb1d68f7SJohan Hedberg 	if (!conn)
2010cb1d68f7SJohan Hedberg 		goto unlock;
2011cb1d68f7SJohan Hedberg 
2012cb1d68f7SJohan Hedberg 	/* Store the initiator and responder address information which
2013cb1d68f7SJohan Hedberg 	 * is needed for SMP. These values will not change during the
2014cb1d68f7SJohan Hedberg 	 * lifetime of the connection.
2015cb1d68f7SJohan Hedberg 	 */
2016cb1d68f7SJohan Hedberg 	conn->init_addr_type = cp->own_address_type;
2017cb1d68f7SJohan Hedberg 	if (cp->own_address_type == ADDR_LE_DEV_RANDOM)
2018cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &hdev->random_addr);
2019cb1d68f7SJohan Hedberg 	else
2020cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &hdev->bdaddr);
2021cb1d68f7SJohan Hedberg 
2022cb1d68f7SJohan Hedberg 	conn->resp_addr_type = cp->peer_addr_type;
2023cb1d68f7SJohan Hedberg 	bacpy(&conn->resp_addr, &cp->peer_addr);
2024cb1d68f7SJohan Hedberg 
20259489eca4SJohan Hedberg 	/* We don't want the connection attempt to stick around
20269489eca4SJohan Hedberg 	 * indefinitely since LE doesn't have a page timeout concept
20279489eca4SJohan Hedberg 	 * like BR/EDR. Set a timer for any connection that doesn't use
20289489eca4SJohan Hedberg 	 * the white list for connecting.
20299489eca4SJohan Hedberg 	 */
20309489eca4SJohan Hedberg 	if (cp->filter_policy == HCI_LE_USE_PEER_ADDR)
20319489eca4SJohan Hedberg 		queue_delayed_work(conn->hdev->workqueue,
20329489eca4SJohan Hedberg 				   &conn->le_conn_timeout,
203309ae260bSJohan Hedberg 				   conn->conn_timeout);
20349489eca4SJohan Hedberg 
2035cb1d68f7SJohan Hedberg unlock:
2036cb1d68f7SJohan Hedberg 	hci_dev_unlock(hdev);
2037cb1d68f7SJohan Hedberg }
2038cb1d68f7SJohan Hedberg 
20390fe29fd1SMarcel Holtmann static void hci_cs_le_read_remote_features(struct hci_dev *hdev, u8 status)
20400fe29fd1SMarcel Holtmann {
20410fe29fd1SMarcel Holtmann 	struct hci_cp_le_read_remote_features *cp;
20420fe29fd1SMarcel Holtmann 	struct hci_conn *conn;
20430fe29fd1SMarcel Holtmann 
20440fe29fd1SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
20450fe29fd1SMarcel Holtmann 
20460fe29fd1SMarcel Holtmann 	if (!status)
20470fe29fd1SMarcel Holtmann 		return;
20480fe29fd1SMarcel Holtmann 
20490fe29fd1SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_READ_REMOTE_FEATURES);
20500fe29fd1SMarcel Holtmann 	if (!cp)
20510fe29fd1SMarcel Holtmann 		return;
20520fe29fd1SMarcel Holtmann 
20530fe29fd1SMarcel Holtmann 	hci_dev_lock(hdev);
20540fe29fd1SMarcel Holtmann 
20550fe29fd1SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
20560fe29fd1SMarcel Holtmann 	if (conn) {
20570fe29fd1SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
20580fe29fd1SMarcel Holtmann 			hci_connect_cfm(conn, status);
20590fe29fd1SMarcel Holtmann 			hci_conn_drop(conn);
20600fe29fd1SMarcel Holtmann 		}
20610fe29fd1SMarcel Holtmann 	}
20620fe29fd1SMarcel Holtmann 
20630fe29fd1SMarcel Holtmann 	hci_dev_unlock(hdev);
20640fe29fd1SMarcel Holtmann }
20650fe29fd1SMarcel Holtmann 
206681d0c8adSJohan Hedberg static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
206781d0c8adSJohan Hedberg {
206881d0c8adSJohan Hedberg 	struct hci_cp_le_start_enc *cp;
206981d0c8adSJohan Hedberg 	struct hci_conn *conn;
207081d0c8adSJohan Hedberg 
207181d0c8adSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
207281d0c8adSJohan Hedberg 
207381d0c8adSJohan Hedberg 	if (!status)
207481d0c8adSJohan Hedberg 		return;
207581d0c8adSJohan Hedberg 
207681d0c8adSJohan Hedberg 	hci_dev_lock(hdev);
207781d0c8adSJohan Hedberg 
207881d0c8adSJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC);
207981d0c8adSJohan Hedberg 	if (!cp)
208081d0c8adSJohan Hedberg 		goto unlock;
208181d0c8adSJohan Hedberg 
208281d0c8adSJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
208381d0c8adSJohan Hedberg 	if (!conn)
208481d0c8adSJohan Hedberg 		goto unlock;
208581d0c8adSJohan Hedberg 
208681d0c8adSJohan Hedberg 	if (conn->state != BT_CONNECTED)
208781d0c8adSJohan Hedberg 		goto unlock;
208881d0c8adSJohan Hedberg 
208981d0c8adSJohan Hedberg 	hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
209081d0c8adSJohan Hedberg 	hci_conn_drop(conn);
209181d0c8adSJohan Hedberg 
209281d0c8adSJohan Hedberg unlock:
209381d0c8adSJohan Hedberg 	hci_dev_unlock(hdev);
209481d0c8adSJohan Hedberg }
209581d0c8adSJohan Hedberg 
209650fc85f1SKuba Pawlak static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
209750fc85f1SKuba Pawlak {
209850fc85f1SKuba Pawlak 	struct hci_cp_switch_role *cp;
209950fc85f1SKuba Pawlak 	struct hci_conn *conn;
210050fc85f1SKuba Pawlak 
210150fc85f1SKuba Pawlak 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
210250fc85f1SKuba Pawlak 
210350fc85f1SKuba Pawlak 	if (!status)
210450fc85f1SKuba Pawlak 		return;
210550fc85f1SKuba Pawlak 
210650fc85f1SKuba Pawlak 	cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE);
210750fc85f1SKuba Pawlak 	if (!cp)
210850fc85f1SKuba Pawlak 		return;
210950fc85f1SKuba Pawlak 
211050fc85f1SKuba Pawlak 	hci_dev_lock(hdev);
211150fc85f1SKuba Pawlak 
211250fc85f1SKuba Pawlak 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
211350fc85f1SKuba Pawlak 	if (conn)
211450fc85f1SKuba Pawlak 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
211550fc85f1SKuba Pawlak 
211650fc85f1SKuba Pawlak 	hci_dev_unlock(hdev);
211750fc85f1SKuba Pawlak }
211850fc85f1SKuba Pawlak 
21196039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
21201da177e4SLinus Torvalds {
21211da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
212230dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
212330dc78e1SJohan Hedberg 	struct inquiry_entry *e;
21241da177e4SLinus Torvalds 
21259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
21261da177e4SLinus Torvalds 
2127a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
212889352e7dSAndre Guedes 
212989352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
213089352e7dSAndre Guedes 		return;
213189352e7dSAndre Guedes 
21324e857c58SPeter Zijlstra 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
21333e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
21343e13fa1eSAndre Guedes 
2135d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
213630dc78e1SJohan Hedberg 		return;
213730dc78e1SJohan Hedberg 
213856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
213930dc78e1SJohan Hedberg 
2140343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
214130dc78e1SJohan Hedberg 		goto unlock;
214230dc78e1SJohan Hedberg 
214330dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
214407d2334aSJakub Pawlowski 		/* When BR/EDR inquiry is active and no LE scanning is in
214507d2334aSJakub Pawlowski 		 * progress, then change discovery state to indicate completion.
214607d2334aSJakub Pawlowski 		 *
214707d2334aSJakub Pawlowski 		 * When running LE scanning and BR/EDR inquiry simultaneously
214807d2334aSJakub Pawlowski 		 * and the LE scan already finished, then change the discovery
214907d2334aSJakub Pawlowski 		 * state to indicate completion.
215007d2334aSJakub Pawlowski 		 */
215107d2334aSJakub Pawlowski 		if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
215207d2334aSJakub Pawlowski 		    !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
2153ff9ef578SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
215430dc78e1SJohan Hedberg 		goto unlock;
215530dc78e1SJohan Hedberg 	}
215630dc78e1SJohan Hedberg 
215730dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
215830dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
215930dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
216030dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
216130dc78e1SJohan Hedberg 	} else {
216207d2334aSJakub Pawlowski 		/* When BR/EDR inquiry is active and no LE scanning is in
216307d2334aSJakub Pawlowski 		 * progress, then change discovery state to indicate completion.
216407d2334aSJakub Pawlowski 		 *
216507d2334aSJakub Pawlowski 		 * When running LE scanning and BR/EDR inquiry simultaneously
216607d2334aSJakub Pawlowski 		 * and the LE scan already finished, then change the discovery
216707d2334aSJakub Pawlowski 		 * state to indicate completion.
216807d2334aSJakub Pawlowski 		 */
216907d2334aSJakub Pawlowski 		if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
217007d2334aSJakub Pawlowski 		    !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
217130dc78e1SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
217230dc78e1SJohan Hedberg 	}
217330dc78e1SJohan Hedberg 
217430dc78e1SJohan Hedberg unlock:
217556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
21761da177e4SLinus Torvalds }
21771da177e4SLinus Torvalds 
21786039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
21791da177e4SLinus Torvalds {
218045bb4bf0SMarcel Holtmann 	struct inquiry_data data;
2181a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
21821da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
21831da177e4SLinus Torvalds 
21841da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
21851da177e4SLinus Torvalds 
218645bb4bf0SMarcel Holtmann 	if (!num_rsp)
218745bb4bf0SMarcel Holtmann 		return;
218845bb4bf0SMarcel Holtmann 
2189d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
21901519cc17SAndre Guedes 		return;
21911519cc17SAndre Guedes 
21921da177e4SLinus Torvalds 	hci_dev_lock(hdev);
219345bb4bf0SMarcel Holtmann 
2194e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2195af58925cSMarcel Holtmann 		u32 flags;
21963175405bSJohan Hedberg 
21971da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
21981da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
21991da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
22001da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
22011da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
22021da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
2203efb2513fSMarcel Holtmann 		data.rssi		= HCI_RSSI_INVALID;
220441a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
22053175405bSJohan Hedberg 
2206af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, false);
2207af58925cSMarcel Holtmann 
220848264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2209efb2513fSMarcel Holtmann 				  info->dev_class, HCI_RSSI_INVALID,
2210efb2513fSMarcel Holtmann 				  flags, NULL, 0, NULL, 0);
22111da177e4SLinus Torvalds 	}
221245bb4bf0SMarcel Holtmann 
22131da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
22141da177e4SLinus Torvalds }
22151da177e4SLinus Torvalds 
22166039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
22171da177e4SLinus Torvalds {
2218a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
2219a9de9248SMarcel Holtmann 	struct hci_conn *conn;
22201da177e4SLinus Torvalds 
2221a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
222245bb4bf0SMarcel Holtmann 
22231da177e4SLinus Torvalds 	hci_dev_lock(hdev);
222445bb4bf0SMarcel Holtmann 
2225a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
22269499237aSMarcel Holtmann 	if (!conn) {
22279499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
22289499237aSMarcel Holtmann 			goto unlock;
22299499237aSMarcel Holtmann 
22309499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2231a9de9248SMarcel Holtmann 		if (!conn)
2232a9de9248SMarcel Holtmann 			goto unlock;
223345bb4bf0SMarcel Holtmann 
22349499237aSMarcel Holtmann 		conn->type = SCO_LINK;
22359499237aSMarcel Holtmann 	}
22369499237aSMarcel Holtmann 
2237a9de9248SMarcel Holtmann 	if (!ev->status) {
2238a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2239769be974SMarcel Holtmann 
2240769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2241769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
2242769be974SMarcel Holtmann 			hci_conn_hold(conn);
2243a9ea3ed9SSzymon Janc 
2244a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
2245a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
2246a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2247a9ea3ed9SSzymon Janc 			else
2248052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2249769be974SMarcel Holtmann 		} else
2250a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
2251a9de9248SMarcel Holtmann 
225223b9ceb7SMarcel Holtmann 		hci_debugfs_create_conn(conn);
22537d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
22547d0db0a3SMarcel Holtmann 
2255a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
22564dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2257a9de9248SMarcel Holtmann 
2258a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
22594dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2260a9de9248SMarcel Holtmann 
2261a9de9248SMarcel Holtmann 		/* Get remote features */
2262a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2263a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
2264a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2265769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
2266769be974SMarcel Holtmann 				     sizeof(cp), &cp);
226722f433dcSJohan Hedberg 
22681d2dc5b7SJohan Hedberg 			hci_update_page_scan(hdev);
226945bb4bf0SMarcel Holtmann 		}
2270a9de9248SMarcel Holtmann 
2271a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
2272d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
2273a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
2274a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2275a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
227604124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
227704124681SGustavo F. Padovan 				     &cp);
2278a9de9248SMarcel Holtmann 		}
227917d5c04cSJohan Hedberg 	} else {
2280a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
228117d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
228264c7b77cSMarcel Holtmann 			mgmt_connect_failed(hdev, &conn->dst, conn->type,
228348264f06SJohan Hedberg 					    conn->dst_type, ev->status);
228417d5c04cSJohan Hedberg 	}
228545bb4bf0SMarcel Holtmann 
2286e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
2287e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
228845bb4bf0SMarcel Holtmann 
2289769be974SMarcel Holtmann 	if (ev->status) {
2290539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
2291a9de9248SMarcel Holtmann 		hci_conn_del(conn);
2292c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
2293539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
2294a9de9248SMarcel Holtmann 
2295a9de9248SMarcel Holtmann unlock:
22961da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
2297a9de9248SMarcel Holtmann 
2298a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
22991da177e4SLinus Torvalds }
23001da177e4SLinus Torvalds 
230170c46425SJohan Hedberg static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr)
230270c46425SJohan Hedberg {
230370c46425SJohan Hedberg 	struct hci_cp_reject_conn_req cp;
230470c46425SJohan Hedberg 
230570c46425SJohan Hedberg 	bacpy(&cp.bdaddr, bdaddr);
230670c46425SJohan Hedberg 	cp.reason = HCI_ERROR_REJ_BAD_ADDR;
230770c46425SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
230870c46425SJohan Hedberg }
230970c46425SJohan Hedberg 
23106039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
23111da177e4SLinus Torvalds {
2312a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
23131da177e4SLinus Torvalds 	int mask = hdev->link_mode;
231470c46425SJohan Hedberg 	struct inquiry_entry *ie;
231570c46425SJohan Hedberg 	struct hci_conn *conn;
231620714bfeSFrédéric Dalleau 	__u8 flags = 0;
23171da177e4SLinus Torvalds 
23186ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
2319807deac2SGustavo Padovan 	       ev->link_type);
23201da177e4SLinus Torvalds 
232120714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
232220714bfeSFrédéric Dalleau 				      &flags);
23231da177e4SLinus Torvalds 
232470c46425SJohan Hedberg 	if (!(mask & HCI_LM_ACCEPT)) {
232570c46425SJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
232670c46425SJohan Hedberg 		return;
232770c46425SJohan Hedberg 	}
232870c46425SJohan Hedberg 
2329a55bd29dSJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr,
2330dcc36c16SJohan Hedberg 				   BDADDR_BREDR)) {
233170c46425SJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
233270c46425SJohan Hedberg 		return;
233370c46425SJohan Hedberg 	}
233446c4c941SJohan Hedberg 
23356a8fc95cSJohan Hedberg 	/* Require HCI_CONNECTABLE or a whitelist entry to accept the
23366a8fc95cSJohan Hedberg 	 * connection. These features are only touched through mgmt so
23376a8fc95cSJohan Hedberg 	 * only do the checks if HCI_MGMT is set.
23386a8fc95cSJohan Hedberg 	 */
2339d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT) &&
2340d7a5a11dSMarcel Holtmann 	    !hci_dev_test_flag(hdev, HCI_CONNECTABLE) &&
234146c4c941SJohan Hedberg 	    !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr,
2342a55bd29dSJohan Hedberg 				    BDADDR_BREDR)) {
2343a55bd29dSJohan Hedberg 		    hci_reject_conn(hdev, &ev->bdaddr);
2344a55bd29dSJohan Hedberg 		    return;
2345a55bd29dSJohan Hedberg 	}
234670c46425SJohan Hedberg 
23471da177e4SLinus Torvalds 	/* Connection accepted */
23481da177e4SLinus Torvalds 
23491da177e4SLinus Torvalds 	hci_dev_lock(hdev);
2350b6a0dc82SMarcel Holtmann 
2351cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2352cc11b9c1SAndrei Emeltchenko 	if (ie)
2353c7bdd502SMarcel Holtmann 		memcpy(ie->data.dev_class, ev->dev_class, 3);
2354c7bdd502SMarcel Holtmann 
23558fc9ced3SGustavo Padovan 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
23568fc9ced3SGustavo Padovan 			&ev->bdaddr);
23571da177e4SLinus Torvalds 	if (!conn) {
2358a5c4e309SJohan Hedberg 		conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
2359a5c4e309SJohan Hedberg 				    HCI_ROLE_SLAVE);
2360cc11b9c1SAndrei Emeltchenko 		if (!conn) {
2361893ef971SGustavo F. Padovan 			BT_ERR("No memory for new connection");
23621da177e4SLinus Torvalds 			hci_dev_unlock(hdev);
23631da177e4SLinus Torvalds 			return;
23641da177e4SLinus Torvalds 		}
23651da177e4SLinus Torvalds 	}
2366b6a0dc82SMarcel Holtmann 
23671da177e4SLinus Torvalds 	memcpy(conn->dev_class, ev->dev_class, 3);
2368b6a0dc82SMarcel Holtmann 
23691da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
23701da177e4SLinus Torvalds 
237120714bfeSFrédéric Dalleau 	if (ev->link_type == ACL_LINK ||
237220714bfeSFrédéric Dalleau 	    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
2373b6a0dc82SMarcel Holtmann 		struct hci_cp_accept_conn_req cp;
237420714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT;
2375b6a0dc82SMarcel Holtmann 
23761da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
23771da177e4SLinus Torvalds 
23781da177e4SLinus Torvalds 		if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
23791da177e4SLinus Torvalds 			cp.role = 0x00; /* Become master */
23801da177e4SLinus Torvalds 		else
23811da177e4SLinus Torvalds 			cp.role = 0x01; /* Remain slave */
23821da177e4SLinus Torvalds 
238370c46425SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
238420714bfeSFrédéric Dalleau 	} else if (!(flags & HCI_PROTO_DEFER)) {
2385b6a0dc82SMarcel Holtmann 		struct hci_cp_accept_sync_conn_req cp;
238620714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT;
2387b6a0dc82SMarcel Holtmann 
2388b6a0dc82SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
2389a8746417SMarcel Holtmann 		cp.pkt_type = cpu_to_le16(conn->pkt_type);
2390b6a0dc82SMarcel Holtmann 
2391dcf4adbfSJoe Perches 		cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
2392dcf4adbfSJoe Perches 		cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
2393dcf4adbfSJoe Perches 		cp.max_latency    = cpu_to_le16(0xffff);
2394b6a0dc82SMarcel Holtmann 		cp.content_format = cpu_to_le16(hdev->voice_setting);
2395b6a0dc82SMarcel Holtmann 		cp.retrans_effort = 0xff;
2396b6a0dc82SMarcel Holtmann 
239770c46425SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(cp),
239870c46425SJohan Hedberg 			     &cp);
239920714bfeSFrédéric Dalleau 	} else {
240020714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT2;
2401539c496dSJohan Hedberg 		hci_connect_cfm(conn, 0);
2402b6a0dc82SMarcel Holtmann 	}
24031da177e4SLinus Torvalds }
24041da177e4SLinus Torvalds 
2405f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2406f0d6a0eaSMikel Astiz {
2407f0d6a0eaSMikel Astiz 	switch (err) {
2408f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2409f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2410f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2411f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2412f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2413f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2414f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2415f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2416f0d6a0eaSMikel Astiz 	default:
2417f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2418f0d6a0eaSMikel Astiz 	}
2419f0d6a0eaSMikel Astiz }
2420f0d6a0eaSMikel Astiz 
24216039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
24221da177e4SLinus Torvalds {
2423a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
2424abf54a50SAndre Guedes 	u8 reason = hci_to_mgmt_reason(ev->reason);
24259fcb18efSAndre Guedes 	struct hci_conn_params *params;
242604837f64SMarcel Holtmann 	struct hci_conn *conn;
242712d4a3b2SJohan Hedberg 	bool mgmt_connected;
24283846220bSAndre Guedes 	u8 type;
24291da177e4SLinus Torvalds 
24309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
24311da177e4SLinus Torvalds 
24321da177e4SLinus Torvalds 	hci_dev_lock(hdev);
24331da177e4SLinus Torvalds 
243404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2435f7520543SJohan Hedberg 	if (!conn)
2436f7520543SJohan Hedberg 		goto unlock;
2437f7520543SJohan Hedberg 
2438f0d6a0eaSMikel Astiz 	if (ev->status) {
243988c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
244088c3df13SJohan Hedberg 				       conn->dst_type, ev->status);
2441abf54a50SAndre Guedes 		goto unlock;
2442abf54a50SAndre Guedes 	}
2443f0d6a0eaSMikel Astiz 
24443846220bSAndre Guedes 	conn->state = BT_CLOSED;
24453846220bSAndre Guedes 
244612d4a3b2SJohan Hedberg 	mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
244712d4a3b2SJohan Hedberg 	mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
244812d4a3b2SJohan Hedberg 				reason, mgmt_connected);
2449f7520543SJohan Hedberg 
245022f433dcSJohan Hedberg 	if (conn->type == ACL_LINK) {
245122f433dcSJohan Hedberg 		if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
24526ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
24533846220bSAndre Guedes 
24541d2dc5b7SJohan Hedberg 		hci_update_page_scan(hdev);
245522f433dcSJohan Hedberg 	}
245622f433dcSJohan Hedberg 
24579fcb18efSAndre Guedes 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
24589fcb18efSAndre Guedes 	if (params) {
24599fcb18efSAndre Guedes 		switch (params->auto_connect) {
24609fcb18efSAndre Guedes 		case HCI_AUTO_CONN_LINK_LOSS:
24619fcb18efSAndre Guedes 			if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
24629fcb18efSAndre Guedes 				break;
24639fcb18efSAndre Guedes 			/* Fall through */
24649fcb18efSAndre Guedes 
24654b9e7e75SMarcel Holtmann 		case HCI_AUTO_CONN_DIRECT:
24669fcb18efSAndre Guedes 		case HCI_AUTO_CONN_ALWAYS:
2467418025d1SJohan Hedberg 			list_del_init(&params->action);
2468418025d1SJohan Hedberg 			list_add(&params->action, &hdev->pend_le_conns);
2469418025d1SJohan Hedberg 			hci_update_background_scan(hdev);
24709fcb18efSAndre Guedes 			break;
24719fcb18efSAndre Guedes 
24729fcb18efSAndre Guedes 		default:
24739fcb18efSAndre Guedes 			break;
24749fcb18efSAndre Guedes 		}
24759fcb18efSAndre Guedes 	}
24769fcb18efSAndre Guedes 
24773846220bSAndre Guedes 	type = conn->type;
24783846220bSAndre Guedes 
24793a6d576bSJohan Hedberg 	hci_disconn_cfm(conn, ev->reason);
24801da177e4SLinus Torvalds 	hci_conn_del(conn);
24812210246cSJohan Hedberg 
24822210246cSJohan Hedberg 	/* Re-enable advertising if necessary, since it might
24832210246cSJohan Hedberg 	 * have been disabled by the connection. From the
24842210246cSJohan Hedberg 	 * HCI_LE_Set_Advertise_Enable command description in
24852210246cSJohan Hedberg 	 * the core specification (v4.0):
24862210246cSJohan Hedberg 	 * "The Controller shall continue advertising until the Host
24872210246cSJohan Hedberg 	 * issues an LE_Set_Advertise_Enable command with
24882210246cSJohan Hedberg 	 * Advertising_Enable set to 0x00 (Advertising is disabled)
24892210246cSJohan Hedberg 	 * or until a connection is created or until the Advertising
24902210246cSJohan Hedberg 	 * is timed out due to Directed Advertising."
24912210246cSJohan Hedberg 	 */
24922210246cSJohan Hedberg 	if (type == LE_LINK)
24935976e608SMarcel Holtmann 		mgmt_reenable_advertising(hdev);
24941da177e4SLinus Torvalds 
2495f7520543SJohan Hedberg unlock:
24961da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
24971da177e4SLinus Torvalds }
24981da177e4SLinus Torvalds 
24996039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2500a9de9248SMarcel Holtmann {
2501a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2502a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2503a9de9248SMarcel Holtmann 
25049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2505a9de9248SMarcel Holtmann 
2506a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2507a9de9248SMarcel Holtmann 
2508a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2509d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2510d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2511d7556e20SWaldemar Rymarkiewicz 
2512765c2a96SJohan Hedberg 	if (!ev->status) {
2513aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
251451a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2515d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
251619f8def0SWaldemar Rymarkiewicz 		} else {
25174dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2518765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
251919f8def0SWaldemar Rymarkiewicz 		}
25202a611692SJohan Hedberg 	} else {
2521e1e930f5SJohan Hedberg 		mgmt_auth_failed(conn, ev->status);
25222a611692SJohan Hedberg 	}
2523a9de9248SMarcel Holtmann 
252451a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
252551a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2526a9de9248SMarcel Holtmann 
2527f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2528aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2529f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2530f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2531f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2532d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2533d7556e20SWaldemar Rymarkiewicz 				     &cp);
2534f8558555SMarcel Holtmann 		} else {
2535f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2536539c496dSJohan Hedberg 			hci_connect_cfm(conn, ev->status);
253776a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2538f8558555SMarcel Holtmann 		}
2539052b30b0SMarcel Holtmann 	} else {
2540a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2541a9de9248SMarcel Holtmann 
2542052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2543052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
254476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2545052b30b0SMarcel Holtmann 	}
2546052b30b0SMarcel Holtmann 
254751a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2548a9de9248SMarcel Holtmann 		if (!ev->status) {
2549a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2550f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2551f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2552d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2553d7556e20SWaldemar Rymarkiewicz 				     &cp);
2554a9de9248SMarcel Holtmann 		} else {
255551a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2556a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2557a9de9248SMarcel Holtmann 		}
2558a9de9248SMarcel Holtmann 	}
2559a9de9248SMarcel Holtmann 
2560d7556e20SWaldemar Rymarkiewicz unlock:
2561a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2562a9de9248SMarcel Holtmann }
2563a9de9248SMarcel Holtmann 
25646039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2565a9de9248SMarcel Holtmann {
2566127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2567127178d2SJohan Hedberg 	struct hci_conn *conn;
2568127178d2SJohan Hedberg 
2569a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2570a9de9248SMarcel Holtmann 
2571a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2572127178d2SJohan Hedberg 
2573127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2574127178d2SJohan Hedberg 
2575127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2576b644ba33SJohan Hedberg 
2577d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
2578b644ba33SJohan Hedberg 		goto check_auth;
2579b644ba33SJohan Hedberg 
2580b644ba33SJohan Hedberg 	if (ev->status == 0)
2581b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2582b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2583b644ba33SJohan Hedberg 	else
2584b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2585b644ba33SJohan Hedberg 
2586b644ba33SJohan Hedberg check_auth:
258779c6c70cSJohan Hedberg 	if (!conn)
258879c6c70cSJohan Hedberg 		goto unlock;
258979c6c70cSJohan Hedberg 
259079c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
259179c6c70cSJohan Hedberg 		goto unlock;
259279c6c70cSJohan Hedberg 
259351a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2594127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2595977f8fceSJohan Hedberg 
2596977f8fceSJohan Hedberg 		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
2597977f8fceSJohan Hedberg 
2598127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2599127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2600127178d2SJohan Hedberg 	}
2601127178d2SJohan Hedberg 
260279c6c70cSJohan Hedberg unlock:
2603127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2604a9de9248SMarcel Holtmann }
2605a9de9248SMarcel Holtmann 
2606821f3766SJohan Hedberg static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status,
2607821f3766SJohan Hedberg 				       u16 opcode, struct sk_buff *skb)
2608821f3766SJohan Hedberg {
2609821f3766SJohan Hedberg 	const struct hci_rp_read_enc_key_size *rp;
2610821f3766SJohan Hedberg 	struct hci_conn *conn;
2611821f3766SJohan Hedberg 	u16 handle;
2612821f3766SJohan Hedberg 
2613821f3766SJohan Hedberg 	BT_DBG("%s status 0x%02x", hdev->name, status);
2614821f3766SJohan Hedberg 
2615821f3766SJohan Hedberg 	if (!skb || skb->len < sizeof(*rp)) {
2616821f3766SJohan Hedberg 		BT_ERR("%s invalid HCI Read Encryption Key Size response",
2617821f3766SJohan Hedberg 		       hdev->name);
2618821f3766SJohan Hedberg 		return;
2619821f3766SJohan Hedberg 	}
2620821f3766SJohan Hedberg 
2621821f3766SJohan Hedberg 	rp = (void *)skb->data;
2622821f3766SJohan Hedberg 	handle = le16_to_cpu(rp->handle);
2623821f3766SJohan Hedberg 
2624821f3766SJohan Hedberg 	hci_dev_lock(hdev);
2625821f3766SJohan Hedberg 
2626821f3766SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, handle);
2627821f3766SJohan Hedberg 	if (!conn)
2628821f3766SJohan Hedberg 		goto unlock;
2629821f3766SJohan Hedberg 
2630821f3766SJohan Hedberg 	/* If we fail to read the encryption key size, assume maximum
2631821f3766SJohan Hedberg 	 * (which is the same we do also when this HCI command isn't
2632821f3766SJohan Hedberg 	 * supported.
2633821f3766SJohan Hedberg 	 */
2634821f3766SJohan Hedberg 	if (rp->status) {
2635821f3766SJohan Hedberg 		BT_ERR("%s failed to read key size for handle %u", hdev->name,
2636821f3766SJohan Hedberg 		       handle);
2637821f3766SJohan Hedberg 		conn->enc_key_size = HCI_LINK_KEY_SIZE;
2638821f3766SJohan Hedberg 	} else {
2639821f3766SJohan Hedberg 		conn->enc_key_size = rp->key_size;
2640821f3766SJohan Hedberg 	}
2641821f3766SJohan Hedberg 
2642821f3766SJohan Hedberg 	if (conn->state == BT_CONFIG) {
2643821f3766SJohan Hedberg 		conn->state = BT_CONNECTED;
2644821f3766SJohan Hedberg 		hci_connect_cfm(conn, 0);
2645821f3766SJohan Hedberg 		hci_conn_drop(conn);
2646821f3766SJohan Hedberg 	} else {
2647821f3766SJohan Hedberg 		u8 encrypt;
2648821f3766SJohan Hedberg 
2649821f3766SJohan Hedberg 		if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
2650821f3766SJohan Hedberg 			encrypt = 0x00;
26515d667ef6SJohan Hedberg 		else if (test_bit(HCI_CONN_AES_CCM, &conn->flags))
2652821f3766SJohan Hedberg 			encrypt = 0x02;
2653821f3766SJohan Hedberg 		else
2654821f3766SJohan Hedberg 			encrypt = 0x01;
2655821f3766SJohan Hedberg 
2656821f3766SJohan Hedberg 		hci_encrypt_cfm(conn, 0, encrypt);
2657821f3766SJohan Hedberg 	}
2658821f3766SJohan Hedberg 
2659821f3766SJohan Hedberg unlock:
2660821f3766SJohan Hedberg 	hci_dev_unlock(hdev);
2661821f3766SJohan Hedberg }
2662821f3766SJohan Hedberg 
26636039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2664a9de9248SMarcel Holtmann {
2665a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2666a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2667a9de9248SMarcel Holtmann 
26689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2669a9de9248SMarcel Holtmann 
2670a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2671a9de9248SMarcel Holtmann 
2672a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2673dc8357ccSMarcel Holtmann 	if (!conn)
2674dc8357ccSMarcel Holtmann 		goto unlock;
2675dc8357ccSMarcel Holtmann 
2676a9de9248SMarcel Holtmann 	if (!ev->status) {
2677ae293196SMarcel Holtmann 		if (ev->encrypt) {
2678ae293196SMarcel Holtmann 			/* Encryption implies authentication */
26794dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
26804dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2681da85e5e5SVinicius Costa Gomes 			conn->sec_level = conn->pending_sec_level;
2682abf76badSMarcel Holtmann 
2683914a6ffeSMarcel Holtmann 			/* P-256 authentication key implies FIPS */
2684914a6ffeSMarcel Holtmann 			if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
26854dae2798SJohan Hedberg 				set_bit(HCI_CONN_FIPS, &conn->flags);
2686914a6ffeSMarcel Holtmann 
2687abf76badSMarcel Holtmann 			if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
2688abf76badSMarcel Holtmann 			    conn->type == LE_LINK)
2689abf76badSMarcel Holtmann 				set_bit(HCI_CONN_AES_CCM, &conn->flags);
2690abf76badSMarcel Holtmann 		} else {
26914dae2798SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
2692abf76badSMarcel Holtmann 			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
2693abf76badSMarcel Holtmann 		}
2694a9de9248SMarcel Holtmann 	}
2695a9de9248SMarcel Holtmann 
26967ed3fa20SJohan Hedberg 	/* We should disregard the current RPA and generate a new one
26977ed3fa20SJohan Hedberg 	 * whenever the encryption procedure fails.
26987ed3fa20SJohan Hedberg 	 */
26997ed3fa20SJohan Hedberg 	if (ev->status && conn->type == LE_LINK)
2700a1536da2SMarcel Holtmann 		hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
27017ed3fa20SJohan Hedberg 
270251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2703a9de9248SMarcel Holtmann 
2704a7d7723aSGustavo Padovan 	if (ev->status && conn->state == BT_CONNECTED) {
2705bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
270676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2707a7d7723aSGustavo Padovan 		goto unlock;
2708a7d7723aSGustavo Padovan 	}
2709a7d7723aSGustavo Padovan 
2710035ad621SJohan Hedberg 	/* In Secure Connections Only mode, do not allow any connections
2711035ad621SJohan Hedberg 	 * that are not encrypted with AES-CCM using a P-256 authenticated
2712035ad621SJohan Hedberg 	 * combination key.
271340b552aaSMarcel Holtmann 	 */
2714d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_SC_ONLY) &&
271540b552aaSMarcel Holtmann 	    (!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
271640b552aaSMarcel Holtmann 	     conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) {
2717539c496dSJohan Hedberg 		hci_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE);
271840b552aaSMarcel Holtmann 		hci_conn_drop(conn);
271940b552aaSMarcel Holtmann 		goto unlock;
272040b552aaSMarcel Holtmann 	}
272140b552aaSMarcel Holtmann 
2722821f3766SJohan Hedberg 	/* Try reading the encryption key size for encrypted ACL links */
2723821f3766SJohan Hedberg 	if (!ev->status && ev->encrypt && conn->type == ACL_LINK) {
2724821f3766SJohan Hedberg 		struct hci_cp_read_enc_key_size cp;
2725821f3766SJohan Hedberg 		struct hci_request req;
2726821f3766SJohan Hedberg 
2727821f3766SJohan Hedberg 		/* Only send HCI_Read_Encryption_Key_Size if the
2728821f3766SJohan Hedberg 		 * controller really supports it. If it doesn't, assume
2729821f3766SJohan Hedberg 		 * the default size (16).
2730821f3766SJohan Hedberg 		 */
2731821f3766SJohan Hedberg 		if (!(hdev->commands[20] & 0x10)) {
2732821f3766SJohan Hedberg 			conn->enc_key_size = HCI_LINK_KEY_SIZE;
2733821f3766SJohan Hedberg 			goto notify;
2734821f3766SJohan Hedberg 		}
2735821f3766SJohan Hedberg 
2736821f3766SJohan Hedberg 		hci_req_init(&req, hdev);
2737821f3766SJohan Hedberg 
2738821f3766SJohan Hedberg 		cp.handle = cpu_to_le16(conn->handle);
2739821f3766SJohan Hedberg 		hci_req_add(&req, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp);
2740821f3766SJohan Hedberg 
2741821f3766SJohan Hedberg 		if (hci_req_run_skb(&req, read_enc_key_size_complete)) {
2742821f3766SJohan Hedberg 			BT_ERR("Sending HCI Read Encryption Key Size failed");
2743821f3766SJohan Hedberg 			conn->enc_key_size = HCI_LINK_KEY_SIZE;
2744821f3766SJohan Hedberg 			goto notify;
2745821f3766SJohan Hedberg 		}
2746821f3766SJohan Hedberg 
2747821f3766SJohan Hedberg 		goto unlock;
2748821f3766SJohan Hedberg 	}
2749821f3766SJohan Hedberg 
2750821f3766SJohan Hedberg notify:
2751035ad621SJohan Hedberg 	if (conn->state == BT_CONFIG) {
2752035ad621SJohan Hedberg 		if (!ev->status)
2753035ad621SJohan Hedberg 			conn->state = BT_CONNECTED;
2754035ad621SJohan Hedberg 
2755539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
275676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2757f8558555SMarcel Holtmann 	} else
2758a9de9248SMarcel Holtmann 		hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2759a9de9248SMarcel Holtmann 
2760a7d7723aSGustavo Padovan unlock:
2761a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2762a9de9248SMarcel Holtmann }
2763a9de9248SMarcel Holtmann 
27646039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2765807deac2SGustavo Padovan 					     struct sk_buff *skb)
2766a9de9248SMarcel Holtmann {
2767a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2768a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2769a9de9248SMarcel Holtmann 
27709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2771a9de9248SMarcel Holtmann 
2772a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2773a9de9248SMarcel Holtmann 
2774a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2775a9de9248SMarcel Holtmann 	if (conn) {
2776a9de9248SMarcel Holtmann 		if (!ev->status)
27774dae2798SJohan Hedberg 			set_bit(HCI_CONN_SECURE, &conn->flags);
2778a9de9248SMarcel Holtmann 
277951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2780a9de9248SMarcel Holtmann 
2781a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2782a9de9248SMarcel Holtmann 	}
2783a9de9248SMarcel Holtmann 
2784a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2785a9de9248SMarcel Holtmann }
2786a9de9248SMarcel Holtmann 
27876039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2788807deac2SGustavo Padovan 				    struct sk_buff *skb)
2789a9de9248SMarcel Holtmann {
2790a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2791a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2792a9de9248SMarcel Holtmann 
27939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2794a9de9248SMarcel Holtmann 
2795a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2796a9de9248SMarcel Holtmann 
2797a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2798ccd556feSJohan Hedberg 	if (!conn)
2799ccd556feSJohan Hedberg 		goto unlock;
2800ccd556feSJohan Hedberg 
2801769be974SMarcel Holtmann 	if (!ev->status)
2802cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
2803a9de9248SMarcel Holtmann 
2804ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2805ccd556feSJohan Hedberg 		goto unlock;
2806ccd556feSJohan Hedberg 
2807ac363cf9SSzymon Janc 	if (!ev->status && lmp_ext_feat_capable(hdev) &&
2808ac363cf9SSzymon Janc 	    lmp_ext_feat_capable(conn)) {
2809769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2810769be974SMarcel Holtmann 		cp.handle = ev->handle;
2811769be974SMarcel Holtmann 		cp.page = 0x01;
2812ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2813769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2814392599b9SJohan Hedberg 		goto unlock;
2815392599b9SJohan Hedberg 	}
2816392599b9SJohan Hedberg 
2817671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2818127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2819127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2820127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2821127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2822127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2823b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
282448ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
2825392599b9SJohan Hedberg 
2826127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2827769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2828539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
282976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2830769be974SMarcel Holtmann 	}
2831769be974SMarcel Holtmann 
2832ccd556feSJohan Hedberg unlock:
2833a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2834a9de9248SMarcel Holtmann }
2835a9de9248SMarcel Holtmann 
2836e6214487SJohan Hedberg static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
2837e6214487SJohan Hedberg 				 u16 *opcode, u8 *status,
2838e6214487SJohan Hedberg 				 hci_req_complete_t *req_complete,
2839e6214487SJohan Hedberg 				 hci_req_complete_skb_t *req_complete_skb)
2840a9de9248SMarcel Holtmann {
2841a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2842e6214487SJohan Hedberg 
2843e6214487SJohan Hedberg 	*opcode = __le16_to_cpu(ev->opcode);
2844e6214487SJohan Hedberg 	*status = skb->data[sizeof(*ev)];
2845a9de9248SMarcel Holtmann 
2846a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2847a9de9248SMarcel Holtmann 
2848e6214487SJohan Hedberg 	switch (*opcode) {
2849a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2850a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2851a9de9248SMarcel Holtmann 		break;
2852a9de9248SMarcel Holtmann 
28534d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
28544d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
28554d93483bSAndre Guedes 		break;
28564d93483bSAndre Guedes 
2857a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2858a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2859a9de9248SMarcel Holtmann 		break;
2860a9de9248SMarcel Holtmann 
2861a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2862a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2863a9de9248SMarcel Holtmann 		break;
2864a9de9248SMarcel Holtmann 
2865a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2866a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2867a9de9248SMarcel Holtmann 		break;
2868a9de9248SMarcel Holtmann 
2869e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2870e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2871e4e8e37cSMarcel Holtmann 		break;
2872e4e8e37cSMarcel Holtmann 
2873a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2874a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2875a9de9248SMarcel Holtmann 		break;
2876a9de9248SMarcel Holtmann 
2877e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2878e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2879e4e8e37cSMarcel Holtmann 		break;
2880e4e8e37cSMarcel Holtmann 
2881e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2882e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2883e4e8e37cSMarcel Holtmann 		break;
2884e4e8e37cSMarcel Holtmann 
2885a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2886a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2887a9de9248SMarcel Holtmann 		break;
2888a9de9248SMarcel Holtmann 
2889c2f0f979SMarcel Holtmann 	case HCI_OP_READ_STORED_LINK_KEY:
2890c2f0f979SMarcel Holtmann 		hci_cc_read_stored_link_key(hdev, skb);
2891c2f0f979SMarcel Holtmann 		break;
2892c2f0f979SMarcel Holtmann 
2893a9366120SMarcel Holtmann 	case HCI_OP_DELETE_STORED_LINK_KEY:
2894a9366120SMarcel Holtmann 		hci_cc_delete_stored_link_key(hdev, skb);
2895a9366120SMarcel Holtmann 		break;
2896a9366120SMarcel Holtmann 
2897a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2898a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2899a9de9248SMarcel Holtmann 		break;
2900a9de9248SMarcel Holtmann 
2901a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2902a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2903a9de9248SMarcel Holtmann 		break;
2904a9de9248SMarcel Holtmann 
2905a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2906a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2907a9de9248SMarcel Holtmann 		break;
2908a9de9248SMarcel Holtmann 
2909a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2910a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2911a9de9248SMarcel Holtmann 		break;
2912a9de9248SMarcel Holtmann 
2913a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2914a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2915a9de9248SMarcel Holtmann 		break;
2916a9de9248SMarcel Holtmann 
2917a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2918a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2919a9de9248SMarcel Holtmann 		break;
2920a9de9248SMarcel Holtmann 
2921a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2922a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2923a9de9248SMarcel Holtmann 		break;
2924a9de9248SMarcel Holtmann 
2925a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2926a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2927a9de9248SMarcel Holtmann 		break;
2928a9de9248SMarcel Holtmann 
2929a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2930a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2931a9de9248SMarcel Holtmann 		break;
2932a9de9248SMarcel Holtmann 
2933b4cb9fb2SMarcel Holtmann 	case HCI_OP_READ_NUM_SUPPORTED_IAC:
2934b4cb9fb2SMarcel Holtmann 		hci_cc_read_num_supported_iac(hdev, skb);
2935b4cb9fb2SMarcel Holtmann 		break;
2936b4cb9fb2SMarcel Holtmann 
2937333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2938333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2939333140b5SMarcel Holtmann 		break;
2940333140b5SMarcel Holtmann 
2941eac83dc6SMarcel Holtmann 	case HCI_OP_WRITE_SC_SUPPORT:
2942eac83dc6SMarcel Holtmann 		hci_cc_write_sc_support(hdev, skb);
2943eac83dc6SMarcel Holtmann 		break;
2944eac83dc6SMarcel Holtmann 
2945a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2946a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2947a9de9248SMarcel Holtmann 		break;
2948a9de9248SMarcel Holtmann 
2949a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2950a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2951a9de9248SMarcel Holtmann 		break;
2952a9de9248SMarcel Holtmann 
2953a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2954a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2955a9de9248SMarcel Holtmann 		break;
2956a9de9248SMarcel Holtmann 
2957971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2958971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2959971e3a4bSAndre Guedes 		break;
2960971e3a4bSAndre Guedes 
2961a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2962a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2963a9de9248SMarcel Holtmann 		break;
2964a9de9248SMarcel Holtmann 
2965a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2966a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2967a9de9248SMarcel Holtmann 		break;
2968a9de9248SMarcel Holtmann 
2969f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2970f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
2971f332ec66SJohan Hedberg 		break;
2972f332ec66SJohan Hedberg 
29734a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
29744a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
29754a3ee763SJohan Hedberg 		break;
29764a3ee763SJohan Hedberg 
2977f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
2978f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
2979f332ec66SJohan Hedberg 		break;
2980f332ec66SJohan Hedberg 
29814a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
29824a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
29834a3ee763SJohan Hedberg 		break;
29844a3ee763SJohan Hedberg 
2985350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2986350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2987350ee4cfSAndrei Emeltchenko 		break;
2988350ee4cfSAndrei Emeltchenko 
29891e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
29901e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
29911e89cffbSAndrei Emeltchenko 		break;
29921e89cffbSAndrei Emeltchenko 
2993928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2994928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2995928abaa7SAndrei Emeltchenko 		break;
2996928abaa7SAndrei Emeltchenko 
299733f35721SJohan Hedberg 	case HCI_OP_READ_CLOCK:
299833f35721SJohan Hedberg 		hci_cc_read_clock(hdev, skb);
299933f35721SJohan Hedberg 		break;
300033f35721SJohan Hedberg 
3001903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
3002903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
3003903e4541SAndrei Emeltchenko 		break;
3004903e4541SAndrei Emeltchenko 
3005d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
3006d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
3007d5859e22SJohan Hedberg 		break;
3008d5859e22SJohan Hedberg 
3009980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
3010980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
3011980e1a53SJohan Hedberg 		break;
3012980e1a53SJohan Hedberg 
3013980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
3014980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
3015980e1a53SJohan Hedberg 		break;
3016980e1a53SJohan Hedberg 
3017c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
30184d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_data(hdev, skb);
30194d2d2796SMarcel Holtmann 		break;
30204d2d2796SMarcel Holtmann 
30214d2d2796SMarcel Holtmann 	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
30224d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_ext_data(hdev, skb);
3023c35938b2SSzymon Janc 		break;
3024c35938b2SSzymon Janc 
30256ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
30266ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
30276ed58ec5SVille Tervo 		break;
30286ed58ec5SVille Tervo 
302960e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
303060e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
303160e77321SJohan Hedberg 		break;
303260e77321SJohan Hedberg 
30338fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
30348fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
30358fa19098SJohan Hedberg 		break;
30368fa19098SJohan Hedberg 
3037a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
3038a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
3039a5c29683SJohan Hedberg 		break;
3040a5c29683SJohan Hedberg 
3041a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
3042a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
3043a5c29683SJohan Hedberg 		break;
3044a5c29683SJohan Hedberg 
30451143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
30461143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
30471143d458SBrian Gix 		break;
30481143d458SBrian Gix 
30491143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
30501143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
305116cde993SSzymon Janc 		break;
305207f7fa5dSAndre Guedes 
30537a4cd51dSMarcel Holtmann 	case HCI_OP_LE_SET_RANDOM_ADDR:
30547a4cd51dSMarcel Holtmann 		hci_cc_le_set_random_addr(hdev, skb);
30557a4cd51dSMarcel Holtmann 		break;
30567a4cd51dSMarcel Holtmann 
3057c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
3058c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
3059c1d5dc4aSJohan Hedberg 		break;
3060c1d5dc4aSJohan Hedberg 
3061533553f8SMarcel Holtmann 	case HCI_OP_LE_SET_SCAN_PARAM:
3062533553f8SMarcel Holtmann 		hci_cc_le_set_scan_param(hdev, skb);
3063533553f8SMarcel Holtmann 		break;
3064533553f8SMarcel Holtmann 
3065eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
3066eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
3067eb9d91f5SAndre Guedes 		break;
3068eb9d91f5SAndre Guedes 
3069cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
3070cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
3071cf1d081fSJohan Hedberg 		break;
3072cf1d081fSJohan Hedberg 
30730f36b589SMarcel Holtmann 	case HCI_OP_LE_CLEAR_WHITE_LIST:
30740f36b589SMarcel Holtmann 		hci_cc_le_clear_white_list(hdev, skb);
30750f36b589SMarcel Holtmann 		break;
30760f36b589SMarcel Holtmann 
30770f36b589SMarcel Holtmann 	case HCI_OP_LE_ADD_TO_WHITE_LIST:
30780f36b589SMarcel Holtmann 		hci_cc_le_add_to_white_list(hdev, skb);
30790f36b589SMarcel Holtmann 		break;
30800f36b589SMarcel Holtmann 
30810f36b589SMarcel Holtmann 	case HCI_OP_LE_DEL_FROM_WHITE_LIST:
30820f36b589SMarcel Holtmann 		hci_cc_le_del_from_white_list(hdev, skb);
30830f36b589SMarcel Holtmann 		break;
30840f36b589SMarcel Holtmann 
30859b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
30869b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
30879b008c04SJohan Hedberg 		break;
30889b008c04SJohan Hedberg 
3089a8e1bfaaSMarcel Holtmann 	case HCI_OP_LE_READ_DEF_DATA_LEN:
3090a8e1bfaaSMarcel Holtmann 		hci_cc_le_read_def_data_len(hdev, skb);
3091a8e1bfaaSMarcel Holtmann 		break;
3092a8e1bfaaSMarcel Holtmann 
3093a8e1bfaaSMarcel Holtmann 	case HCI_OP_LE_WRITE_DEF_DATA_LEN:
3094a8e1bfaaSMarcel Holtmann 		hci_cc_le_write_def_data_len(hdev, skb);
3095a8e1bfaaSMarcel Holtmann 		break;
3096a8e1bfaaSMarcel Holtmann 
3097a8e1bfaaSMarcel Holtmann 	case HCI_OP_LE_READ_MAX_DATA_LEN:
3098a8e1bfaaSMarcel Holtmann 		hci_cc_le_read_max_data_len(hdev, skb);
3099a8e1bfaaSMarcel Holtmann 		break;
3100a8e1bfaaSMarcel Holtmann 
3101f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
3102f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
3103f9b49306SAndre Guedes 		break;
3104f9b49306SAndre Guedes 
310556ed2cb8SJohan Hedberg 	case HCI_OP_LE_SET_ADV_PARAM:
310656ed2cb8SJohan Hedberg 		hci_cc_set_adv_param(hdev, skb);
310756ed2cb8SJohan Hedberg 		break;
310856ed2cb8SJohan Hedberg 
310993c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
311093c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
311193c284eeSAndrei Emeltchenko 		break;
311293c284eeSAndrei Emeltchenko 
31135ae76a94SAndrzej Kaczmarek 	case HCI_OP_READ_RSSI:
31145ae76a94SAndrzej Kaczmarek 		hci_cc_read_rssi(hdev, skb);
31155ae76a94SAndrzej Kaczmarek 		break;
31165ae76a94SAndrzej Kaczmarek 
31175a134faeSAndrzej Kaczmarek 	case HCI_OP_READ_TX_POWER:
31185a134faeSAndrzej Kaczmarek 		hci_cc_read_tx_power(hdev, skb);
31195a134faeSAndrzej Kaczmarek 		break;
31205a134faeSAndrzej Kaczmarek 
3121c50b33c8SMarcel Holtmann 	case HCI_OP_WRITE_SSP_DEBUG_MODE:
3122c50b33c8SMarcel Holtmann 		hci_cc_write_ssp_debug_mode(hdev, skb);
3123c50b33c8SMarcel Holtmann 		break;
3124c50b33c8SMarcel Holtmann 
3125a9de9248SMarcel Holtmann 	default:
3126e6214487SJohan Hedberg 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
3127a9de9248SMarcel Holtmann 		break;
3128a9de9248SMarcel Holtmann 	}
3129a9de9248SMarcel Holtmann 
3130e6214487SJohan Hedberg 	if (*opcode != HCI_OP_NOP)
313165cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
31326bd32326SVille Tervo 
3133600b2150SJohan Hedberg 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags))
3134600b2150SJohan Hedberg 		atomic_set(&hdev->cmd_cnt, 1);
3135600b2150SJohan Hedberg 
3136e6214487SJohan Hedberg 	hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
3137e6214487SJohan Hedberg 			     req_complete_skb);
31389238f36aSJohan Hedberg 
3139600b2150SJohan Hedberg 	if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
3140c347b765SGustavo F. Padovan 		queue_work(hdev->workqueue, &hdev->cmd_work);
3141a9de9248SMarcel Holtmann }
3142a9de9248SMarcel Holtmann 
3143e6214487SJohan Hedberg static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
3144e6214487SJohan Hedberg 			       u16 *opcode, u8 *status,
3145e6214487SJohan Hedberg 			       hci_req_complete_t *req_complete,
3146e6214487SJohan Hedberg 			       hci_req_complete_skb_t *req_complete_skb)
3147a9de9248SMarcel Holtmann {
3148a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
3149a9de9248SMarcel Holtmann 
3150a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
3151a9de9248SMarcel Holtmann 
3152e6214487SJohan Hedberg 	*opcode = __le16_to_cpu(ev->opcode);
3153e6214487SJohan Hedberg 	*status = ev->status;
3154a9de9248SMarcel Holtmann 
3155e6214487SJohan Hedberg 	switch (*opcode) {
3156a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
3157a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
3158a9de9248SMarcel Holtmann 		break;
3159a9de9248SMarcel Holtmann 
3160a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
3161a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
3162a9de9248SMarcel Holtmann 		break;
3163a9de9248SMarcel Holtmann 
31649645c76cSKuba Pawlak 	case HCI_OP_DISCONNECT:
31659645c76cSKuba Pawlak 		hci_cs_disconnect(hdev, ev->status);
31669645c76cSKuba Pawlak 		break;
31679645c76cSKuba Pawlak 
3168a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
3169a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
3170a9de9248SMarcel Holtmann 		break;
3171a9de9248SMarcel Holtmann 
3172f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
3173f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
3174f8558555SMarcel Holtmann 		break;
3175f8558555SMarcel Holtmann 
3176f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
3177f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
3178f8558555SMarcel Holtmann 		break;
3179f8558555SMarcel Holtmann 
3180a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
3181a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
3182a9de9248SMarcel Holtmann 		break;
3183a9de9248SMarcel Holtmann 
3184769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
3185769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
3186769be974SMarcel Holtmann 		break;
3187769be974SMarcel Holtmann 
3188769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
3189769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
3190769be974SMarcel Holtmann 		break;
3191769be974SMarcel Holtmann 
3192a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
3193a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
3194a9de9248SMarcel Holtmann 		break;
3195a9de9248SMarcel Holtmann 
31969645c76cSKuba Pawlak 	case HCI_OP_CREATE_PHY_LINK:
31979645c76cSKuba Pawlak 		hci_cs_create_phylink(hdev, ev->status);
31989645c76cSKuba Pawlak 		break;
31999645c76cSKuba Pawlak 
32009645c76cSKuba Pawlak 	case HCI_OP_ACCEPT_PHY_LINK:
32019645c76cSKuba Pawlak 		hci_cs_accept_phylink(hdev, ev->status);
32029645c76cSKuba Pawlak 		break;
32039645c76cSKuba Pawlak 
3204a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
3205a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
3206a9de9248SMarcel Holtmann 		break;
3207a9de9248SMarcel Holtmann 
3208a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
3209a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
3210a9de9248SMarcel Holtmann 		break;
3211a9de9248SMarcel Holtmann 
321250fc85f1SKuba Pawlak 	case HCI_OP_SWITCH_ROLE:
321350fc85f1SKuba Pawlak 		hci_cs_switch_role(hdev, ev->status);
321450fc85f1SKuba Pawlak 		break;
321550fc85f1SKuba Pawlak 
3216cb1d68f7SJohan Hedberg 	case HCI_OP_LE_CREATE_CONN:
3217cb1d68f7SJohan Hedberg 		hci_cs_le_create_conn(hdev, ev->status);
3218cb1d68f7SJohan Hedberg 		break;
3219cb1d68f7SJohan Hedberg 
32200fe29fd1SMarcel Holtmann 	case HCI_OP_LE_READ_REMOTE_FEATURES:
32210fe29fd1SMarcel Holtmann 		hci_cs_le_read_remote_features(hdev, ev->status);
32220fe29fd1SMarcel Holtmann 		break;
32230fe29fd1SMarcel Holtmann 
322481d0c8adSJohan Hedberg 	case HCI_OP_LE_START_ENC:
322581d0c8adSJohan Hedberg 		hci_cs_le_start_enc(hdev, ev->status);
322681d0c8adSJohan Hedberg 		break;
322781d0c8adSJohan Hedberg 
3228a9de9248SMarcel Holtmann 	default:
3229e6214487SJohan Hedberg 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
3230a9de9248SMarcel Holtmann 		break;
3231a9de9248SMarcel Holtmann 	}
3232a9de9248SMarcel Holtmann 
3233e6214487SJohan Hedberg 	if (*opcode != HCI_OP_NOP)
323465cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
32356bd32326SVille Tervo 
3236600b2150SJohan Hedberg 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags))
3237600b2150SJohan Hedberg 		atomic_set(&hdev->cmd_cnt, 1);
3238600b2150SJohan Hedberg 
3239444c6dd5SJohan Hedberg 	/* Indicate request completion if the command failed. Also, if
3240444c6dd5SJohan Hedberg 	 * we're not waiting for a special event and we get a success
3241444c6dd5SJohan Hedberg 	 * command status we should try to flag the request as completed
3242444c6dd5SJohan Hedberg 	 * (since for this kind of commands there will not be a command
3243444c6dd5SJohan Hedberg 	 * complete event).
3244444c6dd5SJohan Hedberg 	 */
324502350a72SJohan Hedberg 	if (ev->status ||
3246db6e3e8dSJohan Hedberg 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
3247e6214487SJohan Hedberg 		hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
3248e6214487SJohan Hedberg 				     req_complete_skb);
32499238f36aSJohan Hedberg 
3250600b2150SJohan Hedberg 	if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
3251c347b765SGustavo F. Padovan 		queue_work(hdev->workqueue, &hdev->cmd_work);
3252a9de9248SMarcel Holtmann }
3253a9de9248SMarcel Holtmann 
325424dfa343SMarcel Holtmann static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
325524dfa343SMarcel Holtmann {
325624dfa343SMarcel Holtmann 	struct hci_ev_hardware_error *ev = (void *) skb->data;
325724dfa343SMarcel Holtmann 
3258c7741d16SMarcel Holtmann 	hdev->hw_error_code = ev->code;
3259c7741d16SMarcel Holtmann 
3260c7741d16SMarcel Holtmann 	queue_work(hdev->req_workqueue, &hdev->error_reset);
326124dfa343SMarcel Holtmann }
326224dfa343SMarcel Holtmann 
32636039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3264a9de9248SMarcel Holtmann {
3265a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
3266a9de9248SMarcel Holtmann 	struct hci_conn *conn;
3267a9de9248SMarcel Holtmann 
32689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3269a9de9248SMarcel Holtmann 
3270a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3271a9de9248SMarcel Holtmann 
3272a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3273a9de9248SMarcel Holtmann 	if (conn) {
327440bef302SJohan Hedberg 		if (!ev->status)
327540bef302SJohan Hedberg 			conn->role = ev->role;
3276a9de9248SMarcel Holtmann 
327751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
3278a9de9248SMarcel Holtmann 
3279a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
3280a9de9248SMarcel Holtmann 	}
3281a9de9248SMarcel Holtmann 
3282a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3283a9de9248SMarcel Holtmann }
3284a9de9248SMarcel Holtmann 
32856039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
32861da177e4SLinus Torvalds {
3287a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
32881da177e4SLinus Torvalds 	int i;
32891da177e4SLinus Torvalds 
329032ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
329132ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
329232ac5b9bSAndrei Emeltchenko 		return;
329332ac5b9bSAndrei Emeltchenko 	}
329432ac5b9bSAndrei Emeltchenko 
3295c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
3296c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
32971da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
32981da177e4SLinus Torvalds 		return;
32991da177e4SLinus Torvalds 	}
33001da177e4SLinus Torvalds 
3301c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
3302c5993de8SAndrei Emeltchenko 
3303613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
3304613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
33051da177e4SLinus Torvalds 		struct hci_conn *conn;
33061da177e4SLinus Torvalds 		__u16  handle, count;
33071da177e4SLinus Torvalds 
3308613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
3309613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
33101da177e4SLinus Torvalds 
33111da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
3312f4280918SAndrei Emeltchenko 		if (!conn)
3313f4280918SAndrei Emeltchenko 			continue;
3314f4280918SAndrei Emeltchenko 
33151da177e4SLinus Torvalds 		conn->sent -= count;
33161da177e4SLinus Torvalds 
3317f4280918SAndrei Emeltchenko 		switch (conn->type) {
3318f4280918SAndrei Emeltchenko 		case ACL_LINK:
331970f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
332070f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
33211da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
3322f4280918SAndrei Emeltchenko 			break;
3323f4280918SAndrei Emeltchenko 
3324f4280918SAndrei Emeltchenko 		case LE_LINK:
33256ed58ec5SVille Tervo 			if (hdev->le_pkts) {
33266ed58ec5SVille Tervo 				hdev->le_cnt += count;
33276ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
33286ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
33296ed58ec5SVille Tervo 			} else {
33306ed58ec5SVille Tervo 				hdev->acl_cnt += count;
33316ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
33326ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
33336ed58ec5SVille Tervo 			}
3334f4280918SAndrei Emeltchenko 			break;
3335f4280918SAndrei Emeltchenko 
3336f4280918SAndrei Emeltchenko 		case SCO_LINK:
333770f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
333870f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
33395b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
3340f4280918SAndrei Emeltchenko 			break;
3341f4280918SAndrei Emeltchenko 
3342f4280918SAndrei Emeltchenko 		default:
3343f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
3344f4280918SAndrei Emeltchenko 			break;
33451da177e4SLinus Torvalds 		}
33461da177e4SLinus Torvalds 	}
3347a9de9248SMarcel Holtmann 
33483eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
33491da177e4SLinus Torvalds }
33501da177e4SLinus Torvalds 
335176ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
335276ef7cf7SAndrei Emeltchenko 						 __u16 handle)
335376ef7cf7SAndrei Emeltchenko {
335476ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
335576ef7cf7SAndrei Emeltchenko 
335676ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
335776ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
335876ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
335976ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
336076ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
336176ef7cf7SAndrei Emeltchenko 		if (chan)
336276ef7cf7SAndrei Emeltchenko 			return chan->conn;
336376ef7cf7SAndrei Emeltchenko 		break;
336476ef7cf7SAndrei Emeltchenko 	default:
336576ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
336676ef7cf7SAndrei Emeltchenko 		break;
336776ef7cf7SAndrei Emeltchenko 	}
336876ef7cf7SAndrei Emeltchenko 
336976ef7cf7SAndrei Emeltchenko 	return NULL;
337076ef7cf7SAndrei Emeltchenko }
337176ef7cf7SAndrei Emeltchenko 
33726039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
337325e89e99SAndrei Emeltchenko {
337425e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
337525e89e99SAndrei Emeltchenko 	int i;
337625e89e99SAndrei Emeltchenko 
337725e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
337825e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
337925e89e99SAndrei Emeltchenko 		return;
338025e89e99SAndrei Emeltchenko 	}
338125e89e99SAndrei Emeltchenko 
338225e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
338325e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
338425e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
338525e89e99SAndrei Emeltchenko 		return;
338625e89e99SAndrei Emeltchenko 	}
338725e89e99SAndrei Emeltchenko 
338825e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
338925e89e99SAndrei Emeltchenko 	       ev->num_hndl);
339025e89e99SAndrei Emeltchenko 
339125e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
339225e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
339376ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
339425e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
339525e89e99SAndrei Emeltchenko 
339625e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
339725e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
339825e89e99SAndrei Emeltchenko 
339976ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
340025e89e99SAndrei Emeltchenko 		if (!conn)
340125e89e99SAndrei Emeltchenko 			continue;
340225e89e99SAndrei Emeltchenko 
340325e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
340425e89e99SAndrei Emeltchenko 
340525e89e99SAndrei Emeltchenko 		switch (conn->type) {
340625e89e99SAndrei Emeltchenko 		case ACL_LINK:
3407bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
340825e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
340925e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
341025e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
341125e89e99SAndrei Emeltchenko 			break;
341225e89e99SAndrei Emeltchenko 
341325e89e99SAndrei Emeltchenko 		default:
341425e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
341525e89e99SAndrei Emeltchenko 			break;
341625e89e99SAndrei Emeltchenko 		}
341725e89e99SAndrei Emeltchenko 	}
341825e89e99SAndrei Emeltchenko 
341925e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
342025e89e99SAndrei Emeltchenko }
342125e89e99SAndrei Emeltchenko 
34226039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
34231da177e4SLinus Torvalds {
3424a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
342504837f64SMarcel Holtmann 	struct hci_conn *conn;
34261da177e4SLinus Torvalds 
34279f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
34281da177e4SLinus Torvalds 
34291da177e4SLinus Torvalds 	hci_dev_lock(hdev);
34301da177e4SLinus Torvalds 
343104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
343204837f64SMarcel Holtmann 	if (conn) {
343304837f64SMarcel Holtmann 		conn->mode = ev->mode;
343404837f64SMarcel Holtmann 
34358fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
34368fc9ced3SGustavo Padovan 					&conn->flags)) {
343704837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
343858a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
343904837f64SMarcel Holtmann 			else
344058a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
344104837f64SMarcel Holtmann 		}
3442e73439d8SMarcel Holtmann 
344351a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
3444e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
344504837f64SMarcel Holtmann 	}
344604837f64SMarcel Holtmann 
344704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
344804837f64SMarcel Holtmann }
344904837f64SMarcel Holtmann 
34506039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
34511da177e4SLinus Torvalds {
3452052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
3453052b30b0SMarcel Holtmann 	struct hci_conn *conn;
3454052b30b0SMarcel Holtmann 
3455a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3456052b30b0SMarcel Holtmann 
3457052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3458052b30b0SMarcel Holtmann 
3459052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3460b6f98044SWaldemar Rymarkiewicz 	if (!conn)
3461b6f98044SWaldemar Rymarkiewicz 		goto unlock;
3462b6f98044SWaldemar Rymarkiewicz 
3463b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
3464052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3465052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
346676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3467052b30b0SMarcel Holtmann 	}
3468052b30b0SMarcel Holtmann 
3469d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
34702f407f0aSJohan Hedberg 	    !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) {
347103b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
347203b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
3473d7a5a11dSMarcel Holtmann 	} else if (hci_dev_test_flag(hdev, HCI_MGMT)) {
3474a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
3475a770bb5aSWaldemar Rymarkiewicz 
3476a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
3477a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
3478a770bb5aSWaldemar Rymarkiewicz 		else
3479a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
3480a770bb5aSWaldemar Rymarkiewicz 
3481744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
3482a770bb5aSWaldemar Rymarkiewicz 	}
3483980e1a53SJohan Hedberg 
3484b6f98044SWaldemar Rymarkiewicz unlock:
3485052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
34861da177e4SLinus Torvalds }
34871da177e4SLinus Torvalds 
3488cb6f3f7aSJohan Hedberg static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
3489cb6f3f7aSJohan Hedberg {
3490cb6f3f7aSJohan Hedberg 	if (key_type == HCI_LK_CHANGED_COMBINATION)
3491cb6f3f7aSJohan Hedberg 		return;
3492cb6f3f7aSJohan Hedberg 
3493cb6f3f7aSJohan Hedberg 	conn->pin_length = pin_len;
3494cb6f3f7aSJohan Hedberg 	conn->key_type = key_type;
3495cb6f3f7aSJohan Hedberg 
3496cb6f3f7aSJohan Hedberg 	switch (key_type) {
3497cb6f3f7aSJohan Hedberg 	case HCI_LK_LOCAL_UNIT:
3498cb6f3f7aSJohan Hedberg 	case HCI_LK_REMOTE_UNIT:
3499cb6f3f7aSJohan Hedberg 	case HCI_LK_DEBUG_COMBINATION:
3500cb6f3f7aSJohan Hedberg 		return;
3501cb6f3f7aSJohan Hedberg 	case HCI_LK_COMBINATION:
3502cb6f3f7aSJohan Hedberg 		if (pin_len == 16)
3503cb6f3f7aSJohan Hedberg 			conn->pending_sec_level = BT_SECURITY_HIGH;
3504cb6f3f7aSJohan Hedberg 		else
3505cb6f3f7aSJohan Hedberg 			conn->pending_sec_level = BT_SECURITY_MEDIUM;
3506cb6f3f7aSJohan Hedberg 		break;
3507cb6f3f7aSJohan Hedberg 	case HCI_LK_UNAUTH_COMBINATION_P192:
3508cb6f3f7aSJohan Hedberg 	case HCI_LK_UNAUTH_COMBINATION_P256:
3509cb6f3f7aSJohan Hedberg 		conn->pending_sec_level = BT_SECURITY_MEDIUM;
3510cb6f3f7aSJohan Hedberg 		break;
3511cb6f3f7aSJohan Hedberg 	case HCI_LK_AUTH_COMBINATION_P192:
3512cb6f3f7aSJohan Hedberg 		conn->pending_sec_level = BT_SECURITY_HIGH;
3513cb6f3f7aSJohan Hedberg 		break;
3514cb6f3f7aSJohan Hedberg 	case HCI_LK_AUTH_COMBINATION_P256:
3515cb6f3f7aSJohan Hedberg 		conn->pending_sec_level = BT_SECURITY_FIPS;
3516cb6f3f7aSJohan Hedberg 		break;
3517cb6f3f7aSJohan Hedberg 	}
3518cb6f3f7aSJohan Hedberg }
3519cb6f3f7aSJohan Hedberg 
35206039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
35211da177e4SLinus Torvalds {
352255ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
352355ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
352455ed8ca1SJohan Hedberg 	struct hci_conn *conn;
352555ed8ca1SJohan Hedberg 	struct link_key *key;
352655ed8ca1SJohan Hedberg 
3527a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
352855ed8ca1SJohan Hedberg 
3529d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
353055ed8ca1SJohan Hedberg 		return;
353155ed8ca1SJohan Hedberg 
353255ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
353355ed8ca1SJohan Hedberg 
353455ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
353555ed8ca1SJohan Hedberg 	if (!key) {
35366ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
35376ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
353855ed8ca1SJohan Hedberg 		goto not_found;
353955ed8ca1SJohan Hedberg 	}
354055ed8ca1SJohan Hedberg 
35416ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
35426ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
354355ed8ca1SJohan Hedberg 
354455ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
354560b83f57SWaldemar Rymarkiewicz 	if (conn) {
3546fe8bc5acSJohan Hedberg 		clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
3547fe8bc5acSJohan Hedberg 
354866138ce8SMarcel Holtmann 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
354966138ce8SMarcel Holtmann 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
3550807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
355155ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
355255ed8ca1SJohan Hedberg 			goto not_found;
355355ed8ca1SJohan Hedberg 		}
355455ed8ca1SJohan Hedberg 
355560b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
3556f3fb0b58SJohan Hedberg 		    (conn->pending_sec_level == BT_SECURITY_HIGH ||
3557f3fb0b58SJohan Hedberg 		     conn->pending_sec_level == BT_SECURITY_FIPS)) {
35588fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
35598fc9ced3SGustavo Padovan 			       hdev->name);
356060b83f57SWaldemar Rymarkiewicz 			goto not_found;
356160b83f57SWaldemar Rymarkiewicz 		}
356260b83f57SWaldemar Rymarkiewicz 
3563cb6f3f7aSJohan Hedberg 		conn_set_key(conn, key->type, key->pin_len);
356460b83f57SWaldemar Rymarkiewicz 	}
356560b83f57SWaldemar Rymarkiewicz 
356655ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
35679b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
356855ed8ca1SJohan Hedberg 
356955ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
357055ed8ca1SJohan Hedberg 
357155ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
357255ed8ca1SJohan Hedberg 
357355ed8ca1SJohan Hedberg 	return;
357455ed8ca1SJohan Hedberg 
357555ed8ca1SJohan Hedberg not_found:
357655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
357755ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
35781da177e4SLinus Torvalds }
35791da177e4SLinus Torvalds 
35806039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
35811da177e4SLinus Torvalds {
3582052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
3583052b30b0SMarcel Holtmann 	struct hci_conn *conn;
35847652ff6aSJohan Hedberg 	struct link_key *key;
35857652ff6aSJohan Hedberg 	bool persistent;
358655ed8ca1SJohan Hedberg 	u8 pin_len = 0;
3587052b30b0SMarcel Holtmann 
3588a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3589052b30b0SMarcel Holtmann 
3590052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3591052b30b0SMarcel Holtmann 
3592052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
359382c13d42SJohan Hedberg 	if (!conn)
359482c13d42SJohan Hedberg 		goto unlock;
359582c13d42SJohan Hedberg 
3596052b30b0SMarcel Holtmann 	hci_conn_hold(conn);
3597052b30b0SMarcel Holtmann 	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
359876a68ba0SDavid Herrmann 	hci_conn_drop(conn);
359982c13d42SJohan Hedberg 
3600fe8bc5acSJohan Hedberg 	set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
3601cb6f3f7aSJohan Hedberg 	conn_set_key(conn, ev->key_type, conn->pin_length);
3602052b30b0SMarcel Holtmann 
3603d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
36047652ff6aSJohan Hedberg 		goto unlock;
360555ed8ca1SJohan Hedberg 
36067652ff6aSJohan Hedberg 	key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key,
36077652ff6aSJohan Hedberg 			        ev->key_type, pin_len, &persistent);
36087652ff6aSJohan Hedberg 	if (!key)
36097652ff6aSJohan Hedberg 		goto unlock;
36107652ff6aSJohan Hedberg 
3611cb6f3f7aSJohan Hedberg 	/* Update connection information since adding the key will have
3612cb6f3f7aSJohan Hedberg 	 * fixed up the type in the case of changed combination keys.
3613cb6f3f7aSJohan Hedberg 	 */
3614cb6f3f7aSJohan Hedberg 	if (ev->key_type == HCI_LK_CHANGED_COMBINATION)
3615cb6f3f7aSJohan Hedberg 		conn_set_key(conn, key->type, key->pin_len);
3616cb6f3f7aSJohan Hedberg 
36177652ff6aSJohan Hedberg 	mgmt_new_link_key(hdev, key, persistent);
36187652ff6aSJohan Hedberg 
36196d5650c4SJohan Hedberg 	/* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
36206d5650c4SJohan Hedberg 	 * is set. If it's not set simply remove the key from the kernel
36216d5650c4SJohan Hedberg 	 * list (we've still notified user space about it but with
36226d5650c4SJohan Hedberg 	 * store_hint being 0).
36236d5650c4SJohan Hedberg 	 */
36246d5650c4SJohan Hedberg 	if (key->type == HCI_LK_DEBUG_COMBINATION &&
3625d7a5a11dSMarcel Holtmann 	    !hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS)) {
36260378b597SJohan Hedberg 		list_del_rcu(&key->list);
36270378b597SJohan Hedberg 		kfree_rcu(key, rcu);
362882c13d42SJohan Hedberg 		goto unlock;
362982c13d42SJohan Hedberg 	}
363082c13d42SJohan Hedberg 
3631af6a9c32SJohan Hedberg 	if (persistent)
3632af6a9c32SJohan Hedberg 		clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
3633af6a9c32SJohan Hedberg 	else
3634af6a9c32SJohan Hedberg 		set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
36357652ff6aSJohan Hedberg 
36367652ff6aSJohan Hedberg unlock:
3637052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
36381da177e4SLinus Torvalds }
36391da177e4SLinus Torvalds 
36406039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
364104837f64SMarcel Holtmann {
3642a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
364304837f64SMarcel Holtmann 	struct hci_conn *conn;
364404837f64SMarcel Holtmann 
36459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
364604837f64SMarcel Holtmann 
364704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
364804837f64SMarcel Holtmann 
364904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
36501da177e4SLinus Torvalds 	if (conn && !ev->status) {
36511da177e4SLinus Torvalds 		struct inquiry_entry *ie;
36521da177e4SLinus Torvalds 
3653cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3654cc11b9c1SAndrei Emeltchenko 		if (ie) {
36551da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
36561da177e4SLinus Torvalds 			ie->timestamp = jiffies;
36571da177e4SLinus Torvalds 		}
36581da177e4SLinus Torvalds 	}
36591da177e4SLinus Torvalds 
36601da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
36611da177e4SLinus Torvalds }
36621da177e4SLinus Torvalds 
36636039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3664a8746417SMarcel Holtmann {
3665a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3666a8746417SMarcel Holtmann 	struct hci_conn *conn;
3667a8746417SMarcel Holtmann 
36689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3669a8746417SMarcel Holtmann 
3670a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
3671a8746417SMarcel Holtmann 
3672a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3673a8746417SMarcel Holtmann 	if (conn && !ev->status)
3674a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3675a8746417SMarcel Holtmann 
3676a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
3677a8746417SMarcel Holtmann }
3678a8746417SMarcel Holtmann 
36796039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
368085a1e930SMarcel Holtmann {
3681a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
368285a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
368385a1e930SMarcel Holtmann 
368485a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
368585a1e930SMarcel Holtmann 
368685a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
368785a1e930SMarcel Holtmann 
3688cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3689cc11b9c1SAndrei Emeltchenko 	if (ie) {
369085a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
369185a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
369285a1e930SMarcel Holtmann 	}
369385a1e930SMarcel Holtmann 
369485a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
369585a1e930SMarcel Holtmann }
369685a1e930SMarcel Holtmann 
36976039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3698807deac2SGustavo Padovan 					     struct sk_buff *skb)
3699a9de9248SMarcel Holtmann {
3700a9de9248SMarcel Holtmann 	struct inquiry_data data;
3701a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
3702a9de9248SMarcel Holtmann 
3703a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3704a9de9248SMarcel Holtmann 
3705a9de9248SMarcel Holtmann 	if (!num_rsp)
3706a9de9248SMarcel Holtmann 		return;
3707a9de9248SMarcel Holtmann 
3708d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
37091519cc17SAndre Guedes 		return;
37101519cc17SAndre Guedes 
3711a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3712a9de9248SMarcel Holtmann 
3713a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3714138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3715138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3716a9de9248SMarcel Holtmann 
3717e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3718af58925cSMarcel Holtmann 			u32 flags;
3719af58925cSMarcel Holtmann 
3720a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3721a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3722a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3723a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3724a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3725a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3726a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
372741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
37283175405bSJohan Hedberg 
3729af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
3730af58925cSMarcel Holtmann 
373148264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3732e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3733af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
3734a9de9248SMarcel Holtmann 		}
3735a9de9248SMarcel Holtmann 	} else {
3736a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3737a9de9248SMarcel Holtmann 
3738e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3739af58925cSMarcel Holtmann 			u32 flags;
3740af58925cSMarcel Holtmann 
3741a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3742a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3743a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3744a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3745a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3746a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3747a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
374841a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
3749af58925cSMarcel Holtmann 
3750af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
3751af58925cSMarcel Holtmann 
375248264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3753e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3754af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
3755a9de9248SMarcel Holtmann 		}
3756a9de9248SMarcel Holtmann 	}
3757a9de9248SMarcel Holtmann 
3758a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3759a9de9248SMarcel Holtmann }
3760a9de9248SMarcel Holtmann 
37616039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3762807deac2SGustavo Padovan 					struct sk_buff *skb)
3763a9de9248SMarcel Holtmann {
376441a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
376541a96212SMarcel Holtmann 	struct hci_conn *conn;
376641a96212SMarcel Holtmann 
3767a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
376841a96212SMarcel Holtmann 
376941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
377041a96212SMarcel Holtmann 
377141a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3772ccd556feSJohan Hedberg 	if (!conn)
3773ccd556feSJohan Hedberg 		goto unlock;
3774ccd556feSJohan Hedberg 
3775cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
3776cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
3777cad718edSJohan Hedberg 
3778769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
377941a96212SMarcel Holtmann 		struct inquiry_entry *ie;
378041a96212SMarcel Holtmann 
3781cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3782cc11b9c1SAndrei Emeltchenko 		if (ie)
378302b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
378441a96212SMarcel Holtmann 
3785bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
378658a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
3787bbb0eadaSJaganath Kanakkassery 		} else {
3788bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
3789bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
3790bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
3791bbb0eadaSJaganath Kanakkassery 			 * this.
3792bbb0eadaSJaganath Kanakkassery 			 *
3793bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
3794bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
3795bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
3796bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
3797bbb0eadaSJaganath Kanakkassery 		}
3798eb9a8f3fSMarcel Holtmann 
3799eb9a8f3fSMarcel Holtmann 		if (ev->features[0] & LMP_HOST_SC)
3800eb9a8f3fSMarcel Holtmann 			set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
380141a96212SMarcel Holtmann 	}
380241a96212SMarcel Holtmann 
3803ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3804ccd556feSJohan Hedberg 		goto unlock;
3805ccd556feSJohan Hedberg 
3806671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3807127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3808127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3809127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3810127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3811127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3812b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
381348ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
3814392599b9SJohan Hedberg 
3815127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3816769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3817539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
381876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3819769be974SMarcel Holtmann 	}
3820769be974SMarcel Holtmann 
3821ccd556feSJohan Hedberg unlock:
382241a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3823a9de9248SMarcel Holtmann }
3824a9de9248SMarcel Holtmann 
38256039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3826807deac2SGustavo Padovan 				       struct sk_buff *skb)
3827a9de9248SMarcel Holtmann {
3828b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3829b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3830b6a0dc82SMarcel Holtmann 
38319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3832b6a0dc82SMarcel Holtmann 
3833b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3834b6a0dc82SMarcel Holtmann 
3835b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
38369dc0a3afSMarcel Holtmann 	if (!conn) {
38379dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
38389dc0a3afSMarcel Holtmann 			goto unlock;
38399dc0a3afSMarcel Holtmann 
38409dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3841b6a0dc82SMarcel Holtmann 		if (!conn)
3842b6a0dc82SMarcel Holtmann 			goto unlock;
3843b6a0dc82SMarcel Holtmann 
38449dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
38459dc0a3afSMarcel Holtmann 	}
38469dc0a3afSMarcel Holtmann 
3847732547f9SMarcel Holtmann 	switch (ev->status) {
3848732547f9SMarcel Holtmann 	case 0x00:
3849732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3850732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3851732547f9SMarcel Holtmann 
385223b9ceb7SMarcel Holtmann 		hci_debugfs_create_conn(conn);
3853732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3854732547f9SMarcel Holtmann 		break;
3855732547f9SMarcel Holtmann 
385681218d20SNick Pelly 	case 0x10:	/* Connection Accept Timeout */
38571a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
3858705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3859732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
38601038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3861732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
386227539bc4SAndrew Earl 	case 0x20:	/* Unsupported LMP Parameter value */
38632dea632fSFrédéric Dalleau 		if (conn->out) {
3864efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3865efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
38662dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
3867efc7688bSMarcel Holtmann 				goto unlock;
3868efc7688bSMarcel Holtmann 		}
3869732547f9SMarcel Holtmann 		/* fall through */
3870efc7688bSMarcel Holtmann 
3871732547f9SMarcel Holtmann 	default:
3872b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3873732547f9SMarcel Holtmann 		break;
3874732547f9SMarcel Holtmann 	}
3875b6a0dc82SMarcel Holtmann 
3876539c496dSJohan Hedberg 	hci_connect_cfm(conn, ev->status);
3877b6a0dc82SMarcel Holtmann 	if (ev->status)
3878b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3879b6a0dc82SMarcel Holtmann 
3880b6a0dc82SMarcel Holtmann unlock:
3881b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3882a9de9248SMarcel Holtmann }
3883a9de9248SMarcel Holtmann 
3884efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len)
3885efdcf8e3SMarcel Holtmann {
3886efdcf8e3SMarcel Holtmann 	size_t parsed = 0;
3887efdcf8e3SMarcel Holtmann 
3888efdcf8e3SMarcel Holtmann 	while (parsed < eir_len) {
3889efdcf8e3SMarcel Holtmann 		u8 field_len = eir[0];
3890efdcf8e3SMarcel Holtmann 
3891efdcf8e3SMarcel Holtmann 		if (field_len == 0)
3892efdcf8e3SMarcel Holtmann 			return parsed;
3893efdcf8e3SMarcel Holtmann 
3894efdcf8e3SMarcel Holtmann 		parsed += field_len + 1;
3895efdcf8e3SMarcel Holtmann 		eir += field_len + 1;
3896efdcf8e3SMarcel Holtmann 	}
3897efdcf8e3SMarcel Holtmann 
3898efdcf8e3SMarcel Holtmann 	return eir_len;
3899efdcf8e3SMarcel Holtmann }
3900efdcf8e3SMarcel Holtmann 
39016039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3902807deac2SGustavo Padovan 					    struct sk_buff *skb)
3903a9de9248SMarcel Holtmann {
3904a9de9248SMarcel Holtmann 	struct inquiry_data data;
3905a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3906a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
39079d939d94SVishal Agarwal 	size_t eir_len;
3908a9de9248SMarcel Holtmann 
3909a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3910a9de9248SMarcel Holtmann 
3911a9de9248SMarcel Holtmann 	if (!num_rsp)
3912a9de9248SMarcel Holtmann 		return;
3913a9de9248SMarcel Holtmann 
3914d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
39151519cc17SAndre Guedes 		return;
39161519cc17SAndre Guedes 
3917a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3918a9de9248SMarcel Holtmann 
3919e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3920af58925cSMarcel Holtmann 		u32 flags;
3921af58925cSMarcel Holtmann 		bool name_known;
3922561aafbcSJohan Hedberg 
3923a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3924a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3925a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3926a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3927a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3928a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3929a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
393041a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3931561aafbcSJohan Hedberg 
3932d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_MGMT))
39334ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
39344ddb1930SJohan Hedberg 						       sizeof(info->data),
39354ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3936561aafbcSJohan Hedberg 		else
3937561aafbcSJohan Hedberg 			name_known = true;
3938561aafbcSJohan Hedberg 
3939af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, name_known);
3940af58925cSMarcel Holtmann 
39419d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
3942af58925cSMarcel Holtmann 
394348264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3944af58925cSMarcel Holtmann 				  info->dev_class, info->rssi,
3945af58925cSMarcel Holtmann 				  flags, info->data, eir_len, NULL, 0);
3946a9de9248SMarcel Holtmann 	}
3947a9de9248SMarcel Holtmann 
3948a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3949a9de9248SMarcel Holtmann }
3950a9de9248SMarcel Holtmann 
39511c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
39521c2e0041SJohan Hedberg 					 struct sk_buff *skb)
39531c2e0041SJohan Hedberg {
39541c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
39551c2e0041SJohan Hedberg 	struct hci_conn *conn;
39561c2e0041SJohan Hedberg 
39579f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
39581c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
39591c2e0041SJohan Hedberg 
39601c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
39611c2e0041SJohan Hedberg 
39621c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
39631c2e0041SJohan Hedberg 	if (!conn)
39641c2e0041SJohan Hedberg 		goto unlock;
39651c2e0041SJohan Hedberg 
39669eb1fbfaSJohan Hedberg 	/* For BR/EDR the necessary steps are taken through the
39679eb1fbfaSJohan Hedberg 	 * auth_complete event.
39689eb1fbfaSJohan Hedberg 	 */
39699eb1fbfaSJohan Hedberg 	if (conn->type != LE_LINK)
39709eb1fbfaSJohan Hedberg 		goto unlock;
39719eb1fbfaSJohan Hedberg 
39721c2e0041SJohan Hedberg 	if (!ev->status)
39731c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
39741c2e0041SJohan Hedberg 
39751c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
39761c2e0041SJohan Hedberg 
39771c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3978bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
397976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
39801c2e0041SJohan Hedberg 		goto unlock;
39811c2e0041SJohan Hedberg 	}
39821c2e0041SJohan Hedberg 
39831c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
39841c2e0041SJohan Hedberg 		if (!ev->status)
39851c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
39861c2e0041SJohan Hedberg 
3987539c496dSJohan Hedberg 		hci_connect_cfm(conn, ev->status);
398876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
39891c2e0041SJohan Hedberg 	} else {
39901c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
39911c2e0041SJohan Hedberg 
39921c2e0041SJohan Hedberg 		hci_conn_hold(conn);
39931c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
399476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
39951c2e0041SJohan Hedberg 	}
39961c2e0041SJohan Hedberg 
39971c2e0041SJohan Hedberg unlock:
39981c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
39991c2e0041SJohan Hedberg }
40001c2e0041SJohan Hedberg 
40016039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
400217fa4b9dSJohan Hedberg {
400317fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
4004acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
4005acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
400658797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
400717fa4b9dSJohan Hedberg 
4008b7f94c88SMikel Astiz 	/* If both remote and local have enough IO capabilities, require
4009b7f94c88SMikel Astiz 	 * MITM protection
4010b7f94c88SMikel Astiz 	 */
4011b7f94c88SMikel Astiz 	if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT &&
4012b7f94c88SMikel Astiz 	    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT)
4013b7f94c88SMikel Astiz 		return conn->remote_auth | 0x01;
4014b7f94c88SMikel Astiz 
40157e74170aSTimo Mueller 	/* No MITM protection possible so ignore remote requirement */
40167e74170aSTimo Mueller 	return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01);
401717fa4b9dSJohan Hedberg }
401817fa4b9dSJohan Hedberg 
4019a83ed81eSMarcel Holtmann static u8 bredr_oob_data_present(struct hci_conn *conn)
4020a83ed81eSMarcel Holtmann {
4021a83ed81eSMarcel Holtmann 	struct hci_dev *hdev = conn->hdev;
4022a83ed81eSMarcel Holtmann 	struct oob_data *data;
4023a83ed81eSMarcel Holtmann 
4024a83ed81eSMarcel Holtmann 	data = hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR);
4025a83ed81eSMarcel Holtmann 	if (!data)
4026a83ed81eSMarcel Holtmann 		return 0x00;
4027a83ed81eSMarcel Holtmann 
4028bf21d793SMarcel Holtmann 	if (bredr_sc_enabled(hdev)) {
4029bf21d793SMarcel Holtmann 		/* When Secure Connections is enabled, then just
4030bf21d793SMarcel Holtmann 		 * return the present value stored with the OOB
4031bf21d793SMarcel Holtmann 		 * data. The stored value contains the right present
4032bf21d793SMarcel Holtmann 		 * information. However it can only be trusted when
4033bf21d793SMarcel Holtmann 		 * not in Secure Connection Only mode.
4034aa5b0345SMarcel Holtmann 		 */
4035d7a5a11dSMarcel Holtmann 		if (!hci_dev_test_flag(hdev, HCI_SC_ONLY))
4036bf21d793SMarcel Holtmann 			return data->present;
4037bf21d793SMarcel Holtmann 
4038bf21d793SMarcel Holtmann 		/* When Secure Connections Only mode is enabled, then
4039bf21d793SMarcel Holtmann 		 * the P-256 values are required. If they are not
4040bf21d793SMarcel Holtmann 		 * available, then do not declare that OOB data is
4041bf21d793SMarcel Holtmann 		 * present.
4042bf21d793SMarcel Holtmann 		 */
4043bf21d793SMarcel Holtmann 		if (!memcmp(data->rand256, ZERO_KEY, 16) ||
4044bf21d793SMarcel Holtmann 		    !memcmp(data->hash256, ZERO_KEY, 16))
4045aa5b0345SMarcel Holtmann 			return 0x00;
4046aa5b0345SMarcel Holtmann 
4047bf21d793SMarcel Holtmann 		return 0x02;
4048bf21d793SMarcel Holtmann 	}
4049659c7fb0SMarcel Holtmann 
4050659c7fb0SMarcel Holtmann 	/* When Secure Connections is not enabled or actually
4051659c7fb0SMarcel Holtmann 	 * not supported by the hardware, then check that if
4052659c7fb0SMarcel Holtmann 	 * P-192 data values are present.
4053659c7fb0SMarcel Holtmann 	 */
4054659c7fb0SMarcel Holtmann 	if (!memcmp(data->rand192, ZERO_KEY, 16) ||
4055659c7fb0SMarcel Holtmann 	    !memcmp(data->hash192, ZERO_KEY, 16))
4056659c7fb0SMarcel Holtmann 		return 0x00;
4057659c7fb0SMarcel Holtmann 
4058a83ed81eSMarcel Holtmann 	return 0x01;
4059659c7fb0SMarcel Holtmann }
4060a83ed81eSMarcel Holtmann 
40616039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
40620493684eSMarcel Holtmann {
40630493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
40640493684eSMarcel Holtmann 	struct hci_conn *conn;
40650493684eSMarcel Holtmann 
40660493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
40670493684eSMarcel Holtmann 
40680493684eSMarcel Holtmann 	hci_dev_lock(hdev);
40690493684eSMarcel Holtmann 
40700493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
407103b555e1SJohan Hedberg 	if (!conn)
407203b555e1SJohan Hedberg 		goto unlock;
407303b555e1SJohan Hedberg 
40740493684eSMarcel Holtmann 	hci_conn_hold(conn);
40750493684eSMarcel Holtmann 
4076d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
407703b555e1SJohan Hedberg 		goto unlock;
407803b555e1SJohan Hedberg 
40792f407f0aSJohan Hedberg 	/* Allow pairing if we're pairable, the initiators of the
40802f407f0aSJohan Hedberg 	 * pairing or if the remote is not requesting bonding.
40812f407f0aSJohan Hedberg 	 */
4082d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_BONDABLE) ||
40832f407f0aSJohan Hedberg 	    test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) ||
408403b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
408517fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
408617fa4b9dSJohan Hedberg 
408717fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
40887a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
40897a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
40907a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
4091a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
4092b7f94c88SMikel Astiz 
4093b7f94c88SMikel Astiz 		/* If we are initiators, there is no remote information yet */
4094b7f94c88SMikel Astiz 		if (conn->remote_auth == 0xff) {
4095b16c6604SMikel Astiz 			/* Request MITM protection if our IO caps allow it
40964ad51a75SJohan Hedberg 			 * except for the no-bonding case.
4097b16c6604SMikel Astiz 			 */
40986fd6b915SMikel Astiz 			if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
40999f743d74SJohan Hedberg 			    conn->auth_type != HCI_AT_NO_BONDING)
41006c53823aSJohan Hedberg 				conn->auth_type |= 0x01;
4101b7f94c88SMikel Astiz 		} else {
41027cbc9bd9SJohan Hedberg 			conn->auth_type = hci_get_auth_req(conn);
4103b7f94c88SMikel Astiz 		}
410417fa4b9dSJohan Hedberg 
410582c295b1SJohan Hedberg 		/* If we're not bondable, force one of the non-bondable
410682c295b1SJohan Hedberg 		 * authentication requirement values.
410782c295b1SJohan Hedberg 		 */
4108d7a5a11dSMarcel Holtmann 		if (!hci_dev_test_flag(hdev, HCI_BONDABLE))
410982c295b1SJohan Hedberg 			conn->auth_type &= HCI_AT_NO_BONDING_MITM;
411082c295b1SJohan Hedberg 
411182c295b1SJohan Hedberg 		cp.authentication = conn->auth_type;
4112a83ed81eSMarcel Holtmann 		cp.oob_data = bredr_oob_data_present(conn);
4113ce85ee13SSzymon Janc 
411417fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
411517fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
411603b555e1SJohan Hedberg 	} else {
411703b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
411803b555e1SJohan Hedberg 
411903b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
41209f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
412103b555e1SJohan Hedberg 
412203b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
412303b555e1SJohan Hedberg 			     sizeof(cp), &cp);
412403b555e1SJohan Hedberg 	}
412503b555e1SJohan Hedberg 
412603b555e1SJohan Hedberg unlock:
412703b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
412803b555e1SJohan Hedberg }
412903b555e1SJohan Hedberg 
41306039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
413103b555e1SJohan Hedberg {
413203b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
413303b555e1SJohan Hedberg 	struct hci_conn *conn;
413403b555e1SJohan Hedberg 
413503b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
413603b555e1SJohan Hedberg 
413703b555e1SJohan Hedberg 	hci_dev_lock(hdev);
413803b555e1SJohan Hedberg 
413903b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
414003b555e1SJohan Hedberg 	if (!conn)
414103b555e1SJohan Hedberg 		goto unlock;
414203b555e1SJohan Hedberg 
414303b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
414403b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
414503b555e1SJohan Hedberg 
414603b555e1SJohan Hedberg unlock:
41470493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
41480493684eSMarcel Holtmann }
41490493684eSMarcel Holtmann 
41506039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
4151a5c29683SJohan Hedberg 					 struct sk_buff *skb)
4152a5c29683SJohan Hedberg {
4153a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
415455bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
41557a828908SJohan Hedberg 	struct hci_conn *conn;
4156a5c29683SJohan Hedberg 
4157a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
4158a5c29683SJohan Hedberg 
4159a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
4160a5c29683SJohan Hedberg 
4161d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
41627a828908SJohan Hedberg 		goto unlock;
41637a828908SJohan Hedberg 
41647a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
41657a828908SJohan Hedberg 	if (!conn)
41667a828908SJohan Hedberg 		goto unlock;
41677a828908SJohan Hedberg 
41687a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
41697a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
41707a828908SJohan Hedberg 
41717a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
41726c53823aSJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
41736c53823aSJohan Hedberg 	 * request. We check the security level here since it doesn't
41746c53823aSJohan Hedberg 	 * necessarily match conn->auth_type.
41756fd6b915SMikel Astiz 	 */
41766c53823aSJohan Hedberg 	if (conn->pending_sec_level > BT_SECURITY_MEDIUM &&
41776c53823aSJohan Hedberg 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
41787a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
41797a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
41807a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
41817a828908SJohan Hedberg 		goto unlock;
41827a828908SJohan Hedberg 	}
41837a828908SJohan Hedberg 
41847a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
4185a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
4186a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
418755bc1a37SJohan Hedberg 
418855bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
418955bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
4190ba15a58bSJohan Hedberg 		 * confirm_hint set to 1). The exception is if neither
419102f3e254SJohan Hedberg 		 * side had MITM or if the local IO capability is
419202f3e254SJohan Hedberg 		 * NoInputNoOutput, in which case we do auto-accept
4193ba15a58bSJohan Hedberg 		 */
4194ba15a58bSJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
419502f3e254SJohan Hedberg 		    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
4196ba15a58bSJohan Hedberg 		    (loc_mitm || rem_mitm)) {
419755bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
419855bc1a37SJohan Hedberg 			confirm_hint = 1;
419955bc1a37SJohan Hedberg 			goto confirm;
420055bc1a37SJohan Hedberg 		}
420155bc1a37SJohan Hedberg 
42029f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
42039f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
42049f61656aSJohan Hedberg 
42059f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
42069f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
42077bc18d9dSJohan Hedberg 			queue_delayed_work(conn->hdev->workqueue,
42087bc18d9dSJohan Hedberg 					   &conn->auto_accept_work, delay);
42099f61656aSJohan Hedberg 			goto unlock;
42109f61656aSJohan Hedberg 		}
42119f61656aSJohan Hedberg 
42127a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
42137a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
42147a828908SJohan Hedberg 		goto unlock;
42157a828908SJohan Hedberg 	}
42167a828908SJohan Hedberg 
421755bc1a37SJohan Hedberg confirm:
421839adbffeSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0,
421939adbffeSJohan Hedberg 				  le32_to_cpu(ev->passkey), confirm_hint);
4220a5c29683SJohan Hedberg 
42217a828908SJohan Hedberg unlock:
4222a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
4223a5c29683SJohan Hedberg }
4224a5c29683SJohan Hedberg 
42256039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
42261143d458SBrian Gix 					 struct sk_buff *skb)
42271143d458SBrian Gix {
42281143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
42291143d458SBrian Gix 
42301143d458SBrian Gix 	BT_DBG("%s", hdev->name);
42311143d458SBrian Gix 
4232d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
4233272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
42341143d458SBrian Gix }
42351143d458SBrian Gix 
423692a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
423792a25256SJohan Hedberg 					struct sk_buff *skb)
423892a25256SJohan Hedberg {
423992a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
424092a25256SJohan Hedberg 	struct hci_conn *conn;
424192a25256SJohan Hedberg 
424292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
424392a25256SJohan Hedberg 
424492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
424592a25256SJohan Hedberg 	if (!conn)
424692a25256SJohan Hedberg 		return;
424792a25256SJohan Hedberg 
424892a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
424992a25256SJohan Hedberg 	conn->passkey_entered = 0;
425092a25256SJohan Hedberg 
4251d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
425292a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
425392a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
425492a25256SJohan Hedberg 					 conn->passkey_entered);
425592a25256SJohan Hedberg }
425692a25256SJohan Hedberg 
425792a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
425892a25256SJohan Hedberg {
425992a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
426092a25256SJohan Hedberg 	struct hci_conn *conn;
426192a25256SJohan Hedberg 
426292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
426392a25256SJohan Hedberg 
426492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
426592a25256SJohan Hedberg 	if (!conn)
426692a25256SJohan Hedberg 		return;
426792a25256SJohan Hedberg 
426892a25256SJohan Hedberg 	switch (ev->type) {
426992a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
427092a25256SJohan Hedberg 		conn->passkey_entered = 0;
427192a25256SJohan Hedberg 		return;
427292a25256SJohan Hedberg 
427392a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
427492a25256SJohan Hedberg 		conn->passkey_entered++;
427592a25256SJohan Hedberg 		break;
427692a25256SJohan Hedberg 
427792a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
427892a25256SJohan Hedberg 		conn->passkey_entered--;
427992a25256SJohan Hedberg 		break;
428092a25256SJohan Hedberg 
428192a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
428292a25256SJohan Hedberg 		conn->passkey_entered = 0;
428392a25256SJohan Hedberg 		break;
428492a25256SJohan Hedberg 
428592a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
428692a25256SJohan Hedberg 		return;
428792a25256SJohan Hedberg 	}
428892a25256SJohan Hedberg 
4289d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT))
429092a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
429192a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
429292a25256SJohan Hedberg 					 conn->passkey_entered);
429392a25256SJohan Hedberg }
429492a25256SJohan Hedberg 
42956039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
4296807deac2SGustavo Padovan 					 struct sk_buff *skb)
42970493684eSMarcel Holtmann {
42980493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
42990493684eSMarcel Holtmann 	struct hci_conn *conn;
43000493684eSMarcel Holtmann 
43010493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
43020493684eSMarcel Holtmann 
43030493684eSMarcel Holtmann 	hci_dev_lock(hdev);
43040493684eSMarcel Holtmann 
43050493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
43062a611692SJohan Hedberg 	if (!conn)
43072a611692SJohan Hedberg 		goto unlock;
43082a611692SJohan Hedberg 
4309c1d4fa7aSJohan Hedberg 	/* Reset the authentication requirement to unknown */
4310c1d4fa7aSJohan Hedberg 	conn->remote_auth = 0xff;
4311c1d4fa7aSJohan Hedberg 
43122a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
43132a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
43142a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
43152a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
43162a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
4317fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
4318e1e930f5SJohan Hedberg 		mgmt_auth_failed(conn, ev->status);
43192a611692SJohan Hedberg 
432076a68ba0SDavid Herrmann 	hci_conn_drop(conn);
43210493684eSMarcel Holtmann 
43222a611692SJohan Hedberg unlock:
43230493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
43240493684eSMarcel Holtmann }
43250493684eSMarcel Holtmann 
43266039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
4327807deac2SGustavo Padovan 					 struct sk_buff *skb)
432841a96212SMarcel Holtmann {
432941a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
433041a96212SMarcel Holtmann 	struct inquiry_entry *ie;
4331cad718edSJohan Hedberg 	struct hci_conn *conn;
433241a96212SMarcel Holtmann 
433341a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
433441a96212SMarcel Holtmann 
433541a96212SMarcel Holtmann 	hci_dev_lock(hdev);
433641a96212SMarcel Holtmann 
4337cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
4338cad718edSJohan Hedberg 	if (conn)
4339cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
4340cad718edSJohan Hedberg 
4341cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
4342cc11b9c1SAndrei Emeltchenko 	if (ie)
434302b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
434441a96212SMarcel Holtmann 
434541a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
434641a96212SMarcel Holtmann }
434741a96212SMarcel Holtmann 
43486039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
43492763eda6SSzymon Janc 					    struct sk_buff *skb)
43502763eda6SSzymon Janc {
43512763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
43522763eda6SSzymon Janc 	struct oob_data *data;
43532763eda6SSzymon Janc 
43542763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
43552763eda6SSzymon Janc 
43562763eda6SSzymon Janc 	hci_dev_lock(hdev);
43572763eda6SSzymon Janc 
4358d7a5a11dSMarcel Holtmann 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
4359e1ba1f15SSzymon Janc 		goto unlock;
4360e1ba1f15SSzymon Janc 
43616928a924SJohan Hedberg 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR);
43626665d057SMarcel Holtmann 	if (!data) {
43636665d057SMarcel Holtmann 		struct hci_cp_remote_oob_data_neg_reply cp;
43646665d057SMarcel Holtmann 
43656665d057SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
43666665d057SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
43676665d057SMarcel Holtmann 			     sizeof(cp), &cp);
43686665d057SMarcel Holtmann 		goto unlock;
43696665d057SMarcel Holtmann 	}
43706665d057SMarcel Holtmann 
4371710f11c0SJohan Hedberg 	if (bredr_sc_enabled(hdev)) {
4372519ca9d0SMarcel Holtmann 		struct hci_cp_remote_oob_ext_data_reply cp;
4373519ca9d0SMarcel Holtmann 
4374519ca9d0SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
4375d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
43766665d057SMarcel Holtmann 			memset(cp.hash192, 0, sizeof(cp.hash192));
43776665d057SMarcel Holtmann 			memset(cp.rand192, 0, sizeof(cp.rand192));
43786665d057SMarcel Holtmann 		} else {
4379519ca9d0SMarcel Holtmann 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
438038da1703SJohan Hedberg 			memcpy(cp.rand192, data->rand192, sizeof(cp.rand192));
43816665d057SMarcel Holtmann 		}
4382519ca9d0SMarcel Holtmann 		memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
438338da1703SJohan Hedberg 		memcpy(cp.rand256, data->rand256, sizeof(cp.rand256));
4384519ca9d0SMarcel Holtmann 
4385519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
4386519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
4387519ca9d0SMarcel Holtmann 	} else {
43882763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
43892763eda6SSzymon Janc 
43902763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
4391519ca9d0SMarcel Holtmann 		memcpy(cp.hash, data->hash192, sizeof(cp.hash));
439238da1703SJohan Hedberg 		memcpy(cp.rand, data->rand192, sizeof(cp.rand));
43932763eda6SSzymon Janc 
4394519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
4395519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
4396519ca9d0SMarcel Holtmann 	}
43972763eda6SSzymon Janc 
4398e1ba1f15SSzymon Janc unlock:
43992763eda6SSzymon Janc 	hci_dev_unlock(hdev);
44002763eda6SSzymon Janc }
44012763eda6SSzymon Janc 
4402d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
4403d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
4404d5e91192SAndrei Emeltchenko {
4405d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
4406d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
4407d5e91192SAndrei Emeltchenko 
4408d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
4409d5e91192SAndrei Emeltchenko 	       ev->status);
4410d5e91192SAndrei Emeltchenko 
4411d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
4412d5e91192SAndrei Emeltchenko 
4413d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
4414d5e91192SAndrei Emeltchenko 	if (!hcon) {
4415d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
4416d5e91192SAndrei Emeltchenko 		return;
4417d5e91192SAndrei Emeltchenko 	}
4418d5e91192SAndrei Emeltchenko 
4419d5e91192SAndrei Emeltchenko 	if (ev->status) {
4420d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
4421d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
4422d5e91192SAndrei Emeltchenko 		return;
4423d5e91192SAndrei Emeltchenko 	}
4424d5e91192SAndrei Emeltchenko 
4425d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
4426d5e91192SAndrei Emeltchenko 
4427d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
4428d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
4429d5e91192SAndrei Emeltchenko 
4430d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
4431d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
443276a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
4433d5e91192SAndrei Emeltchenko 
443423b9ceb7SMarcel Holtmann 	hci_debugfs_create_conn(hcon);
4435d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
4436d5e91192SAndrei Emeltchenko 
4437cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
4438cf70ff22SAndrei Emeltchenko 
4439d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
4440d5e91192SAndrei Emeltchenko }
4441d5e91192SAndrei Emeltchenko 
444227695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
444327695fb4SAndrei Emeltchenko {
444427695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
444527695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
444627695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
444727695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
444827695fb4SAndrei Emeltchenko 
444927695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
445027695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
445127695fb4SAndrei Emeltchenko 	       ev->status);
445227695fb4SAndrei Emeltchenko 
445327695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
445427695fb4SAndrei Emeltchenko 	if (!hcon)
445527695fb4SAndrei Emeltchenko 		return;
445627695fb4SAndrei Emeltchenko 
445727695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
445827695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
445927695fb4SAndrei Emeltchenko 	if (!hchan)
446027695fb4SAndrei Emeltchenko 		return;
446127695fb4SAndrei Emeltchenko 
446227695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
446327695fb4SAndrei Emeltchenko 
446427695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
446527695fb4SAndrei Emeltchenko 
446627695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
446727695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
446827695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
446927695fb4SAndrei Emeltchenko 
447027695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
447127695fb4SAndrei Emeltchenko 
447227695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
447327695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
447427695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
447527695fb4SAndrei Emeltchenko 
447627695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
447727695fb4SAndrei Emeltchenko 	}
447827695fb4SAndrei Emeltchenko }
447927695fb4SAndrei Emeltchenko 
4480606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
4481606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
4482606e2a10SAndrei Emeltchenko {
4483606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
4484606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
4485606e2a10SAndrei Emeltchenko 
4486606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
4487606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
4488606e2a10SAndrei Emeltchenko 
4489606e2a10SAndrei Emeltchenko 	if (ev->status)
4490606e2a10SAndrei Emeltchenko 		return;
4491606e2a10SAndrei Emeltchenko 
4492606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
4493606e2a10SAndrei Emeltchenko 
4494606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
4495606e2a10SAndrei Emeltchenko 	if (!hchan)
4496606e2a10SAndrei Emeltchenko 		goto unlock;
4497606e2a10SAndrei Emeltchenko 
4498606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
4499606e2a10SAndrei Emeltchenko 
4500606e2a10SAndrei Emeltchenko unlock:
4501606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
4502606e2a10SAndrei Emeltchenko }
4503606e2a10SAndrei Emeltchenko 
45049eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
45059eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
45069eef6b3aSAndrei Emeltchenko {
45079eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
45089eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
45099eef6b3aSAndrei Emeltchenko 
45109eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
45119eef6b3aSAndrei Emeltchenko 
45129eef6b3aSAndrei Emeltchenko 	if (ev->status)
45139eef6b3aSAndrei Emeltchenko 		return;
45149eef6b3aSAndrei Emeltchenko 
45159eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
45169eef6b3aSAndrei Emeltchenko 
45179eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
45189eef6b3aSAndrei Emeltchenko 	if (hcon) {
45199eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
45209eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
45219eef6b3aSAndrei Emeltchenko 	}
45229eef6b3aSAndrei Emeltchenko 
45239eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
45249eef6b3aSAndrei Emeltchenko }
45259eef6b3aSAndrei Emeltchenko 
45266039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
4527fcd89c09SVille Tervo {
4528fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
4529912b42efSJohan Hedberg 	struct hci_conn_params *params;
4530fcd89c09SVille Tervo 	struct hci_conn *conn;
453168d6f6deSJohan Hedberg 	struct smp_irk *irk;
4532837d502eSJohan Hedberg 	u8 addr_type;
4533fcd89c09SVille Tervo 
45349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
4535fcd89c09SVille Tervo 
4536fcd89c09SVille Tervo 	hci_dev_lock(hdev);
4537fcd89c09SVille Tervo 
4538fbd96c15SJohan Hedberg 	/* All controllers implicitly stop advertising in the event of a
4539fbd96c15SJohan Hedberg 	 * connection, so ensure that the state bit is cleared.
4540fbd96c15SJohan Hedberg 	 */
4541a358dc11SMarcel Holtmann 	hci_dev_clear_flag(hdev, HCI_LE_ADV);
4542fbd96c15SJohan Hedberg 
45434f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
4544b62f328bSVille Tervo 	if (!conn) {
4545a5c4e309SJohan Hedberg 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr, ev->role);
4546b62f328bSVille Tervo 		if (!conn) {
4547b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
4548230fd16aSAndre Guedes 			goto unlock;
4549b62f328bSVille Tervo 		}
455029b7988aSAndre Guedes 
455129b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
4552b9b343d2SAndre Guedes 
4553cb1d68f7SJohan Hedberg 		/* If we didn't have a hci_conn object previously
4554cb1d68f7SJohan Hedberg 		 * but we're in master role this must be something
4555cb1d68f7SJohan Hedberg 		 * initiated using a white list. Since white list based
4556cb1d68f7SJohan Hedberg 		 * connections are not "first class citizens" we don't
4557cb1d68f7SJohan Hedberg 		 * have full tracking of them. Therefore, we go ahead
4558cb1d68f7SJohan Hedberg 		 * with a "best effort" approach of determining the
4559cb1d68f7SJohan Hedberg 		 * initiator address based on the HCI_PRIVACY flag.
4560cb1d68f7SJohan Hedberg 		 */
4561cb1d68f7SJohan Hedberg 		if (conn->out) {
4562cb1d68f7SJohan Hedberg 			conn->resp_addr_type = ev->bdaddr_type;
4563cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &ev->bdaddr);
4564d7a5a11dSMarcel Holtmann 			if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
4565cb1d68f7SJohan Hedberg 				conn->init_addr_type = ADDR_LE_DEV_RANDOM;
4566cb1d68f7SJohan Hedberg 				bacpy(&conn->init_addr, &hdev->rpa);
4567cb1d68f7SJohan Hedberg 			} else {
4568cb1d68f7SJohan Hedberg 				hci_copy_identity_address(hdev,
4569cb1d68f7SJohan Hedberg 							  &conn->init_addr,
4570cb1d68f7SJohan Hedberg 							  &conn->init_addr_type);
4571cb1d68f7SJohan Hedberg 			}
457280c24ab8SJohan Hedberg 		}
4573cb1d68f7SJohan Hedberg 	} else {
457480c24ab8SJohan Hedberg 		cancel_delayed_work(&conn->le_conn_timeout);
457580c24ab8SJohan Hedberg 	}
457680c24ab8SJohan Hedberg 
457780c24ab8SJohan Hedberg 	if (!conn->out) {
4578cb1d68f7SJohan Hedberg 		/* Set the responder (our side) address type based on
4579cb1d68f7SJohan Hedberg 		 * the advertising address type.
4580cb1d68f7SJohan Hedberg 		 */
4581cb1d68f7SJohan Hedberg 		conn->resp_addr_type = hdev->adv_addr_type;
4582cb1d68f7SJohan Hedberg 		if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM)
4583cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &hdev->random_addr);
4584cb1d68f7SJohan Hedberg 		else
4585cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &hdev->bdaddr);
4586cb1d68f7SJohan Hedberg 
4587cb1d68f7SJohan Hedberg 		conn->init_addr_type = ev->bdaddr_type;
4588cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &ev->bdaddr);
4589a720d735SMarcel Holtmann 
4590a720d735SMarcel Holtmann 		/* For incoming connections, set the default minimum
4591a720d735SMarcel Holtmann 		 * and maximum connection interval. They will be used
4592a720d735SMarcel Holtmann 		 * to check if the parameters are in range and if not
4593a720d735SMarcel Holtmann 		 * trigger the connection update procedure.
4594a720d735SMarcel Holtmann 		 */
4595a720d735SMarcel Holtmann 		conn->le_conn_min_interval = hdev->le_conn_min_interval;
4596a720d735SMarcel Holtmann 		conn->le_conn_max_interval = hdev->le_conn_max_interval;
4597cb1d68f7SJohan Hedberg 	}
45987be2edbbSJohan Hedberg 
4599edb4b466SMarcel Holtmann 	/* Lookup the identity address from the stored connection
4600edb4b466SMarcel Holtmann 	 * address and address type.
4601edb4b466SMarcel Holtmann 	 *
4602edb4b466SMarcel Holtmann 	 * When establishing connections to an identity address, the
4603edb4b466SMarcel Holtmann 	 * connection procedure will store the resolvable random
4604edb4b466SMarcel Holtmann 	 * address first. Now if it can be converted back into the
4605edb4b466SMarcel Holtmann 	 * identity address, start using the identity address from
4606edb4b466SMarcel Holtmann 	 * now on.
4607edb4b466SMarcel Holtmann 	 */
4608edb4b466SMarcel Holtmann 	irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
460968d6f6deSJohan Hedberg 	if (irk) {
461068d6f6deSJohan Hedberg 		bacpy(&conn->dst, &irk->bdaddr);
461168d6f6deSJohan Hedberg 		conn->dst_type = irk->addr_type;
461268d6f6deSJohan Hedberg 	}
461368d6f6deSJohan Hedberg 
46142d3c2260SJohan Hedberg 	if (ev->status) {
46152d3c2260SJohan Hedberg 		hci_le_conn_failed(conn, ev->status);
4616837d502eSJohan Hedberg 		goto unlock;
4617837d502eSJohan Hedberg 	}
4618837d502eSJohan Hedberg 
461908853f18SJohan Hedberg 	if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
462008853f18SJohan Hedberg 		addr_type = BDADDR_LE_PUBLIC;
462108853f18SJohan Hedberg 	else
462208853f18SJohan Hedberg 		addr_type = BDADDR_LE_RANDOM;
462308853f18SJohan Hedberg 
46242d3c2260SJohan Hedberg 	/* Drop the connection if the device is blocked */
46252d3c2260SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) {
46262d3c2260SJohan Hedberg 		hci_conn_drop(conn);
4627cd17decbSAndre Guedes 		goto unlock;
4628cd17decbSAndre Guedes 	}
4629cd17decbSAndre Guedes 
4630b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
463148ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
463283bc71b4SVinicius Costa Gomes 
46337b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
4634fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
46350fe29fd1SMarcel Holtmann 	conn->state = BT_CONFIG;
4636fcd89c09SVille Tervo 
4637e04fde60SMarcel Holtmann 	conn->le_conn_interval = le16_to_cpu(ev->interval);
4638e04fde60SMarcel Holtmann 	conn->le_conn_latency = le16_to_cpu(ev->latency);
4639e04fde60SMarcel Holtmann 	conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
4640e04fde60SMarcel Holtmann 
464123b9ceb7SMarcel Holtmann 	hci_debugfs_create_conn(conn);
4642fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
4643fcd89c09SVille Tervo 
46440fe29fd1SMarcel Holtmann 	if (!ev->status) {
46450fe29fd1SMarcel Holtmann 		/* The remote features procedure is defined for master
46460fe29fd1SMarcel Holtmann 		 * role only. So only in case of an initiated connection
46470fe29fd1SMarcel Holtmann 		 * request the remote features.
46480fe29fd1SMarcel Holtmann 		 *
46490fe29fd1SMarcel Holtmann 		 * If the local controller supports slave-initiated features
46500fe29fd1SMarcel Holtmann 		 * exchange, then requesting the remote features in slave
46510fe29fd1SMarcel Holtmann 		 * role is possible. Otherwise just transition into the
46520fe29fd1SMarcel Holtmann 		 * connected state without requesting the remote features.
46530fe29fd1SMarcel Holtmann 		 */
46540fe29fd1SMarcel Holtmann 		if (conn->out ||
46550fe29fd1SMarcel Holtmann 		    (hdev->le_features[0] & HCI_LE_SLAVE_FEATURES)) {
46560fe29fd1SMarcel Holtmann 			struct hci_cp_le_read_remote_features cp;
46570fe29fd1SMarcel Holtmann 
46580fe29fd1SMarcel Holtmann 			cp.handle = __cpu_to_le16(conn->handle);
46590fe29fd1SMarcel Holtmann 
46600fe29fd1SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_LE_READ_REMOTE_FEATURES,
46610fe29fd1SMarcel Holtmann 				     sizeof(cp), &cp);
46620fe29fd1SMarcel Holtmann 
46630fe29fd1SMarcel Holtmann 			hci_conn_hold(conn);
46640fe29fd1SMarcel Holtmann 		} else {
46650fe29fd1SMarcel Holtmann 			conn->state = BT_CONNECTED;
4666539c496dSJohan Hedberg 			hci_connect_cfm(conn, ev->status);
46670fe29fd1SMarcel Holtmann 		}
46680fe29fd1SMarcel Holtmann 	} else {
46690fe29fd1SMarcel Holtmann 		hci_connect_cfm(conn, ev->status);
46700fe29fd1SMarcel Holtmann 	}
4671fcd89c09SVille Tervo 
46725477610fSJohan Hedberg 	params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
46735477610fSJohan Hedberg 					   conn->dst_type);
4674f161dd41SJohan Hedberg 	if (params) {
467595305baaSJohan Hedberg 		list_del_init(&params->action);
4676f161dd41SJohan Hedberg 		if (params->conn) {
4677f161dd41SJohan Hedberg 			hci_conn_drop(params->conn);
4678f8aaf9b6SJohan Hedberg 			hci_conn_put(params->conn);
4679f161dd41SJohan Hedberg 			params->conn = NULL;
4680f161dd41SJohan Hedberg 		}
4681f161dd41SJohan Hedberg 	}
4682a4790dbdSAndre Guedes 
4683fcd89c09SVille Tervo unlock:
4684223683a5SJohan Hedberg 	hci_update_background_scan(hdev);
4685fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
4686fcd89c09SVille Tervo }
4687fcd89c09SVille Tervo 
46881855d92dSMarcel Holtmann static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
46891855d92dSMarcel Holtmann 					    struct sk_buff *skb)
46901855d92dSMarcel Holtmann {
46911855d92dSMarcel Holtmann 	struct hci_ev_le_conn_update_complete *ev = (void *) skb->data;
46921855d92dSMarcel Holtmann 	struct hci_conn *conn;
46931855d92dSMarcel Holtmann 
46941855d92dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
46951855d92dSMarcel Holtmann 
46961855d92dSMarcel Holtmann 	if (ev->status)
46971855d92dSMarcel Holtmann 		return;
46981855d92dSMarcel Holtmann 
46991855d92dSMarcel Holtmann 	hci_dev_lock(hdev);
47001855d92dSMarcel Holtmann 
47011855d92dSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
47021855d92dSMarcel Holtmann 	if (conn) {
47031855d92dSMarcel Holtmann 		conn->le_conn_interval = le16_to_cpu(ev->interval);
47041855d92dSMarcel Holtmann 		conn->le_conn_latency = le16_to_cpu(ev->latency);
47051855d92dSMarcel Holtmann 		conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
47061855d92dSMarcel Holtmann 	}
47071855d92dSMarcel Holtmann 
47081855d92dSMarcel Holtmann 	hci_dev_unlock(hdev);
47091855d92dSMarcel Holtmann }
47101855d92dSMarcel Holtmann 
4711a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */
4712fd45ada9SAlfonso Acosta static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
4713fd45ada9SAlfonso Acosta 					      bdaddr_t *addr,
47141c1abcabSJohan Hedberg 					      u8 addr_type, u8 adv_type)
4715a4790dbdSAndre Guedes {
4716a4790dbdSAndre Guedes 	struct hci_conn *conn;
47174b9e7e75SMarcel Holtmann 	struct hci_conn_params *params;
4718a4790dbdSAndre Guedes 
47191c1abcabSJohan Hedberg 	/* If the event is not connectable don't proceed further */
47201c1abcabSJohan Hedberg 	if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND)
4721fd45ada9SAlfonso Acosta 		return NULL;
47221c1abcabSJohan Hedberg 
47231c1abcabSJohan Hedberg 	/* Ignore if the device is blocked */
4724dcc36c16SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type))
4725fd45ada9SAlfonso Acosta 		return NULL;
47261c1abcabSJohan Hedberg 
4727f99353cfSJohan Hedberg 	/* Most controller will fail if we try to create new connections
4728f99353cfSJohan Hedberg 	 * while we have an existing one in slave role.
4729f99353cfSJohan Hedberg 	 */
4730f99353cfSJohan Hedberg 	if (hdev->conn_hash.le_num_slave > 0)
4731fd45ada9SAlfonso Acosta 		return NULL;
4732f99353cfSJohan Hedberg 
47331c1abcabSJohan Hedberg 	/* If we're not connectable only connect devices that we have in
47341c1abcabSJohan Hedberg 	 * our pend_le_conns list.
47351c1abcabSJohan Hedberg 	 */
47364b9e7e75SMarcel Holtmann 	params = hci_pend_le_action_lookup(&hdev->pend_le_conns,
47374b9e7e75SMarcel Holtmann 					   addr, addr_type);
47384b9e7e75SMarcel Holtmann 	if (!params)
4739fd45ada9SAlfonso Acosta 		return NULL;
4740a4790dbdSAndre Guedes 
47414b9e7e75SMarcel Holtmann 	switch (params->auto_connect) {
47424b9e7e75SMarcel Holtmann 	case HCI_AUTO_CONN_DIRECT:
47434b9e7e75SMarcel Holtmann 		/* Only devices advertising with ADV_DIRECT_IND are
47444b9e7e75SMarcel Holtmann 		 * triggering a connection attempt. This is allowing
47454b9e7e75SMarcel Holtmann 		 * incoming connections from slave devices.
47464b9e7e75SMarcel Holtmann 		 */
47474b9e7e75SMarcel Holtmann 		if (adv_type != LE_ADV_DIRECT_IND)
4748fd45ada9SAlfonso Acosta 			return NULL;
47494b9e7e75SMarcel Holtmann 		break;
47504b9e7e75SMarcel Holtmann 	case HCI_AUTO_CONN_ALWAYS:
47514b9e7e75SMarcel Holtmann 		/* Devices advertising with ADV_IND or ADV_DIRECT_IND
47524b9e7e75SMarcel Holtmann 		 * are triggering a connection attempt. This means
47534b9e7e75SMarcel Holtmann 		 * that incoming connectioms from slave device are
47544b9e7e75SMarcel Holtmann 		 * accepted and also outgoing connections to slave
47554b9e7e75SMarcel Holtmann 		 * devices are established when found.
47564b9e7e75SMarcel Holtmann 		 */
47574b9e7e75SMarcel Holtmann 		break;
47584b9e7e75SMarcel Holtmann 	default:
4759fd45ada9SAlfonso Acosta 		return NULL;
47604b9e7e75SMarcel Holtmann 	}
47614b9e7e75SMarcel Holtmann 
4762a4790dbdSAndre Guedes 	conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
4763e804d25dSJohan Hedberg 			      HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
4764f161dd41SJohan Hedberg 	if (!IS_ERR(conn)) {
4765f161dd41SJohan Hedberg 		/* Store the pointer since we don't really have any
4766f161dd41SJohan Hedberg 		 * other owner of the object besides the params that
4767f161dd41SJohan Hedberg 		 * triggered it. This way we can abort the connection if
4768f161dd41SJohan Hedberg 		 * the parameters get removed and keep the reference
4769f161dd41SJohan Hedberg 		 * count consistent once the connection is established.
4770f161dd41SJohan Hedberg 		 */
4771f8aaf9b6SJohan Hedberg 		params->conn = hci_conn_get(conn);
4772fd45ada9SAlfonso Acosta 		return conn;
4773f161dd41SJohan Hedberg 	}
4774a4790dbdSAndre Guedes 
4775a4790dbdSAndre Guedes 	switch (PTR_ERR(conn)) {
4776a4790dbdSAndre Guedes 	case -EBUSY:
4777a4790dbdSAndre Guedes 		/* If hci_connect() returns -EBUSY it means there is already
4778a4790dbdSAndre Guedes 		 * an LE connection attempt going on. Since controllers don't
4779a4790dbdSAndre Guedes 		 * support more than one connection attempt at the time, we
4780a4790dbdSAndre Guedes 		 * don't consider this an error case.
4781a4790dbdSAndre Guedes 		 */
4782a4790dbdSAndre Guedes 		break;
4783a4790dbdSAndre Guedes 	default:
4784a4790dbdSAndre Guedes 		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
4785fd45ada9SAlfonso Acosta 		return NULL;
4786a4790dbdSAndre Guedes 	}
4787fd45ada9SAlfonso Acosta 
4788fd45ada9SAlfonso Acosta 	return NULL;
4789a4790dbdSAndre Guedes }
4790a4790dbdSAndre Guedes 
47914af605d8SJohan Hedberg static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
47922f010b55SMarcel Holtmann 			       u8 bdaddr_type, bdaddr_t *direct_addr,
47932f010b55SMarcel Holtmann 			       u8 direct_addr_type, s8 rssi, u8 *data, u8 len)
47944af605d8SJohan Hedberg {
4795b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
47961c1abcabSJohan Hedberg 	struct smp_irk *irk;
4797fd45ada9SAlfonso Acosta 	struct hci_conn *conn;
4798474ee066SJohan Hedberg 	bool match;
4799c70a7e4cSMarcel Holtmann 	u32 flags;
4800b9a6328fSJohan Hedberg 
48012f010b55SMarcel Holtmann 	/* If the direct address is present, then this report is from
48022f010b55SMarcel Holtmann 	 * a LE Direct Advertising Report event. In that case it is
48032f010b55SMarcel Holtmann 	 * important to see if the address is matching the local
48042f010b55SMarcel Holtmann 	 * controller address.
48052f010b55SMarcel Holtmann 	 */
48062f010b55SMarcel Holtmann 	if (direct_addr) {
48072f010b55SMarcel Holtmann 		/* Only resolvable random addresses are valid for these
48082f010b55SMarcel Holtmann 		 * kind of reports and others can be ignored.
48092f010b55SMarcel Holtmann 		 */
48102f010b55SMarcel Holtmann 		if (!hci_bdaddr_is_rpa(direct_addr, direct_addr_type))
48112f010b55SMarcel Holtmann 			return;
48122f010b55SMarcel Holtmann 
48132f010b55SMarcel Holtmann 		/* If the controller is not using resolvable random
48142f010b55SMarcel Holtmann 		 * addresses, then this report can be ignored.
48152f010b55SMarcel Holtmann 		 */
4816d7a5a11dSMarcel Holtmann 		if (!hci_dev_test_flag(hdev, HCI_PRIVACY))
48172f010b55SMarcel Holtmann 			return;
48182f010b55SMarcel Holtmann 
48192f010b55SMarcel Holtmann 		/* If the local IRK of the controller does not match
48202f010b55SMarcel Holtmann 		 * with the resolvable random address provided, then
48212f010b55SMarcel Holtmann 		 * this report can be ignored.
48222f010b55SMarcel Holtmann 		 */
48232f010b55SMarcel Holtmann 		if (!smp_irk_matches(hdev, hdev->irk, direct_addr))
48242f010b55SMarcel Holtmann 			return;
48252f010b55SMarcel Holtmann 	}
48262f010b55SMarcel Holtmann 
4827435a13d8SJohan Hedberg 	/* Check if we need to convert to identity address */
4828435a13d8SJohan Hedberg 	irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
4829435a13d8SJohan Hedberg 	if (irk) {
4830435a13d8SJohan Hedberg 		bdaddr = &irk->bdaddr;
4831435a13d8SJohan Hedberg 		bdaddr_type = irk->addr_type;
4832435a13d8SJohan Hedberg 	}
4833435a13d8SJohan Hedberg 
48341c1abcabSJohan Hedberg 	/* Check if we have been requested to connect to this device */
4835fd45ada9SAlfonso Acosta 	conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type);
4836fd45ada9SAlfonso Acosta 	if (conn && type == LE_ADV_IND) {
4837fd45ada9SAlfonso Acosta 		/* Store report for later inclusion by
4838fd45ada9SAlfonso Acosta 		 * mgmt_device_connected
4839fd45ada9SAlfonso Acosta 		 */
4840fd45ada9SAlfonso Acosta 		memcpy(conn->le_adv_data, data, len);
4841fd45ada9SAlfonso Acosta 		conn->le_adv_data_len = len;
4842fd45ada9SAlfonso Acosta 	}
484399a6768eSJohan Hedberg 
48441c1abcabSJohan Hedberg 	/* Passive scanning shouldn't trigger any device found events,
48451c1abcabSJohan Hedberg 	 * except for devices marked as CONN_REPORT for which we do send
48461c1abcabSJohan Hedberg 	 * device found events.
48471c1abcabSJohan Hedberg 	 */
48481c1abcabSJohan Hedberg 	if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
48490d2bf134SJohan Hedberg 		if (type == LE_ADV_DIRECT_IND)
48500d2bf134SJohan Hedberg 			return;
48510d2bf134SJohan Hedberg 
48523a19b6feSJohan Hedberg 		if (!hci_pend_le_action_lookup(&hdev->pend_le_reports,
48533a19b6feSJohan Hedberg 					       bdaddr, bdaddr_type))
48540d2bf134SJohan Hedberg 			return;
48550d2bf134SJohan Hedberg 
48560d2bf134SJohan Hedberg 		if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND)
48570d2bf134SJohan Hedberg 			flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
48580d2bf134SJohan Hedberg 		else
48590d2bf134SJohan Hedberg 			flags = 0;
48600d2bf134SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
48610d2bf134SJohan Hedberg 				  rssi, flags, data, len, NULL, 0);
486297bf2e99SJohan Hedberg 		return;
4863ca5c4be7SJohan Hedberg 	}
48644af605d8SJohan Hedberg 
4865c70a7e4cSMarcel Holtmann 	/* When receiving non-connectable or scannable undirected
4866c70a7e4cSMarcel Holtmann 	 * advertising reports, this means that the remote device is
4867c70a7e4cSMarcel Holtmann 	 * not connectable and then clearly indicate this in the
4868c70a7e4cSMarcel Holtmann 	 * device found event.
4869c70a7e4cSMarcel Holtmann 	 *
4870c70a7e4cSMarcel Holtmann 	 * When receiving a scan response, then there is no way to
4871c70a7e4cSMarcel Holtmann 	 * know if the remote device is connectable or not. However
4872c70a7e4cSMarcel Holtmann 	 * since scan responses are merged with a previously seen
4873c70a7e4cSMarcel Holtmann 	 * advertising report, the flags field from that report
4874c70a7e4cSMarcel Holtmann 	 * will be used.
4875c70a7e4cSMarcel Holtmann 	 *
4876c70a7e4cSMarcel Holtmann 	 * In the really unlikely case that a controller get confused
4877c70a7e4cSMarcel Holtmann 	 * and just sends a scan response event, then it is marked as
4878c70a7e4cSMarcel Holtmann 	 * not connectable as well.
4879c70a7e4cSMarcel Holtmann 	 */
4880c70a7e4cSMarcel Holtmann 	if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND ||
4881c70a7e4cSMarcel Holtmann 	    type == LE_ADV_SCAN_RSP)
4882c70a7e4cSMarcel Holtmann 		flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
4883c70a7e4cSMarcel Holtmann 	else
4884c70a7e4cSMarcel Holtmann 		flags = 0;
4885c70a7e4cSMarcel Holtmann 
4886b9a6328fSJohan Hedberg 	/* If there's nothing pending either store the data from this
4887b9a6328fSJohan Hedberg 	 * event or send an immediate device found event if the data
4888b9a6328fSJohan Hedberg 	 * should not be stored for later.
4889b9a6328fSJohan Hedberg 	 */
4890b9a6328fSJohan Hedberg 	if (!has_pending_adv_report(hdev)) {
4891b9a6328fSJohan Hedberg 		/* If the report will trigger a SCAN_REQ store it for
4892b9a6328fSJohan Hedberg 		 * later merging.
4893b9a6328fSJohan Hedberg 		 */
4894b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
4895b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
4896c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
4897b9a6328fSJohan Hedberg 			return;
4898b9a6328fSJohan Hedberg 		}
4899b9a6328fSJohan Hedberg 
4900b9a6328fSJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
4901c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
4902b9a6328fSJohan Hedberg 		return;
4903b9a6328fSJohan Hedberg 	}
4904b9a6328fSJohan Hedberg 
4905474ee066SJohan Hedberg 	/* Check if the pending report is for the same device as the new one */
4906474ee066SJohan Hedberg 	match = (!bacmp(bdaddr, &d->last_adv_addr) &&
4907474ee066SJohan Hedberg 		 bdaddr_type == d->last_adv_addr_type);
4908474ee066SJohan Hedberg 
4909b9a6328fSJohan Hedberg 	/* If the pending data doesn't match this report or this isn't a
4910b9a6328fSJohan Hedberg 	 * scan response (e.g. we got a duplicate ADV_IND) then force
4911b9a6328fSJohan Hedberg 	 * sending of the pending data.
4912b9a6328fSJohan Hedberg 	 */
4913474ee066SJohan Hedberg 	if (type != LE_ADV_SCAN_RSP || !match) {
4914474ee066SJohan Hedberg 		/* Send out whatever is in the cache, but skip duplicates */
4915474ee066SJohan Hedberg 		if (!match)
4916b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4917ff5cd29fSJohan Hedberg 					  d->last_adv_addr_type, NULL,
4918c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
4919ff5cd29fSJohan Hedberg 					  d->last_adv_data,
4920474ee066SJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
4921b9a6328fSJohan Hedberg 
4922b9a6328fSJohan Hedberg 		/* If the new report will trigger a SCAN_REQ store it for
4923b9a6328fSJohan Hedberg 		 * later merging.
4924b9a6328fSJohan Hedberg 		 */
4925b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
4926b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
4927c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
4928b9a6328fSJohan Hedberg 			return;
4929b9a6328fSJohan Hedberg 		}
4930b9a6328fSJohan Hedberg 
4931b9a6328fSJohan Hedberg 		/* The advertising reports cannot be merged, so clear
4932b9a6328fSJohan Hedberg 		 * the pending report and send out a device found event.
4933b9a6328fSJohan Hedberg 		 */
4934b9a6328fSJohan Hedberg 		clear_pending_adv_report(hdev);
49355c5b93e4SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
4936c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
4937b9a6328fSJohan Hedberg 		return;
4938b9a6328fSJohan Hedberg 	}
4939b9a6328fSJohan Hedberg 
4940b9a6328fSJohan Hedberg 	/* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
4941b9a6328fSJohan Hedberg 	 * the new event is a SCAN_RSP. We can therefore proceed with
4942b9a6328fSJohan Hedberg 	 * sending a merged device found event.
4943b9a6328fSJohan Hedberg 	 */
4944b9a6328fSJohan Hedberg 	mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4945c70a7e4cSMarcel Holtmann 			  d->last_adv_addr_type, NULL, rssi, d->last_adv_flags,
494642bd6a56SMarcel Holtmann 			  d->last_adv_data, d->last_adv_data_len, data, len);
4947b9a6328fSJohan Hedberg 	clear_pending_adv_report(hdev);
49484af605d8SJohan Hedberg }
49494af605d8SJohan Hedberg 
49506039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
49519aa04c91SAndre Guedes {
4952e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
4953e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
49549aa04c91SAndre Guedes 
4955a4790dbdSAndre Guedes 	hci_dev_lock(hdev);
4956a4790dbdSAndre Guedes 
4957e95beb41SAndre Guedes 	while (num_reports--) {
4958e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
49594af605d8SJohan Hedberg 		s8 rssi;
4960a4790dbdSAndre Guedes 
49613c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
49624af605d8SJohan Hedberg 		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
49632f010b55SMarcel Holtmann 				   ev->bdaddr_type, NULL, 0, rssi,
49642f010b55SMarcel Holtmann 				   ev->data, ev->length);
49653c9e9195SAndre Guedes 
4966e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
49679aa04c91SAndre Guedes 	}
4968a4790dbdSAndre Guedes 
4969a4790dbdSAndre Guedes 	hci_dev_unlock(hdev);
49709aa04c91SAndre Guedes }
49719aa04c91SAndre Guedes 
49720fe29fd1SMarcel Holtmann static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
49730fe29fd1SMarcel Holtmann 					    struct sk_buff *skb)
49740fe29fd1SMarcel Holtmann {
49750fe29fd1SMarcel Holtmann 	struct hci_ev_le_remote_feat_complete *ev = (void *)skb->data;
49760fe29fd1SMarcel Holtmann 	struct hci_conn *conn;
49770fe29fd1SMarcel Holtmann 
49780fe29fd1SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
49790fe29fd1SMarcel Holtmann 
49800fe29fd1SMarcel Holtmann 	hci_dev_lock(hdev);
49810fe29fd1SMarcel Holtmann 
49820fe29fd1SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
49830fe29fd1SMarcel Holtmann 	if (conn) {
49840fe29fd1SMarcel Holtmann 		if (!ev->status)
49850fe29fd1SMarcel Holtmann 			memcpy(conn->features[0], ev->features, 8);
49860fe29fd1SMarcel Holtmann 
49870fe29fd1SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
49880fe29fd1SMarcel Holtmann 			__u8 status;
49890fe29fd1SMarcel Holtmann 
49900fe29fd1SMarcel Holtmann 			/* If the local controller supports slave-initiated
49910fe29fd1SMarcel Holtmann 			 * features exchange, but the remote controller does
49920fe29fd1SMarcel Holtmann 			 * not, then it is possible that the error code 0x1a
49930fe29fd1SMarcel Holtmann 			 * for unsupported remote feature gets returned.
49940fe29fd1SMarcel Holtmann 			 *
49950fe29fd1SMarcel Holtmann 			 * In this specific case, allow the connection to
49960fe29fd1SMarcel Holtmann 			 * transition into connected state and mark it as
49970fe29fd1SMarcel Holtmann 			 * successful.
49980fe29fd1SMarcel Holtmann 			 */
49990fe29fd1SMarcel Holtmann 			if ((hdev->le_features[0] & HCI_LE_SLAVE_FEATURES) &&
50000fe29fd1SMarcel Holtmann 			    !conn->out && ev->status == 0x1a)
50010fe29fd1SMarcel Holtmann 				status = 0x00;
50020fe29fd1SMarcel Holtmann 			else
50030fe29fd1SMarcel Holtmann 				status = ev->status;
50040fe29fd1SMarcel Holtmann 
50050fe29fd1SMarcel Holtmann 			conn->state = BT_CONNECTED;
50060fe29fd1SMarcel Holtmann 			hci_connect_cfm(conn, status);
50070fe29fd1SMarcel Holtmann 			hci_conn_drop(conn);
50080fe29fd1SMarcel Holtmann 		}
50090fe29fd1SMarcel Holtmann 	}
50100fe29fd1SMarcel Holtmann 
50110fe29fd1SMarcel Holtmann 	hci_dev_unlock(hdev);
50120fe29fd1SMarcel Holtmann }
50130fe29fd1SMarcel Holtmann 
50146039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
5015a7a595f6SVinicius Costa Gomes {
5016a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
5017a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
5018bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
5019a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
5020c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
5021a7a595f6SVinicius Costa Gomes 
50229f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
5023a7a595f6SVinicius Costa Gomes 
5024a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
5025a7a595f6SVinicius Costa Gomes 
5026a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
5027bea710feSVinicius Costa Gomes 	if (conn == NULL)
5028bea710feSVinicius Costa Gomes 		goto not_found;
5029a7a595f6SVinicius Costa Gomes 
5030f3a73d97SJohan Hedberg 	ltk = hci_find_ltk(hdev, &conn->dst, conn->dst_type, conn->role);
50315378bc56SJohan Hedberg 	if (!ltk)
5032bea710feSVinicius Costa Gomes 		goto not_found;
5033bea710feSVinicius Costa Gomes 
50345378bc56SJohan Hedberg 	if (smp_ltk_is_sc(ltk)) {
50355378bc56SJohan Hedberg 		/* With SC both EDiv and Rand are set to zero */
50365378bc56SJohan Hedberg 		if (ev->ediv || ev->rand)
50375378bc56SJohan Hedberg 			goto not_found;
50385378bc56SJohan Hedberg 	} else {
50395378bc56SJohan Hedberg 		/* For non-SC keys check that EDiv and Rand match */
50405378bc56SJohan Hedberg 		if (ev->ediv != ltk->ediv || ev->rand != ltk->rand)
50415378bc56SJohan Hedberg 			goto not_found;
50425378bc56SJohan Hedberg 	}
50435378bc56SJohan Hedberg 
50448b76ce34SJohan Hedberg 	memcpy(cp.ltk, ltk->val, ltk->enc_size);
50458b76ce34SJohan Hedberg 	memset(cp.ltk + ltk->enc_size, 0, sizeof(cp.ltk) - ltk->enc_size);
5046a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
5047c9839a11SVinicius Costa Gomes 
5048a6f7833cSJohan Hedberg 	conn->pending_sec_level = smp_ltk_sec_level(ltk);
5049a7a595f6SVinicius Costa Gomes 
505089cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
5051a7a595f6SVinicius Costa Gomes 
5052a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
5053a7a595f6SVinicius Costa Gomes 
50545981a882SClaudio Takahasi 	/* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a
50555981a882SClaudio Takahasi 	 * temporary key used to encrypt a connection following
50565981a882SClaudio Takahasi 	 * pairing. It is used during the Encrypted Session Setup to
50575981a882SClaudio Takahasi 	 * distribute the keys. Later, security can be re-established
50585981a882SClaudio Takahasi 	 * using a distributed LTK.
50595981a882SClaudio Takahasi 	 */
50602ceba539SJohan Hedberg 	if (ltk->type == SMP_STK) {
5061fe59a05fSJohan Hedberg 		set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
5062970d0f1bSJohan Hedberg 		list_del_rcu(&ltk->list);
5063970d0f1bSJohan Hedberg 		kfree_rcu(ltk, rcu);
5064fe59a05fSJohan Hedberg 	} else {
5065fe59a05fSJohan Hedberg 		clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
5066c9839a11SVinicius Costa Gomes 	}
5067c9839a11SVinicius Costa Gomes 
5068a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
5069bea710feSVinicius Costa Gomes 
5070bea710feSVinicius Costa Gomes 	return;
5071bea710feSVinicius Costa Gomes 
5072bea710feSVinicius Costa Gomes not_found:
5073bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
5074bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
5075bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
5076a7a595f6SVinicius Costa Gomes }
5077a7a595f6SVinicius Costa Gomes 
50788e75b46aSAndre Guedes static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
50798e75b46aSAndre Guedes 				      u8 reason)
50808e75b46aSAndre Guedes {
50818e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_neg_reply cp;
50828e75b46aSAndre Guedes 
50838e75b46aSAndre Guedes 	cp.handle = cpu_to_le16(handle);
50848e75b46aSAndre Guedes 	cp.reason = reason;
50858e75b46aSAndre Guedes 
50868e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp),
50878e75b46aSAndre Guedes 		     &cp);
50888e75b46aSAndre Guedes }
50898e75b46aSAndre Guedes 
50908e75b46aSAndre Guedes static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
50918e75b46aSAndre Guedes 					     struct sk_buff *skb)
50928e75b46aSAndre Guedes {
50938e75b46aSAndre Guedes 	struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data;
50948e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_reply cp;
50958e75b46aSAndre Guedes 	struct hci_conn *hcon;
50968e75b46aSAndre Guedes 	u16 handle, min, max, latency, timeout;
50978e75b46aSAndre Guedes 
50988e75b46aSAndre Guedes 	handle = le16_to_cpu(ev->handle);
50998e75b46aSAndre Guedes 	min = le16_to_cpu(ev->interval_min);
51008e75b46aSAndre Guedes 	max = le16_to_cpu(ev->interval_max);
51018e75b46aSAndre Guedes 	latency = le16_to_cpu(ev->latency);
51028e75b46aSAndre Guedes 	timeout = le16_to_cpu(ev->timeout);
51038e75b46aSAndre Guedes 
51048e75b46aSAndre Guedes 	hcon = hci_conn_hash_lookup_handle(hdev, handle);
51058e75b46aSAndre Guedes 	if (!hcon || hcon->state != BT_CONNECTED)
51068e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
51078e75b46aSAndre Guedes 						 HCI_ERROR_UNKNOWN_CONN_ID);
51088e75b46aSAndre Guedes 
51098e75b46aSAndre Guedes 	if (hci_check_conn_params(min, max, latency, timeout))
51108e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
51118e75b46aSAndre Guedes 						 HCI_ERROR_INVALID_LL_PARAMS);
51128e75b46aSAndre Guedes 
511340bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_MASTER) {
5114348d50b8SJohan Hedberg 		struct hci_conn_params *params;
5115f4869e2aSJohan Hedberg 		u8 store_hint;
5116348d50b8SJohan Hedberg 
5117348d50b8SJohan Hedberg 		hci_dev_lock(hdev);
5118348d50b8SJohan Hedberg 
5119348d50b8SJohan Hedberg 		params = hci_conn_params_lookup(hdev, &hcon->dst,
5120348d50b8SJohan Hedberg 						hcon->dst_type);
5121348d50b8SJohan Hedberg 		if (params) {
5122348d50b8SJohan Hedberg 			params->conn_min_interval = min;
5123348d50b8SJohan Hedberg 			params->conn_max_interval = max;
5124348d50b8SJohan Hedberg 			params->conn_latency = latency;
5125348d50b8SJohan Hedberg 			params->supervision_timeout = timeout;
5126f4869e2aSJohan Hedberg 			store_hint = 0x01;
5127f4869e2aSJohan Hedberg 		} else{
5128f4869e2aSJohan Hedberg 			store_hint = 0x00;
5129348d50b8SJohan Hedberg 		}
5130348d50b8SJohan Hedberg 
5131348d50b8SJohan Hedberg 		hci_dev_unlock(hdev);
5132348d50b8SJohan Hedberg 
5133f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type,
5134f4869e2aSJohan Hedberg 				    store_hint, min, max, latency, timeout);
5135348d50b8SJohan Hedberg 	}
5136ffb5a827SAndre Guedes 
51378e75b46aSAndre Guedes 	cp.handle = ev->handle;
51388e75b46aSAndre Guedes 	cp.interval_min = ev->interval_min;
51398e75b46aSAndre Guedes 	cp.interval_max = ev->interval_max;
51408e75b46aSAndre Guedes 	cp.latency = ev->latency;
51418e75b46aSAndre Guedes 	cp.timeout = ev->timeout;
51428e75b46aSAndre Guedes 	cp.min_ce_len = 0;
51438e75b46aSAndre Guedes 	cp.max_ce_len = 0;
51448e75b46aSAndre Guedes 
51458e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
51468e75b46aSAndre Guedes }
51478e75b46aSAndre Guedes 
51482f010b55SMarcel Holtmann static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
51492f010b55SMarcel Holtmann 					 struct sk_buff *skb)
51502f010b55SMarcel Holtmann {
51512f010b55SMarcel Holtmann 	u8 num_reports = skb->data[0];
51522f010b55SMarcel Holtmann 	void *ptr = &skb->data[1];
51532f010b55SMarcel Holtmann 
51542f010b55SMarcel Holtmann 	hci_dev_lock(hdev);
51552f010b55SMarcel Holtmann 
51562f010b55SMarcel Holtmann 	while (num_reports--) {
51572f010b55SMarcel Holtmann 		struct hci_ev_le_direct_adv_info *ev = ptr;
51582f010b55SMarcel Holtmann 
51592f010b55SMarcel Holtmann 		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
51602f010b55SMarcel Holtmann 				   ev->bdaddr_type, &ev->direct_addr,
51612f010b55SMarcel Holtmann 				   ev->direct_addr_type, ev->rssi, NULL, 0);
51622f010b55SMarcel Holtmann 
51632f010b55SMarcel Holtmann 		ptr += sizeof(*ev);
51642f010b55SMarcel Holtmann 	}
51652f010b55SMarcel Holtmann 
51662f010b55SMarcel Holtmann 	hci_dev_unlock(hdev);
51672f010b55SMarcel Holtmann }
51682f010b55SMarcel Holtmann 
51696039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
5170fcd89c09SVille Tervo {
5171fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
5172fcd89c09SVille Tervo 
5173fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
5174fcd89c09SVille Tervo 
5175fcd89c09SVille Tervo 	switch (le_ev->subevent) {
5176fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
5177fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
5178fcd89c09SVille Tervo 		break;
5179fcd89c09SVille Tervo 
51801855d92dSMarcel Holtmann 	case HCI_EV_LE_CONN_UPDATE_COMPLETE:
51811855d92dSMarcel Holtmann 		hci_le_conn_update_complete_evt(hdev, skb);
51821855d92dSMarcel Holtmann 		break;
51831855d92dSMarcel Holtmann 
51849aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
51859aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
51869aa04c91SAndre Guedes 		break;
51879aa04c91SAndre Guedes 
51880fe29fd1SMarcel Holtmann 	case HCI_EV_LE_REMOTE_FEAT_COMPLETE:
51890fe29fd1SMarcel Holtmann 		hci_le_remote_feat_complete_evt(hdev, skb);
51900fe29fd1SMarcel Holtmann 		break;
51910fe29fd1SMarcel Holtmann 
5192a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
5193a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
5194a7a595f6SVinicius Costa Gomes 		break;
5195a7a595f6SVinicius Costa Gomes 
51968e75b46aSAndre Guedes 	case HCI_EV_LE_REMOTE_CONN_PARAM_REQ:
51978e75b46aSAndre Guedes 		hci_le_remote_conn_param_req_evt(hdev, skb);
51988e75b46aSAndre Guedes 		break;
51998e75b46aSAndre Guedes 
52002f010b55SMarcel Holtmann 	case HCI_EV_LE_DIRECT_ADV_REPORT:
52012f010b55SMarcel Holtmann 		hci_le_direct_adv_report_evt(hdev, skb);
52022f010b55SMarcel Holtmann 		break;
52032f010b55SMarcel Holtmann 
5204fcd89c09SVille Tervo 	default:
5205fcd89c09SVille Tervo 		break;
5206fcd89c09SVille Tervo 	}
5207fcd89c09SVille Tervo }
5208fcd89c09SVille Tervo 
52099495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
52109495b2eeSAndrei Emeltchenko {
52119495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
52129495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
52139495b2eeSAndrei Emeltchenko 
52149495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
52159495b2eeSAndrei Emeltchenko 
52169495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
52179495b2eeSAndrei Emeltchenko 
52189495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
52199495b2eeSAndrei Emeltchenko 	if (!hcon)
52209495b2eeSAndrei Emeltchenko 		return;
52219495b2eeSAndrei Emeltchenko 
52229495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
52239495b2eeSAndrei Emeltchenko }
52249495b2eeSAndrei Emeltchenko 
5225757aa0b5SJohan Hedberg static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
5226757aa0b5SJohan Hedberg 				 u8 event, struct sk_buff *skb)
5227757aa0b5SJohan Hedberg {
5228757aa0b5SJohan Hedberg 	struct hci_ev_cmd_complete *ev;
5229757aa0b5SJohan Hedberg 	struct hci_event_hdr *hdr;
5230757aa0b5SJohan Hedberg 
5231757aa0b5SJohan Hedberg 	if (!skb)
5232757aa0b5SJohan Hedberg 		return false;
5233757aa0b5SJohan Hedberg 
5234757aa0b5SJohan Hedberg 	if (skb->len < sizeof(*hdr)) {
5235757aa0b5SJohan Hedberg 		BT_ERR("Too short HCI event");
5236757aa0b5SJohan Hedberg 		return false;
5237757aa0b5SJohan Hedberg 	}
5238757aa0b5SJohan Hedberg 
5239757aa0b5SJohan Hedberg 	hdr = (void *) skb->data;
5240757aa0b5SJohan Hedberg 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
5241757aa0b5SJohan Hedberg 
5242757aa0b5SJohan Hedberg 	if (event) {
5243757aa0b5SJohan Hedberg 		if (hdr->evt != event)
5244757aa0b5SJohan Hedberg 			return false;
5245757aa0b5SJohan Hedberg 		return true;
5246757aa0b5SJohan Hedberg 	}
5247757aa0b5SJohan Hedberg 
5248757aa0b5SJohan Hedberg 	if (hdr->evt != HCI_EV_CMD_COMPLETE) {
5249757aa0b5SJohan Hedberg 		BT_DBG("Last event is not cmd complete (0x%2.2x)", hdr->evt);
5250757aa0b5SJohan Hedberg 		return false;
5251757aa0b5SJohan Hedberg 	}
5252757aa0b5SJohan Hedberg 
5253757aa0b5SJohan Hedberg 	if (skb->len < sizeof(*ev)) {
5254757aa0b5SJohan Hedberg 		BT_ERR("Too short cmd_complete event");
5255757aa0b5SJohan Hedberg 		return false;
5256757aa0b5SJohan Hedberg 	}
5257757aa0b5SJohan Hedberg 
5258757aa0b5SJohan Hedberg 	ev = (void *) skb->data;
5259757aa0b5SJohan Hedberg 	skb_pull(skb, sizeof(*ev));
5260757aa0b5SJohan Hedberg 
5261757aa0b5SJohan Hedberg 	if (opcode != __le16_to_cpu(ev->opcode)) {
5262757aa0b5SJohan Hedberg 		BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode,
5263757aa0b5SJohan Hedberg 		       __le16_to_cpu(ev->opcode));
5264757aa0b5SJohan Hedberg 		return false;
5265757aa0b5SJohan Hedberg 	}
5266757aa0b5SJohan Hedberg 
5267757aa0b5SJohan Hedberg 	return true;
5268757aa0b5SJohan Hedberg }
5269757aa0b5SJohan Hedberg 
52701da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
52711da177e4SLinus Torvalds {
5272a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
5273e6214487SJohan Hedberg 	hci_req_complete_t req_complete = NULL;
5274e6214487SJohan Hedberg 	hci_req_complete_skb_t req_complete_skb = NULL;
5275e6214487SJohan Hedberg 	struct sk_buff *orig_skb = NULL;
5276757aa0b5SJohan Hedberg 	u8 status = 0, event = hdr->evt, req_evt = 0;
5277e6214487SJohan Hedberg 	u16 opcode = HCI_OP_NOP;
52781da177e4SLinus Torvalds 
5279db6e3e8dSJohan Hedberg 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
5280c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
5281e6214487SJohan Hedberg 		opcode = __le16_to_cpu(cmd_hdr->opcode);
5282e6214487SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, status, &req_complete,
5283e6214487SJohan Hedberg 				     &req_complete_skb);
5284757aa0b5SJohan Hedberg 		req_evt = event;
528502350a72SJohan Hedberg 	}
528602350a72SJohan Hedberg 
5287e6214487SJohan Hedberg 	/* If it looks like we might end up having to call
5288e6214487SJohan Hedberg 	 * req_complete_skb, store a pristine copy of the skb since the
5289e6214487SJohan Hedberg 	 * various handlers may modify the original one through
5290e6214487SJohan Hedberg 	 * skb_pull() calls, etc.
5291e6214487SJohan Hedberg 	 */
5292e6214487SJohan Hedberg 	if (req_complete_skb || event == HCI_EV_CMD_STATUS ||
5293e6214487SJohan Hedberg 	    event == HCI_EV_CMD_COMPLETE)
5294e6214487SJohan Hedberg 		orig_skb = skb_clone(skb, GFP_KERNEL);
5295e6214487SJohan Hedberg 
5296e6214487SJohan Hedberg 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
5297e6214487SJohan Hedberg 
5298a9de9248SMarcel Holtmann 	switch (event) {
52991da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
53001da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
53011da177e4SLinus Torvalds 		break;
53021da177e4SLinus Torvalds 
53031da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
53041da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
53051da177e4SLinus Torvalds 		break;
53061da177e4SLinus Torvalds 
5307a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
5308a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
530921d9e30eSMarcel Holtmann 		break;
531021d9e30eSMarcel Holtmann 
53111da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
53121da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
53131da177e4SLinus Torvalds 		break;
53141da177e4SLinus Torvalds 
53151da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
53161da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
53171da177e4SLinus Torvalds 		break;
53181da177e4SLinus Torvalds 
53191da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
53201da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
53211da177e4SLinus Torvalds 		break;
53221da177e4SLinus Torvalds 
5323a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
5324a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
5325a9de9248SMarcel Holtmann 		break;
5326a9de9248SMarcel Holtmann 
53271da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
53281da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
53291da177e4SLinus Torvalds 		break;
53301da177e4SLinus Torvalds 
5331a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
5332a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
5333a9de9248SMarcel Holtmann 		break;
5334a9de9248SMarcel Holtmann 
5335a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
5336a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
5337a9de9248SMarcel Holtmann 		break;
5338a9de9248SMarcel Holtmann 
5339a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
5340e6214487SJohan Hedberg 		hci_cmd_complete_evt(hdev, skb, &opcode, &status,
5341e6214487SJohan Hedberg 				     &req_complete, &req_complete_skb);
5342a9de9248SMarcel Holtmann 		break;
5343a9de9248SMarcel Holtmann 
5344a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
5345e6214487SJohan Hedberg 		hci_cmd_status_evt(hdev, skb, &opcode, &status, &req_complete,
5346e6214487SJohan Hedberg 				   &req_complete_skb);
5347a9de9248SMarcel Holtmann 		break;
5348a9de9248SMarcel Holtmann 
534924dfa343SMarcel Holtmann 	case HCI_EV_HARDWARE_ERROR:
535024dfa343SMarcel Holtmann 		hci_hardware_error_evt(hdev, skb);
535124dfa343SMarcel Holtmann 		break;
535224dfa343SMarcel Holtmann 
5353a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
5354a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
5355a9de9248SMarcel Holtmann 		break;
5356a9de9248SMarcel Holtmann 
5357a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
5358a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
5359a9de9248SMarcel Holtmann 		break;
5360a9de9248SMarcel Holtmann 
5361a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
5362a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
53631da177e4SLinus Torvalds 		break;
53641da177e4SLinus Torvalds 
53651da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
53661da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
53671da177e4SLinus Torvalds 		break;
53681da177e4SLinus Torvalds 
53691da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
53701da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
53711da177e4SLinus Torvalds 		break;
53721da177e4SLinus Torvalds 
53731da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
53741da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
53751da177e4SLinus Torvalds 		break;
53761da177e4SLinus Torvalds 
53771da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
53781da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
53791da177e4SLinus Torvalds 		break;
53801da177e4SLinus Torvalds 
5381a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
5382a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
5383a8746417SMarcel Holtmann 		break;
5384a8746417SMarcel Holtmann 
538585a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
538685a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
538785a1e930SMarcel Holtmann 		break;
538885a1e930SMarcel Holtmann 
5389a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
5390a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
5391a9de9248SMarcel Holtmann 		break;
5392a9de9248SMarcel Holtmann 
5393a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
5394a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
5395a9de9248SMarcel Holtmann 		break;
5396a9de9248SMarcel Holtmann 
5397a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
5398a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
5399a9de9248SMarcel Holtmann 		break;
5400a9de9248SMarcel Holtmann 
5401a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
5402a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
54031da177e4SLinus Torvalds 		break;
54041da177e4SLinus Torvalds 
54051c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
54061c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
54071c2e0041SJohan Hedberg 		break;
54081c2e0041SJohan Hedberg 
54090493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
54100493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
54110493684eSMarcel Holtmann 		break;
54120493684eSMarcel Holtmann 
541303b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
541403b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
541503b555e1SJohan Hedberg 		break;
541603b555e1SJohan Hedberg 
5417a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
5418a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
5419a5c29683SJohan Hedberg 		break;
5420a5c29683SJohan Hedberg 
54211143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
54221143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
54231143d458SBrian Gix 		break;
54241143d458SBrian Gix 
542592a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
542692a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
542792a25256SJohan Hedberg 		break;
542892a25256SJohan Hedberg 
542992a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
543092a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
543192a25256SJohan Hedberg 		break;
543292a25256SJohan Hedberg 
54330493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
54340493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
54350493684eSMarcel Holtmann 		break;
54360493684eSMarcel Holtmann 
543741a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
543841a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
543941a96212SMarcel Holtmann 		break;
544041a96212SMarcel Holtmann 
5441fcd89c09SVille Tervo 	case HCI_EV_LE_META:
5442fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
5443fcd89c09SVille Tervo 		break;
5444fcd89c09SVille Tervo 
54459495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
54469495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
54479495b2eeSAndrei Emeltchenko 		break;
54489495b2eeSAndrei Emeltchenko 
54492763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
54502763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
54512763eda6SSzymon Janc 		break;
54522763eda6SSzymon Janc 
5453d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
5454d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
5455d5e91192SAndrei Emeltchenko 		break;
5456d5e91192SAndrei Emeltchenko 
545727695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
545827695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
545927695fb4SAndrei Emeltchenko 		break;
546027695fb4SAndrei Emeltchenko 
5461606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
5462606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
5463606e2a10SAndrei Emeltchenko 		break;
5464606e2a10SAndrei Emeltchenko 
54659eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
54669eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
54679eef6b3aSAndrei Emeltchenko 		break;
54689eef6b3aSAndrei Emeltchenko 
546925e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
547025e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
547125e89e99SAndrei Emeltchenko 		break;
547225e89e99SAndrei Emeltchenko 
54731da177e4SLinus Torvalds 	default:
54749f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
54751da177e4SLinus Torvalds 		break;
54761da177e4SLinus Torvalds 	}
54771da177e4SLinus Torvalds 
5478757aa0b5SJohan Hedberg 	if (req_complete) {
5479e6214487SJohan Hedberg 		req_complete(hdev, status, opcode);
5480757aa0b5SJohan Hedberg 	} else if (req_complete_skb) {
5481757aa0b5SJohan Hedberg 		if (!hci_get_cmd_complete(hdev, opcode, req_evt, orig_skb)) {
5482757aa0b5SJohan Hedberg 			kfree_skb(orig_skb);
5483757aa0b5SJohan Hedberg 			orig_skb = NULL;
5484757aa0b5SJohan Hedberg 		}
5485e6214487SJohan Hedberg 		req_complete_skb(hdev, status, opcode, orig_skb);
5486757aa0b5SJohan Hedberg 	}
5487e6214487SJohan Hedberg 
5488e6214487SJohan Hedberg 	kfree_skb(orig_skb);
54891da177e4SLinus Torvalds 	kfree_skb(skb);
54901da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
54911da177e4SLinus Torvalds }
5492