xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 9645c76c)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds    BlueZ - Bluetooth protocol stack for Linux
32d0a0346SRon Shaffer    Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds    This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds    it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds    published by the Free Software Foundation;
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
121da177e4SLinus Torvalds    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131da177e4SLinus Torvalds    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
141da177e4SLinus Torvalds    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
151da177e4SLinus Torvalds    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
161da177e4SLinus Torvalds    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
171da177e4SLinus Torvalds    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
181da177e4SLinus Torvalds    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
211da177e4SLinus Torvalds    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
221da177e4SLinus Torvalds    SOFTWARE IS DISCLAIMED.
231da177e4SLinus Torvalds */
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds #include <asm/unaligned.h>
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
31f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h>
327ef9fbf0SMarcel Holtmann 
337024728eSMarcel Holtmann #include "a2mp.h"
347ef9fbf0SMarcel Holtmann #include "amp.h"
352ceba539SJohan Hedberg #include "smp.h"
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds /* Handle HCI Event packets */
381da177e4SLinus Torvalds 
39a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
401da177e4SLinus Torvalds {
41a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
421da177e4SLinus Torvalds 
439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
441da177e4SLinus Torvalds 
4582f4785cSAndre Guedes 	if (status)
46a9de9248SMarcel Holtmann 		return;
471da177e4SLinus Torvalds 
4889352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
494e857c58SPeter Zijlstra 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
503e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
5189352e7dSAndre Guedes 
5250143a43SJohan Hedberg 	hci_dev_lock(hdev);
5350143a43SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
5450143a43SJohan Hedberg 	hci_dev_unlock(hdev);
5550143a43SJohan Hedberg 
56a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
571da177e4SLinus Torvalds }
586bd57416SMarcel Holtmann 
594d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
604d93483bSAndre Guedes {
614d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
624d93483bSAndre Guedes 
639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
64ae854a70SAndre Guedes 
65ae854a70SAndre Guedes 	if (status)
66ae854a70SAndre Guedes 		return;
67ae854a70SAndre Guedes 
68ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
694d93483bSAndre Guedes }
704d93483bSAndre Guedes 
71a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
721da177e4SLinus Torvalds {
73a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
74a9de9248SMarcel Holtmann 
759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
76a9de9248SMarcel Holtmann 
77a9de9248SMarcel Holtmann 	if (status)
78a9de9248SMarcel Holtmann 		return;
79a9de9248SMarcel Holtmann 
80ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
81ae854a70SAndre Guedes 
82a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
83a9de9248SMarcel Holtmann }
84a9de9248SMarcel Holtmann 
85807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
86807deac2SGustavo Padovan 					  struct sk_buff *skb)
87a9de9248SMarcel Holtmann {
88a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
89a9de9248SMarcel Holtmann }
90a9de9248SMarcel Holtmann 
91a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
92a9de9248SMarcel Holtmann {
93a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
941da177e4SLinus Torvalds 	struct hci_conn *conn;
951da177e4SLinus Torvalds 
969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
971da177e4SLinus Torvalds 
98a9de9248SMarcel Holtmann 	if (rp->status)
99a9de9248SMarcel Holtmann 		return;
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1021da177e4SLinus Torvalds 
103a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
10440bef302SJohan Hedberg 	if (conn)
10540bef302SJohan Hedberg 		conn->role = rp->role;
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
108a9de9248SMarcel Holtmann }
1091da177e4SLinus Torvalds 
110e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
111e4e8e37cSMarcel Holtmann {
112e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
113e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
114e4e8e37cSMarcel Holtmann 
1159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
116e4e8e37cSMarcel Holtmann 
117e4e8e37cSMarcel Holtmann 	if (rp->status)
118e4e8e37cSMarcel Holtmann 		return;
119e4e8e37cSMarcel Holtmann 
120e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
121e4e8e37cSMarcel Holtmann 
122e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
123e4e8e37cSMarcel Holtmann 	if (conn)
124e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
125e4e8e37cSMarcel Holtmann 
126e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
127e4e8e37cSMarcel Holtmann }
128e4e8e37cSMarcel Holtmann 
129a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
130a9de9248SMarcel Holtmann {
131a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
132a9de9248SMarcel Holtmann 	struct hci_conn *conn;
133a9de9248SMarcel Holtmann 	void *sent;
134a9de9248SMarcel Holtmann 
1359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
136a9de9248SMarcel Holtmann 
137a9de9248SMarcel Holtmann 	if (rp->status)
138a9de9248SMarcel Holtmann 		return;
139a9de9248SMarcel Holtmann 
140a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14104837f64SMarcel Holtmann 	if (!sent)
142a9de9248SMarcel Holtmann 		return;
14304837f64SMarcel Holtmann 
14404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14504837f64SMarcel Holtmann 
146a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
147e4e8e37cSMarcel Holtmann 	if (conn)
14883985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
14904837f64SMarcel Holtmann 
15004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1511da177e4SLinus Torvalds }
1521da177e4SLinus Torvalds 
153807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
154807deac2SGustavo Padovan 					struct sk_buff *skb)
155e4e8e37cSMarcel Holtmann {
156e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
157e4e8e37cSMarcel Holtmann 
1589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
159e4e8e37cSMarcel Holtmann 
160e4e8e37cSMarcel Holtmann 	if (rp->status)
161e4e8e37cSMarcel Holtmann 		return;
162e4e8e37cSMarcel Holtmann 
163e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
164e4e8e37cSMarcel Holtmann }
165e4e8e37cSMarcel Holtmann 
166807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
167807deac2SGustavo Padovan 					 struct sk_buff *skb)
168e4e8e37cSMarcel Holtmann {
169e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
170e4e8e37cSMarcel Holtmann 	void *sent;
171e4e8e37cSMarcel Holtmann 
1729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
173e4e8e37cSMarcel Holtmann 
17445296acdSMarcel Holtmann 	if (status)
17545296acdSMarcel Holtmann 		return;
17645296acdSMarcel Holtmann 
177e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
178e4e8e37cSMarcel Holtmann 	if (!sent)
179e4e8e37cSMarcel Holtmann 		return;
180e4e8e37cSMarcel Holtmann 
181e4e8e37cSMarcel Holtmann 	hdev->link_policy = get_unaligned_le16(sent);
182e4e8e37cSMarcel Holtmann }
183e4e8e37cSMarcel Holtmann 
184a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1851da177e4SLinus Torvalds {
186a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
187a9de9248SMarcel Holtmann 
1889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
189a9de9248SMarcel Holtmann 
19010572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19110572132SGustavo F. Padovan 
1928761f9d6SMarcel Holtmann 	if (status)
1938761f9d6SMarcel Holtmann 		return;
1948761f9d6SMarcel Holtmann 
195a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
1962cc6fb00SJohan Hedberg 	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
19769775ff6SAndre Guedes 
19869775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
199bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
200bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
2013f0f524bSJohan Hedberg 
2023f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
2033f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
204f8e808bdSMarcel Holtmann 
205f8e808bdSMarcel Holtmann 	memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data));
206f8e808bdSMarcel Holtmann 	hdev->scan_rsp_data_len = 0;
20706f5b778SMarcel Holtmann 
208533553f8SMarcel Holtmann 	hdev->le_scan_type = LE_SCAN_PASSIVE;
209533553f8SMarcel Holtmann 
21006f5b778SMarcel Holtmann 	hdev->ssp_debug_mode = 0;
211a4d5504dSMarcel Holtmann 
212a4d5504dSMarcel Holtmann 	hci_bdaddr_list_clear(&hdev->le_white_list);
213a9de9248SMarcel Holtmann }
214a9de9248SMarcel Holtmann 
215a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
216a9de9248SMarcel Holtmann {
217a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2181da177e4SLinus Torvalds 	void *sent;
2191da177e4SLinus Torvalds 
2209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2211da177e4SLinus Torvalds 
222a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2231da177e4SLinus Torvalds 	if (!sent)
224a9de9248SMarcel Holtmann 		return;
2251da177e4SLinus Torvalds 
22656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
22756e5cb86SJohan Hedberg 
228f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
229f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
23028cc7bdeSJohan Hedberg 	else if (!status)
23128cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
232f51d5b24SJohan Hedberg 
23356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
234a9de9248SMarcel Holtmann }
235a9de9248SMarcel Holtmann 
236a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
237a9de9248SMarcel Holtmann {
238a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
239a9de9248SMarcel Holtmann 
2409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
241a9de9248SMarcel Holtmann 
242a9de9248SMarcel Holtmann 	if (rp->status)
243a9de9248SMarcel Holtmann 		return;
244a9de9248SMarcel Holtmann 
245db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2461f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
247a9de9248SMarcel Holtmann }
248a9de9248SMarcel Holtmann 
249a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
250a9de9248SMarcel Holtmann {
251a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
252a9de9248SMarcel Holtmann 	void *sent;
253a9de9248SMarcel Holtmann 
2549f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
255a9de9248SMarcel Holtmann 
256a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
257a9de9248SMarcel Holtmann 	if (!sent)
258a9de9248SMarcel Holtmann 		return;
2591da177e4SLinus Torvalds 
2601da177e4SLinus Torvalds 	if (!status) {
261a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
262a9de9248SMarcel Holtmann 
2631da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2641da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2651da177e4SLinus Torvalds 		else
2661da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2671da177e4SLinus Torvalds 	}
268a9de9248SMarcel Holtmann 
26933ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
27033ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
271a9de9248SMarcel Holtmann }
2721da177e4SLinus Torvalds 
273a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
274a9de9248SMarcel Holtmann {
275a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
27645296acdSMarcel Holtmann 	__u8 param;
277a9de9248SMarcel Holtmann 	void *sent;
278a9de9248SMarcel Holtmann 
2799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
280a9de9248SMarcel Holtmann 
28145296acdSMarcel Holtmann 	if (status)
28245296acdSMarcel Holtmann 		return;
28345296acdSMarcel Holtmann 
284a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2851da177e4SLinus Torvalds 	if (!sent)
286a9de9248SMarcel Holtmann 		return;
2871da177e4SLinus Torvalds 
28845296acdSMarcel Holtmann 	param = *((__u8 *) sent);
289a9de9248SMarcel Holtmann 
2901da177e4SLinus Torvalds 	if (param)
2911da177e4SLinus Torvalds 		set_bit(HCI_ENCRYPT, &hdev->flags);
2921da177e4SLinus Torvalds 	else
2931da177e4SLinus Torvalds 		clear_bit(HCI_ENCRYPT, &hdev->flags);
2941da177e4SLinus Torvalds }
2951da177e4SLinus Torvalds 
296a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
297a9de9248SMarcel Holtmann {
29845296acdSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
29945296acdSMarcel Holtmann 	__u8 param;
300a9de9248SMarcel Holtmann 	void *sent;
3011da177e4SLinus Torvalds 
3029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
303a9de9248SMarcel Holtmann 
304a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3051da177e4SLinus Torvalds 	if (!sent)
306a9de9248SMarcel Holtmann 		return;
3071da177e4SLinus Torvalds 
30836f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
309a9de9248SMarcel Holtmann 
31056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
31156e5cb86SJohan Hedberg 
312fa1bd918SMikel Astiz 	if (status) {
3132d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3142d7cee58SJohan Hedberg 		goto done;
3152d7cee58SJohan Hedberg 	}
3162d7cee58SJohan Hedberg 
317bc6d2d04SJohan Hedberg 	if (param & SCAN_INQUIRY)
3181da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
319bc6d2d04SJohan Hedberg 	else
320bc6d2d04SJohan Hedberg 		clear_bit(HCI_ISCAN, &hdev->flags);
3211da177e4SLinus Torvalds 
322031547d8SJohan Hedberg 	if (param & SCAN_PAGE)
3231da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
324bc6d2d04SJohan Hedberg 	else
325204e3990SJohan Hedberg 		clear_bit(HCI_PSCAN, &hdev->flags);
326a9de9248SMarcel Holtmann 
32736f7fc7eSJohan Hedberg done:
32856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
3291da177e4SLinus Torvalds }
3301da177e4SLinus Torvalds 
331a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
332a9de9248SMarcel Holtmann {
333a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
334a9de9248SMarcel Holtmann 
3359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
336a9de9248SMarcel Holtmann 
337a9de9248SMarcel Holtmann 	if (rp->status)
338a9de9248SMarcel Holtmann 		return;
339a9de9248SMarcel Holtmann 
340a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
341a9de9248SMarcel Holtmann 
342a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
343a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
344a9de9248SMarcel Holtmann }
345a9de9248SMarcel Holtmann 
346a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
347a9de9248SMarcel Holtmann {
348a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
349a9de9248SMarcel Holtmann 	void *sent;
350a9de9248SMarcel Holtmann 
3519f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
352a9de9248SMarcel Holtmann 
353a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
354a9de9248SMarcel Holtmann 	if (!sent)
355a9de9248SMarcel Holtmann 		return;
356a9de9248SMarcel Holtmann 
3577f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3587f9a903cSMarcel Holtmann 
3597f9a903cSMarcel Holtmann 	if (status == 0)
360a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3617f9a903cSMarcel Holtmann 
3627f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3637f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3647f9a903cSMarcel Holtmann 
3657f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
366a9de9248SMarcel Holtmann }
367a9de9248SMarcel Holtmann 
368a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
369a9de9248SMarcel Holtmann {
370a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
371a9de9248SMarcel Holtmann 	__u16 setting;
372a9de9248SMarcel Holtmann 
3739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
374a9de9248SMarcel Holtmann 
375a9de9248SMarcel Holtmann 	if (rp->status)
376a9de9248SMarcel Holtmann 		return;
377a9de9248SMarcel Holtmann 
378a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
379a9de9248SMarcel Holtmann 
380a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
381a9de9248SMarcel Holtmann 		return;
382a9de9248SMarcel Holtmann 
383a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
384a9de9248SMarcel Holtmann 
3859f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
386a9de9248SMarcel Holtmann 
3873c54711cSGustavo F. Padovan 	if (hdev->notify)
388a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
389a9de9248SMarcel Holtmann }
390a9de9248SMarcel Holtmann 
3918fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
3928fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
393a9de9248SMarcel Holtmann {
394a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
395f383f275SMarcel Holtmann 	__u16 setting;
396a9de9248SMarcel Holtmann 	void *sent;
397a9de9248SMarcel Holtmann 
3989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
399a9de9248SMarcel Holtmann 
400f383f275SMarcel Holtmann 	if (status)
401f383f275SMarcel Holtmann 		return;
402f383f275SMarcel Holtmann 
403a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
404a9de9248SMarcel Holtmann 	if (!sent)
405a9de9248SMarcel Holtmann 		return;
406a9de9248SMarcel Holtmann 
407f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4081da177e4SLinus Torvalds 
409f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
410f383f275SMarcel Holtmann 		return;
411f383f275SMarcel Holtmann 
4121da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4131da177e4SLinus Torvalds 
4149f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4151da177e4SLinus Torvalds 
4163c54711cSGustavo F. Padovan 	if (hdev->notify)
4171da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4181da177e4SLinus Torvalds }
4191da177e4SLinus Torvalds 
420b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev,
421b4cb9fb2SMarcel Holtmann 					  struct sk_buff *skb)
422b4cb9fb2SMarcel Holtmann {
423b4cb9fb2SMarcel Holtmann 	struct hci_rp_read_num_supported_iac *rp = (void *) skb->data;
424b4cb9fb2SMarcel Holtmann 
425b4cb9fb2SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
426b4cb9fb2SMarcel Holtmann 
427b4cb9fb2SMarcel Holtmann 	if (rp->status)
428b4cb9fb2SMarcel Holtmann 		return;
429b4cb9fb2SMarcel Holtmann 
430b4cb9fb2SMarcel Holtmann 	hdev->num_iac = rp->num_iac;
431b4cb9fb2SMarcel Holtmann 
432b4cb9fb2SMarcel Holtmann 	BT_DBG("%s num iac %d", hdev->name, hdev->num_iac);
433b4cb9fb2SMarcel Holtmann }
434b4cb9fb2SMarcel Holtmann 
435333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
436333140b5SMarcel Holtmann {
437333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4385ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
439333140b5SMarcel Holtmann 
4409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
441333140b5SMarcel Holtmann 
442333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
443333140b5SMarcel Holtmann 	if (!sent)
444333140b5SMarcel Holtmann 		return;
445333140b5SMarcel Holtmann 
4465ed8eb2fSJohan Hedberg 	if (!status) {
4475ed8eb2fSJohan Hedberg 		if (sent->mode)
448cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_SSP;
4495ed8eb2fSJohan Hedberg 		else
450cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_SSP;
4515ed8eb2fSJohan Hedberg 	}
4525ed8eb2fSJohan Hedberg 
453c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4545ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
455c0ecddc2SJohan Hedberg 	else if (!status) {
4565ed8eb2fSJohan Hedberg 		if (sent->mode)
45784bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
45884bde9d6SJohan Hedberg 		else
45984bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
460c0ecddc2SJohan Hedberg 	}
461333140b5SMarcel Holtmann }
462333140b5SMarcel Holtmann 
463eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
464eac83dc6SMarcel Holtmann {
465eac83dc6SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
466eac83dc6SMarcel Holtmann 	struct hci_cp_write_sc_support *sent;
467eac83dc6SMarcel Holtmann 
468eac83dc6SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
469eac83dc6SMarcel Holtmann 
470eac83dc6SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
471eac83dc6SMarcel Holtmann 	if (!sent)
472eac83dc6SMarcel Holtmann 		return;
473eac83dc6SMarcel Holtmann 
474eac83dc6SMarcel Holtmann 	if (!status) {
475eac83dc6SMarcel Holtmann 		if (sent->support)
476eac83dc6SMarcel Holtmann 			hdev->features[1][0] |= LMP_HOST_SC;
477eac83dc6SMarcel Holtmann 		else
478eac83dc6SMarcel Holtmann 			hdev->features[1][0] &= ~LMP_HOST_SC;
479eac83dc6SMarcel Holtmann 	}
480eac83dc6SMarcel Holtmann 
481eac83dc6SMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
482eac83dc6SMarcel Holtmann 		mgmt_sc_enable_complete(hdev, sent->support, status);
483eac83dc6SMarcel Holtmann 	else if (!status) {
484eac83dc6SMarcel Holtmann 		if (sent->support)
485eac83dc6SMarcel Holtmann 			set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
486eac83dc6SMarcel Holtmann 		else
487eac83dc6SMarcel Holtmann 			clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
488eac83dc6SMarcel Holtmann 	}
489eac83dc6SMarcel Holtmann }
490eac83dc6SMarcel Holtmann 
491a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
492a9de9248SMarcel Holtmann {
493a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
4941143e5a6SMarcel Holtmann 
4959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
4961143e5a6SMarcel Holtmann 
497a9de9248SMarcel Holtmann 	if (rp->status)
49842c6b129SJohan Hedberg 		return;
4991143e5a6SMarcel Holtmann 
5000d5551f5SMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
501a9de9248SMarcel Holtmann 		hdev->hci_ver = rp->hci_ver;
502e4e8e37cSMarcel Holtmann 		hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
503d5859e22SJohan Hedberg 		hdev->lmp_ver = rp->lmp_ver;
504e4e8e37cSMarcel Holtmann 		hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
505d5859e22SJohan Hedberg 		hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5060d5551f5SMarcel Holtmann 	}
507d5859e22SJohan Hedberg }
508d5859e22SJohan Hedberg 
5098fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
5108fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
511a9de9248SMarcel Holtmann {
512a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
513a9de9248SMarcel Holtmann 
5149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
515a9de9248SMarcel Holtmann 
5166a070e6eSMarcel Holtmann 	if (rp->status)
5176a070e6eSMarcel Holtmann 		return;
5186a070e6eSMarcel Holtmann 
5196a070e6eSMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
520a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
521a9de9248SMarcel Holtmann }
522a9de9248SMarcel Holtmann 
5238fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
5248fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
525a9de9248SMarcel Holtmann {
526a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
527a9de9248SMarcel Holtmann 
5289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
529a9de9248SMarcel Holtmann 
530a9de9248SMarcel Holtmann 	if (rp->status)
531a9de9248SMarcel Holtmann 		return;
532a9de9248SMarcel Holtmann 
533a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
5341da177e4SLinus Torvalds 
5351da177e4SLinus Torvalds 	/* Adjust default settings according to features
5361da177e4SLinus Torvalds 	 * supported by device. */
537a9de9248SMarcel Holtmann 
538cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_3SLOT)
5391da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
5401da177e4SLinus Torvalds 
541cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_5SLOT)
5421da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
5431da177e4SLinus Torvalds 
544cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV2) {
5451da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
5465b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
5475b7f9909SMarcel Holtmann 	}
5481da177e4SLinus Torvalds 
549cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV3) {
5501da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
5515b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
5525b7f9909SMarcel Holtmann 	}
5535b7f9909SMarcel Holtmann 
55445db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
5555b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
5565b7f9909SMarcel Holtmann 
557cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV4)
5585b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
5595b7f9909SMarcel Holtmann 
560cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV5)
5615b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
5621da177e4SLinus Torvalds 
563cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
564efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
565efc7688bSMarcel Holtmann 
566cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
567efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
568efc7688bSMarcel Holtmann 
569cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
570efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
5711da177e4SLinus Torvalds }
5721da177e4SLinus Torvalds 
573971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
574971e3a4bSAndre Guedes 					   struct sk_buff *skb)
575971e3a4bSAndre Guedes {
576971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
577971e3a4bSAndre Guedes 
5789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
579971e3a4bSAndre Guedes 
580971e3a4bSAndre Guedes 	if (rp->status)
58142c6b129SJohan Hedberg 		return;
582971e3a4bSAndre Guedes 
58357af75a8SMarcel Holtmann 	if (hdev->max_page < rp->max_page)
584d2c5d77fSJohan Hedberg 		hdev->max_page = rp->max_page;
585d2c5d77fSJohan Hedberg 
586cad718edSJohan Hedberg 	if (rp->page < HCI_MAX_PAGES)
587cad718edSJohan Hedberg 		memcpy(hdev->features[rp->page], rp->features, 8);
588971e3a4bSAndre Guedes }
589971e3a4bSAndre Guedes 
5901e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
5911e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
5921e89cffbSAndrei Emeltchenko {
5931e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
5941e89cffbSAndrei Emeltchenko 
5959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5961e89cffbSAndrei Emeltchenko 
59745296acdSMarcel Holtmann 	if (rp->status)
59845296acdSMarcel Holtmann 		return;
59945296acdSMarcel Holtmann 
6001e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
6011e89cffbSAndrei Emeltchenko }
6021e89cffbSAndrei Emeltchenko 
603a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
604a9de9248SMarcel Holtmann {
605a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
606a9de9248SMarcel Holtmann 
6079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
608a9de9248SMarcel Holtmann 
609a9de9248SMarcel Holtmann 	if (rp->status)
610a9de9248SMarcel Holtmann 		return;
611a9de9248SMarcel Holtmann 
612a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
613a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
614a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
615a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
616da1f5198SMarcel Holtmann 
617da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
618da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
619da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
620da1f5198SMarcel Holtmann 	}
621da1f5198SMarcel Holtmann 
622da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
623da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
6241da177e4SLinus Torvalds 
625807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
626807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
6271da177e4SLinus Torvalds }
6281da177e4SLinus Torvalds 
629a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
630a9de9248SMarcel Holtmann {
631a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6321da177e4SLinus Torvalds 
6339f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
634a9de9248SMarcel Holtmann 
635e30d3f5fSMarcel Holtmann 	if (rp->status)
636e30d3f5fSMarcel Holtmann 		return;
637e30d3f5fSMarcel Holtmann 
638e30d3f5fSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
639a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
640e30d3f5fSMarcel Holtmann 
641e30d3f5fSMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
642e30d3f5fSMarcel Holtmann 		bacpy(&hdev->setup_addr, &rp->bdaddr);
64323bb5763SJohan Hedberg }
64423bb5763SJohan Hedberg 
645f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
646f332ec66SJohan Hedberg 					   struct sk_buff *skb)
647f332ec66SJohan Hedberg {
648f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
649f332ec66SJohan Hedberg 
650f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
651f332ec66SJohan Hedberg 
65245296acdSMarcel Holtmann 	if (rp->status)
65345296acdSMarcel Holtmann 		return;
65445296acdSMarcel Holtmann 
65545296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags)) {
656f332ec66SJohan Hedberg 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
657f332ec66SJohan Hedberg 		hdev->page_scan_window = __le16_to_cpu(rp->window);
658f332ec66SJohan Hedberg 	}
659f332ec66SJohan Hedberg }
660f332ec66SJohan Hedberg 
6614a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
6624a3ee763SJohan Hedberg 					    struct sk_buff *skb)
6634a3ee763SJohan Hedberg {
6644a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6654a3ee763SJohan Hedberg 	struct hci_cp_write_page_scan_activity *sent;
6664a3ee763SJohan Hedberg 
6674a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6684a3ee763SJohan Hedberg 
6694a3ee763SJohan Hedberg 	if (status)
6704a3ee763SJohan Hedberg 		return;
6714a3ee763SJohan Hedberg 
6724a3ee763SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
6734a3ee763SJohan Hedberg 	if (!sent)
6744a3ee763SJohan Hedberg 		return;
6754a3ee763SJohan Hedberg 
6764a3ee763SJohan Hedberg 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
6774a3ee763SJohan Hedberg 	hdev->page_scan_window = __le16_to_cpu(sent->window);
6784a3ee763SJohan Hedberg }
6794a3ee763SJohan Hedberg 
680f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
681f332ec66SJohan Hedberg 					   struct sk_buff *skb)
682f332ec66SJohan Hedberg {
683f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
684f332ec66SJohan Hedberg 
685f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
686f332ec66SJohan Hedberg 
68745296acdSMarcel Holtmann 	if (rp->status)
68845296acdSMarcel Holtmann 		return;
68945296acdSMarcel Holtmann 
69045296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
691f332ec66SJohan Hedberg 		hdev->page_scan_type = rp->type;
692f332ec66SJohan Hedberg }
693f332ec66SJohan Hedberg 
6944a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
6954a3ee763SJohan Hedberg 					struct sk_buff *skb)
6964a3ee763SJohan Hedberg {
6974a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6984a3ee763SJohan Hedberg 	u8 *type;
6994a3ee763SJohan Hedberg 
7004a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
7014a3ee763SJohan Hedberg 
7024a3ee763SJohan Hedberg 	if (status)
7034a3ee763SJohan Hedberg 		return;
7044a3ee763SJohan Hedberg 
7054a3ee763SJohan Hedberg 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
7064a3ee763SJohan Hedberg 	if (type)
7074a3ee763SJohan Hedberg 		hdev->page_scan_type = *type;
7084a3ee763SJohan Hedberg }
7094a3ee763SJohan Hedberg 
710350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
711350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
712350ee4cfSAndrei Emeltchenko {
713350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
714350ee4cfSAndrei Emeltchenko 
7159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
716350ee4cfSAndrei Emeltchenko 
717350ee4cfSAndrei Emeltchenko 	if (rp->status)
718350ee4cfSAndrei Emeltchenko 		return;
719350ee4cfSAndrei Emeltchenko 
720350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
721350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
722350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
723350ee4cfSAndrei Emeltchenko 
724350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
725350ee4cfSAndrei Emeltchenko 
726350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
727350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
728350ee4cfSAndrei Emeltchenko }
729350ee4cfSAndrei Emeltchenko 
73033f35721SJohan Hedberg static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb)
73133f35721SJohan Hedberg {
73233f35721SJohan Hedberg 	struct hci_rp_read_clock *rp = (void *) skb->data;
73333f35721SJohan Hedberg 	struct hci_cp_read_clock *cp;
73433f35721SJohan Hedberg 	struct hci_conn *conn;
73533f35721SJohan Hedberg 
73633f35721SJohan Hedberg 	BT_DBG("%s", hdev->name);
73733f35721SJohan Hedberg 
73833f35721SJohan Hedberg 	if (skb->len < sizeof(*rp))
73933f35721SJohan Hedberg 		return;
74033f35721SJohan Hedberg 
74133f35721SJohan Hedberg 	if (rp->status)
74233f35721SJohan Hedberg 		return;
74333f35721SJohan Hedberg 
74433f35721SJohan Hedberg 	hci_dev_lock(hdev);
74533f35721SJohan Hedberg 
74633f35721SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
74733f35721SJohan Hedberg 	if (!cp)
74833f35721SJohan Hedberg 		goto unlock;
74933f35721SJohan Hedberg 
75033f35721SJohan Hedberg 	if (cp->which == 0x00) {
75133f35721SJohan Hedberg 		hdev->clock = le32_to_cpu(rp->clock);
75233f35721SJohan Hedberg 		goto unlock;
75333f35721SJohan Hedberg 	}
75433f35721SJohan Hedberg 
75533f35721SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
75633f35721SJohan Hedberg 	if (conn) {
75733f35721SJohan Hedberg 		conn->clock = le32_to_cpu(rp->clock);
75833f35721SJohan Hedberg 		conn->clock_accuracy = le16_to_cpu(rp->accuracy);
75933f35721SJohan Hedberg 	}
76033f35721SJohan Hedberg 
76133f35721SJohan Hedberg unlock:
76233f35721SJohan Hedberg 	hci_dev_unlock(hdev);
76333f35721SJohan Hedberg }
76433f35721SJohan Hedberg 
765928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
766928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
767928abaa7SAndrei Emeltchenko {
768928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
769928abaa7SAndrei Emeltchenko 
7709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
771928abaa7SAndrei Emeltchenko 
772928abaa7SAndrei Emeltchenko 	if (rp->status)
7738e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
774928abaa7SAndrei Emeltchenko 
775928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
776928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
777928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
778928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
779928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
780928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
781928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
782928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
783928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
784928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
785928abaa7SAndrei Emeltchenko 
7868e2a0d92SAndrei Emeltchenko a2mp_rsp:
7878e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
788928abaa7SAndrei Emeltchenko }
789928abaa7SAndrei Emeltchenko 
790903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
791903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
792903e4541SAndrei Emeltchenko {
793903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
794903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
795903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
796903e4541SAndrei Emeltchenko 
797903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
798903e4541SAndrei Emeltchenko 
799903e4541SAndrei Emeltchenko 	if (rp->status)
800903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
801903e4541SAndrei Emeltchenko 
802903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
803903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
804903e4541SAndrei Emeltchenko 
805903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
8062e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
807903e4541SAndrei Emeltchenko 
808903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
809903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
810903e4541SAndrei Emeltchenko 
811903e4541SAndrei Emeltchenko 		/* Read other fragments */
812903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
813903e4541SAndrei Emeltchenko 
814903e4541SAndrei Emeltchenko 		return;
815903e4541SAndrei Emeltchenko 	}
816903e4541SAndrei Emeltchenko 
817903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
818903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
819903e4541SAndrei Emeltchenko 	assoc->offset = 0;
820903e4541SAndrei Emeltchenko 
821903e4541SAndrei Emeltchenko a2mp_rsp:
822903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
823903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
8249495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
825903e4541SAndrei Emeltchenko }
826903e4541SAndrei Emeltchenko 
827d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
828d5859e22SJohan Hedberg 					 struct sk_buff *skb)
829d5859e22SJohan Hedberg {
83091c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
831d5859e22SJohan Hedberg 
8329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
833d5859e22SJohan Hedberg 
83445296acdSMarcel Holtmann 	if (rp->status)
83545296acdSMarcel Holtmann 		return;
83645296acdSMarcel Holtmann 
83791c4e9b1SMarcel Holtmann 	hdev->inq_tx_power = rp->tx_power;
838d5859e22SJohan Hedberg }
839d5859e22SJohan Hedberg 
840980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
841980e1a53SJohan Hedberg {
842980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
843980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
844980e1a53SJohan Hedberg 	struct hci_conn *conn;
845980e1a53SJohan Hedberg 
8469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
847980e1a53SJohan Hedberg 
84856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
84956e5cb86SJohan Hedberg 
850a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
851744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
852980e1a53SJohan Hedberg 
853fa1bd918SMikel Astiz 	if (rp->status)
85456e5cb86SJohan Hedberg 		goto unlock;
855980e1a53SJohan Hedberg 
856980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
857980e1a53SJohan Hedberg 	if (!cp)
85856e5cb86SJohan Hedberg 		goto unlock;
859980e1a53SJohan Hedberg 
860980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
861980e1a53SJohan Hedberg 	if (conn)
862980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
86356e5cb86SJohan Hedberg 
86456e5cb86SJohan Hedberg unlock:
86556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
866980e1a53SJohan Hedberg }
867980e1a53SJohan Hedberg 
868980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
869980e1a53SJohan Hedberg {
870980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
871980e1a53SJohan Hedberg 
8729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
873980e1a53SJohan Hedberg 
87456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
87556e5cb86SJohan Hedberg 
876a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
877744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
878980e1a53SJohan Hedberg 						 rp->status);
87956e5cb86SJohan Hedberg 
88056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
881980e1a53SJohan Hedberg }
88256e5cb86SJohan Hedberg 
8836ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8846ed58ec5SVille Tervo 				       struct sk_buff *skb)
8856ed58ec5SVille Tervo {
8866ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
8876ed58ec5SVille Tervo 
8889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8896ed58ec5SVille Tervo 
8906ed58ec5SVille Tervo 	if (rp->status)
8916ed58ec5SVille Tervo 		return;
8926ed58ec5SVille Tervo 
8936ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
8946ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8956ed58ec5SVille Tervo 
8966ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8976ed58ec5SVille Tervo 
8986ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8996ed58ec5SVille Tervo }
900980e1a53SJohan Hedberg 
90160e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
90260e77321SJohan Hedberg 					  struct sk_buff *skb)
90360e77321SJohan Hedberg {
90460e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
90560e77321SJohan Hedberg 
90660e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
90760e77321SJohan Hedberg 
90845296acdSMarcel Holtmann 	if (rp->status)
90945296acdSMarcel Holtmann 		return;
91045296acdSMarcel Holtmann 
91160e77321SJohan Hedberg 	memcpy(hdev->le_features, rp->features, 8);
91260e77321SJohan Hedberg }
91360e77321SJohan Hedberg 
9148fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
9158fa19098SJohan Hedberg 					struct sk_buff *skb)
9168fa19098SJohan Hedberg {
9178fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
9188fa19098SJohan Hedberg 
9198fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9208fa19098SJohan Hedberg 
92145296acdSMarcel Holtmann 	if (rp->status)
92245296acdSMarcel Holtmann 		return;
92345296acdSMarcel Holtmann 
9248fa19098SJohan Hedberg 	hdev->adv_tx_power = rp->tx_power;
9258fa19098SJohan Hedberg }
9268fa19098SJohan Hedberg 
927a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
928a5c29683SJohan Hedberg {
929a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
930a5c29683SJohan Hedberg 
9319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
932a5c29683SJohan Hedberg 
93356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
93456e5cb86SJohan Hedberg 
935a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
93604124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
93704124681SGustavo F. Padovan 						 rp->status);
93856e5cb86SJohan Hedberg 
93956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
940a5c29683SJohan Hedberg }
941a5c29683SJohan Hedberg 
942a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
943a5c29683SJohan Hedberg 					  struct sk_buff *skb)
944a5c29683SJohan Hedberg {
945a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
946a5c29683SJohan Hedberg 
9479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
948a5c29683SJohan Hedberg 
94956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
95056e5cb86SJohan Hedberg 
951a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
952744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
95304124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
95456e5cb86SJohan Hedberg 
95556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
956a5c29683SJohan Hedberg }
957a5c29683SJohan Hedberg 
9581143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9591143d458SBrian Gix {
9601143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9611143d458SBrian Gix 
9629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9631143d458SBrian Gix 
9641143d458SBrian Gix 	hci_dev_lock(hdev);
9651143d458SBrian Gix 
966a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
967272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
968272d90dfSJohan Hedberg 						 0, rp->status);
9691143d458SBrian Gix 
9701143d458SBrian Gix 	hci_dev_unlock(hdev);
9711143d458SBrian Gix }
9721143d458SBrian Gix 
9731143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9741143d458SBrian Gix 					  struct sk_buff *skb)
9751143d458SBrian Gix {
9761143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9771143d458SBrian Gix 
9789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9791143d458SBrian Gix 
9801143d458SBrian Gix 	hci_dev_lock(hdev);
9811143d458SBrian Gix 
982a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9831143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
98404124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
9851143d458SBrian Gix 
9861143d458SBrian Gix 	hci_dev_unlock(hdev);
9871143d458SBrian Gix }
9881143d458SBrian Gix 
9894d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
990c35938b2SSzymon Janc 				       struct sk_buff *skb)
991c35938b2SSzymon Janc {
992c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
993c35938b2SSzymon Janc 
9949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
995c35938b2SSzymon Janc 
99656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
9974d2d2796SMarcel Holtmann 	mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer,
9984d2d2796SMarcel Holtmann 					  NULL, NULL, rp->status);
9994d2d2796SMarcel Holtmann 	hci_dev_unlock(hdev);
10004d2d2796SMarcel Holtmann }
10014d2d2796SMarcel Holtmann 
10024d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
10034d2d2796SMarcel Holtmann 					   struct sk_buff *skb)
10044d2d2796SMarcel Holtmann {
10054d2d2796SMarcel Holtmann 	struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
10064d2d2796SMarcel Holtmann 
10074d2d2796SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10084d2d2796SMarcel Holtmann 
10094d2d2796SMarcel Holtmann 	hci_dev_lock(hdev);
10104d2d2796SMarcel Holtmann 	mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192,
10114d2d2796SMarcel Holtmann 					  rp->hash256, rp->randomizer256,
10124d2d2796SMarcel Holtmann 					  rp->status);
101356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1014c35938b2SSzymon Janc }
1015c35938b2SSzymon Janc 
10167a4cd51dSMarcel Holtmann 
10177a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
10187a4cd51dSMarcel Holtmann {
10197a4cd51dSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
10207a4cd51dSMarcel Holtmann 	bdaddr_t *sent;
10217a4cd51dSMarcel Holtmann 
10227a4cd51dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10237a4cd51dSMarcel Holtmann 
102445296acdSMarcel Holtmann 	if (status)
102545296acdSMarcel Holtmann 		return;
102645296acdSMarcel Holtmann 
10277a4cd51dSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
10287a4cd51dSMarcel Holtmann 	if (!sent)
10297a4cd51dSMarcel Holtmann 		return;
10307a4cd51dSMarcel Holtmann 
10317a4cd51dSMarcel Holtmann 	hci_dev_lock(hdev);
10327a4cd51dSMarcel Holtmann 
10337a4cd51dSMarcel Holtmann 	bacpy(&hdev->random_addr, sent);
10347a4cd51dSMarcel Holtmann 
10357a4cd51dSMarcel Holtmann 	hci_dev_unlock(hdev);
10367a4cd51dSMarcel Holtmann }
10377a4cd51dSMarcel Holtmann 
1038c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1039c1d5dc4aSJohan Hedberg {
1040c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
1041c1d5dc4aSJohan Hedberg 
1042c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1043c1d5dc4aSJohan Hedberg 
104445296acdSMarcel Holtmann 	if (status)
1045c1d5dc4aSJohan Hedberg 		return;
1046c1d5dc4aSJohan Hedberg 
104745296acdSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
104845296acdSMarcel Holtmann 	if (!sent)
10493c857757SJohan Hedberg 		return;
10503c857757SJohan Hedberg 
1051c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
1052c1d5dc4aSJohan Hedberg 
105349c922bbSStephen Hemminger 	/* If we're doing connection initiation as peripheral. Set a
10543c857757SJohan Hedberg 	 * timeout in case something goes wrong.
10553c857757SJohan Hedberg 	 */
10563c857757SJohan Hedberg 	if (*sent) {
10573c857757SJohan Hedberg 		struct hci_conn *conn;
10583c857757SJohan Hedberg 
105966c417c1SJohan Hedberg 		set_bit(HCI_LE_ADV, &hdev->dev_flags);
106066c417c1SJohan Hedberg 
10613c857757SJohan Hedberg 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
10623c857757SJohan Hedberg 		if (conn)
10633c857757SJohan Hedberg 			queue_delayed_work(hdev->workqueue,
10643c857757SJohan Hedberg 					   &conn->le_conn_timeout,
106509ae260bSJohan Hedberg 					   conn->conn_timeout);
106666c417c1SJohan Hedberg 	} else {
106766c417c1SJohan Hedberg 		clear_bit(HCI_LE_ADV, &hdev->dev_flags);
10683c857757SJohan Hedberg 	}
10693c857757SJohan Hedberg 
107004b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
1071c1d5dc4aSJohan Hedberg }
1072c1d5dc4aSJohan Hedberg 
1073533553f8SMarcel Holtmann static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1074533553f8SMarcel Holtmann {
1075533553f8SMarcel Holtmann 	struct hci_cp_le_set_scan_param *cp;
1076533553f8SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1077533553f8SMarcel Holtmann 
1078533553f8SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1079533553f8SMarcel Holtmann 
108045296acdSMarcel Holtmann 	if (status)
108145296acdSMarcel Holtmann 		return;
108245296acdSMarcel Holtmann 
1083533553f8SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM);
1084533553f8SMarcel Holtmann 	if (!cp)
1085533553f8SMarcel Holtmann 		return;
1086533553f8SMarcel Holtmann 
1087533553f8SMarcel Holtmann 	hci_dev_lock(hdev);
1088533553f8SMarcel Holtmann 
1089533553f8SMarcel Holtmann 	hdev->le_scan_type = cp->type;
1090533553f8SMarcel Holtmann 
1091533553f8SMarcel Holtmann 	hci_dev_unlock(hdev);
1092533553f8SMarcel Holtmann }
1093533553f8SMarcel Holtmann 
1094b9a6328fSJohan Hedberg static bool has_pending_adv_report(struct hci_dev *hdev)
1095b9a6328fSJohan Hedberg {
1096b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1097b9a6328fSJohan Hedberg 
1098b9a6328fSJohan Hedberg 	return bacmp(&d->last_adv_addr, BDADDR_ANY);
1099b9a6328fSJohan Hedberg }
1100b9a6328fSJohan Hedberg 
1101b9a6328fSJohan Hedberg static void clear_pending_adv_report(struct hci_dev *hdev)
1102b9a6328fSJohan Hedberg {
1103b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1104b9a6328fSJohan Hedberg 
1105b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, BDADDR_ANY);
1106b9a6328fSJohan Hedberg 	d->last_adv_data_len = 0;
1107b9a6328fSJohan Hedberg }
1108b9a6328fSJohan Hedberg 
1109b9a6328fSJohan Hedberg static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
1110c70a7e4cSMarcel Holtmann 				     u8 bdaddr_type, s8 rssi, u32 flags,
1111c70a7e4cSMarcel Holtmann 				     u8 *data, u8 len)
1112b9a6328fSJohan Hedberg {
1113b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1114b9a6328fSJohan Hedberg 
1115b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, bdaddr);
1116b9a6328fSJohan Hedberg 	d->last_adv_addr_type = bdaddr_type;
1117ff5cd29fSJohan Hedberg 	d->last_adv_rssi = rssi;
1118c70a7e4cSMarcel Holtmann 	d->last_adv_flags = flags;
1119b9a6328fSJohan Hedberg 	memcpy(d->last_adv_data, data, len);
1120b9a6328fSJohan Hedberg 	d->last_adv_data_len = len;
1121b9a6328fSJohan Hedberg }
1122b9a6328fSJohan Hedberg 
1123eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1124eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1125eb9d91f5SAndre Guedes {
1126eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1127eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1128eb9d91f5SAndre Guedes 
11299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1130eb9d91f5SAndre Guedes 
113145296acdSMarcel Holtmann 	if (status)
1132eb9d91f5SAndre Guedes 		return;
1133eb9d91f5SAndre Guedes 
113445296acdSMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
113545296acdSMarcel Holtmann 	if (!cp)
11367ba8b4beSAndre Guedes 		return;
11377ba8b4beSAndre Guedes 
11383fd319b8SAndre Guedes 	switch (cp->enable) {
11393fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
1140d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1141b9a6328fSJohan Hedberg 		if (hdev->le_scan_type == LE_SCAN_ACTIVE)
1142b9a6328fSJohan Hedberg 			clear_pending_adv_report(hdev);
114368a8aea4SAndrei Emeltchenko 		break;
114468a8aea4SAndrei Emeltchenko 
114576a388beSAndre Guedes 	case LE_SCAN_DISABLE:
1146b9a6328fSJohan Hedberg 		/* We do this here instead of when setting DISCOVERY_STOPPED
1147b9a6328fSJohan Hedberg 		 * since the latter would potentially require waiting for
1148b9a6328fSJohan Hedberg 		 * inquiry to stop too.
1149b9a6328fSJohan Hedberg 		 */
1150b9a6328fSJohan Hedberg 		if (has_pending_adv_report(hdev)) {
1151b9a6328fSJohan Hedberg 			struct discovery_state *d = &hdev->discovery;
1152b9a6328fSJohan Hedberg 
1153b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
1154ab0aa433SJohan Hedberg 					  d->last_adv_addr_type, NULL,
1155c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
1156ab0aa433SJohan Hedberg 					  d->last_adv_data,
1157b9a6328fSJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
1158b9a6328fSJohan Hedberg 		}
1159b9a6328fSJohan Hedberg 
1160317ac8cbSJohan Hedberg 		/* Cancel this timer so that we don't try to disable scanning
1161317ac8cbSJohan Hedberg 		 * when it's already disabled.
1162317ac8cbSJohan Hedberg 		 */
1163317ac8cbSJohan Hedberg 		cancel_delayed_work(&hdev->le_scan_disable);
1164317ac8cbSJohan Hedberg 
1165d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1166e8bb6b97SJohan Hedberg 
116781ad6fd9SJohan Hedberg 		/* The HCI_LE_SCAN_INTERRUPTED flag indicates that we
116881ad6fd9SJohan Hedberg 		 * interrupted scanning due to a connect request. Mark
1169e8bb6b97SJohan Hedberg 		 * therefore discovery as stopped. If this was not
1170e8bb6b97SJohan Hedberg 		 * because of a connect request advertising might have
1171e8bb6b97SJohan Hedberg 		 * been disabled because of active scanning, so
1172e8bb6b97SJohan Hedberg 		 * re-enable it again if necessary.
117381ad6fd9SJohan Hedberg 		 */
117481ad6fd9SJohan Hedberg 		if (test_and_clear_bit(HCI_LE_SCAN_INTERRUPTED,
117581ad6fd9SJohan Hedberg 				       &hdev->dev_flags))
117681ad6fd9SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1177e8bb6b97SJohan Hedberg 		else if (!test_bit(HCI_LE_ADV, &hdev->dev_flags) &&
117834722277SJohan Hedberg 			 hdev->discovery.state == DISCOVERY_FINDING)
1179e8bb6b97SJohan Hedberg 			mgmt_reenable_advertising(hdev);
1180e8bb6b97SJohan Hedberg 
118168a8aea4SAndrei Emeltchenko 		break;
118268a8aea4SAndrei Emeltchenko 
118368a8aea4SAndrei Emeltchenko 	default:
118468a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
118568a8aea4SAndrei Emeltchenko 		break;
118635815085SAndre Guedes 	}
1187eb9d91f5SAndre Guedes }
1188eb9d91f5SAndre Guedes 
1189cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1190cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
1191cf1d081fSJohan Hedberg {
1192cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1193cf1d081fSJohan Hedberg 
1194cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1195cf1d081fSJohan Hedberg 
119645296acdSMarcel Holtmann 	if (rp->status)
119745296acdSMarcel Holtmann 		return;
119845296acdSMarcel Holtmann 
1199cf1d081fSJohan Hedberg 	hdev->le_white_list_size = rp->size;
1200cf1d081fSJohan Hedberg }
1201cf1d081fSJohan Hedberg 
12020f36b589SMarcel Holtmann static void hci_cc_le_clear_white_list(struct hci_dev *hdev,
12030f36b589SMarcel Holtmann 				       struct sk_buff *skb)
12040f36b589SMarcel Holtmann {
12050f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12060f36b589SMarcel Holtmann 
12070f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12080f36b589SMarcel Holtmann 
120945296acdSMarcel Holtmann 	if (status)
121045296acdSMarcel Holtmann 		return;
121145296acdSMarcel Holtmann 
1212dcc36c16SJohan Hedberg 	hci_bdaddr_list_clear(&hdev->le_white_list);
12130f36b589SMarcel Holtmann }
12140f36b589SMarcel Holtmann 
12150f36b589SMarcel Holtmann static void hci_cc_le_add_to_white_list(struct hci_dev *hdev,
12160f36b589SMarcel Holtmann 					struct sk_buff *skb)
12170f36b589SMarcel Holtmann {
12180f36b589SMarcel Holtmann 	struct hci_cp_le_add_to_white_list *sent;
12190f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12200f36b589SMarcel Holtmann 
12210f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12220f36b589SMarcel Holtmann 
122345296acdSMarcel Holtmann 	if (status)
122445296acdSMarcel Holtmann 		return;
122545296acdSMarcel Holtmann 
12260f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST);
12270f36b589SMarcel Holtmann 	if (!sent)
12280f36b589SMarcel Holtmann 		return;
12290f36b589SMarcel Holtmann 
1230dcc36c16SJohan Hedberg 	hci_bdaddr_list_add(&hdev->le_white_list, &sent->bdaddr,
1231dcc36c16SJohan Hedberg 			   sent->bdaddr_type);
12320f36b589SMarcel Holtmann }
12330f36b589SMarcel Holtmann 
12340f36b589SMarcel Holtmann static void hci_cc_le_del_from_white_list(struct hci_dev *hdev,
12350f36b589SMarcel Holtmann 					  struct sk_buff *skb)
12360f36b589SMarcel Holtmann {
12370f36b589SMarcel Holtmann 	struct hci_cp_le_del_from_white_list *sent;
12380f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12390f36b589SMarcel Holtmann 
12400f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12410f36b589SMarcel Holtmann 
124245296acdSMarcel Holtmann 	if (status)
124345296acdSMarcel Holtmann 		return;
124445296acdSMarcel Holtmann 
12450f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST);
12460f36b589SMarcel Holtmann 	if (!sent)
12470f36b589SMarcel Holtmann 		return;
12480f36b589SMarcel Holtmann 
1249dcc36c16SJohan Hedberg 	hci_bdaddr_list_del(&hdev->le_white_list, &sent->bdaddr,
1250dcc36c16SJohan Hedberg 			    sent->bdaddr_type);
12510f36b589SMarcel Holtmann }
12520f36b589SMarcel Holtmann 
12539b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
12549b008c04SJohan Hedberg 					    struct sk_buff *skb)
12559b008c04SJohan Hedberg {
12569b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
12579b008c04SJohan Hedberg 
12589b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
12599b008c04SJohan Hedberg 
126045296acdSMarcel Holtmann 	if (rp->status)
126145296acdSMarcel Holtmann 		return;
126245296acdSMarcel Holtmann 
12639b008c04SJohan Hedberg 	memcpy(hdev->le_states, rp->le_states, 8);
12649b008c04SJohan Hedberg }
12659b008c04SJohan Hedberg 
12666039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1267f9b49306SAndre Guedes 					   struct sk_buff *skb)
1268f9b49306SAndre Guedes {
126906199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1270f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1271f9b49306SAndre Guedes 
12729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1273f9b49306SAndre Guedes 
127445296acdSMarcel Holtmann 	if (status)
127545296acdSMarcel Holtmann 		return;
127645296acdSMarcel Holtmann 
127706199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
12788f984dfaSJohan Hedberg 	if (!sent)
1279f9b49306SAndre Guedes 		return;
1280f9b49306SAndre Guedes 
1281416a4ae5SJohan Hedberg 	if (sent->le) {
1282cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE;
1283416a4ae5SJohan Hedberg 		set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1284416a4ae5SJohan Hedberg 	} else {
1285cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE;
1286416a4ae5SJohan Hedberg 		clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1287f3d3444aSJohan Hedberg 		clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1288416a4ae5SJohan Hedberg 	}
128953b2caabSJohan Hedberg 
129053b2caabSJohan Hedberg 	if (sent->simul)
1291cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE_BREDR;
129253b2caabSJohan Hedberg 	else
1293cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
12948f984dfaSJohan Hedberg }
1295f9b49306SAndre Guedes 
129656ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
129756ed2cb8SJohan Hedberg {
129856ed2cb8SJohan Hedberg 	struct hci_cp_le_set_adv_param *cp;
129956ed2cb8SJohan Hedberg 	u8 status = *((u8 *) skb->data);
130056ed2cb8SJohan Hedberg 
130156ed2cb8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
130256ed2cb8SJohan Hedberg 
130356ed2cb8SJohan Hedberg 	if (status)
130456ed2cb8SJohan Hedberg 		return;
130556ed2cb8SJohan Hedberg 
130656ed2cb8SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
130756ed2cb8SJohan Hedberg 	if (!cp)
130856ed2cb8SJohan Hedberg 		return;
130956ed2cb8SJohan Hedberg 
131056ed2cb8SJohan Hedberg 	hci_dev_lock(hdev);
131156ed2cb8SJohan Hedberg 	hdev->adv_addr_type = cp->own_address_type;
131256ed2cb8SJohan Hedberg 	hci_dev_unlock(hdev);
131356ed2cb8SJohan Hedberg }
131456ed2cb8SJohan Hedberg 
131593c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
131693c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
131793c284eeSAndrei Emeltchenko {
131893c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
131993c284eeSAndrei Emeltchenko 
132093c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
132193c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
132293c284eeSAndrei Emeltchenko 
132393c284eeSAndrei Emeltchenko 	if (rp->status)
132493c284eeSAndrei Emeltchenko 		return;
132593c284eeSAndrei Emeltchenko 
132693c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
132793c284eeSAndrei Emeltchenko }
132893c284eeSAndrei Emeltchenko 
13295ae76a94SAndrzej Kaczmarek static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
13305ae76a94SAndrzej Kaczmarek {
13315ae76a94SAndrzej Kaczmarek 	struct hci_rp_read_rssi *rp = (void *) skb->data;
13325ae76a94SAndrzej Kaczmarek 	struct hci_conn *conn;
13335ae76a94SAndrzej Kaczmarek 
13345ae76a94SAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
13355ae76a94SAndrzej Kaczmarek 
13365ae76a94SAndrzej Kaczmarek 	if (rp->status)
13375ae76a94SAndrzej Kaczmarek 		return;
13385ae76a94SAndrzej Kaczmarek 
13395ae76a94SAndrzej Kaczmarek 	hci_dev_lock(hdev);
13405ae76a94SAndrzej Kaczmarek 
13415ae76a94SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
13425ae76a94SAndrzej Kaczmarek 	if (conn)
13435ae76a94SAndrzej Kaczmarek 		conn->rssi = rp->rssi;
13445ae76a94SAndrzej Kaczmarek 
13455ae76a94SAndrzej Kaczmarek 	hci_dev_unlock(hdev);
13465ae76a94SAndrzej Kaczmarek }
13475ae76a94SAndrzej Kaczmarek 
13485a134faeSAndrzej Kaczmarek static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb)
13495a134faeSAndrzej Kaczmarek {
13505a134faeSAndrzej Kaczmarek 	struct hci_cp_read_tx_power *sent;
13515a134faeSAndrzej Kaczmarek 	struct hci_rp_read_tx_power *rp = (void *) skb->data;
13525a134faeSAndrzej Kaczmarek 	struct hci_conn *conn;
13535a134faeSAndrzej Kaczmarek 
13545a134faeSAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
13555a134faeSAndrzej Kaczmarek 
13565a134faeSAndrzej Kaczmarek 	if (rp->status)
13575a134faeSAndrzej Kaczmarek 		return;
13585a134faeSAndrzej Kaczmarek 
13595a134faeSAndrzej Kaczmarek 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
13605a134faeSAndrzej Kaczmarek 	if (!sent)
13615a134faeSAndrzej Kaczmarek 		return;
13625a134faeSAndrzej Kaczmarek 
13635a134faeSAndrzej Kaczmarek 	hci_dev_lock(hdev);
13645a134faeSAndrzej Kaczmarek 
13655a134faeSAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1366d0455ed9SAndrzej Kaczmarek 	if (!conn)
1367d0455ed9SAndrzej Kaczmarek 		goto unlock;
13685a134faeSAndrzej Kaczmarek 
1369d0455ed9SAndrzej Kaczmarek 	switch (sent->type) {
1370d0455ed9SAndrzej Kaczmarek 	case 0x00:
1371d0455ed9SAndrzej Kaczmarek 		conn->tx_power = rp->tx_power;
1372d0455ed9SAndrzej Kaczmarek 		break;
1373d0455ed9SAndrzej Kaczmarek 	case 0x01:
1374d0455ed9SAndrzej Kaczmarek 		conn->max_tx_power = rp->tx_power;
1375d0455ed9SAndrzej Kaczmarek 		break;
1376d0455ed9SAndrzej Kaczmarek 	}
1377d0455ed9SAndrzej Kaczmarek 
1378d0455ed9SAndrzej Kaczmarek unlock:
13795a134faeSAndrzej Kaczmarek 	hci_dev_unlock(hdev);
13805a134faeSAndrzej Kaczmarek }
13815a134faeSAndrzej Kaczmarek 
13826039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1383a9de9248SMarcel Holtmann {
13849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1385a9de9248SMarcel Holtmann 
1386a9de9248SMarcel Holtmann 	if (status) {
1387a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1388314b2381SJohan Hedberg 		return;
1389314b2381SJohan Hedberg 	}
1390314b2381SJohan Hedberg 
139189352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1392a9de9248SMarcel Holtmann }
1393a9de9248SMarcel Holtmann 
13946039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
13951da177e4SLinus Torvalds {
1396a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
13971da177e4SLinus Torvalds 	struct hci_conn *conn;
13981da177e4SLinus Torvalds 
13999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1400a9de9248SMarcel Holtmann 
1401a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
14021da177e4SLinus Torvalds 	if (!cp)
14031da177e4SLinus Torvalds 		return;
14041da177e4SLinus Torvalds 
14051da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14061da177e4SLinus Torvalds 
14071da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
14081da177e4SLinus Torvalds 
14096ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
14101da177e4SLinus Torvalds 
14111da177e4SLinus Torvalds 	if (status) {
14121da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
14134c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
14141da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
14151da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
14161da177e4SLinus Torvalds 				hci_conn_del(conn);
14174c67bc74SMarcel Holtmann 			} else
14184c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
14191da177e4SLinus Torvalds 		}
14201da177e4SLinus Torvalds 	} else {
14211da177e4SLinus Torvalds 		if (!conn) {
1422a5c4e309SJohan Hedberg 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr,
1423a5c4e309SJohan Hedberg 					    HCI_ROLE_MASTER);
1424a5c4e309SJohan Hedberg 			if (!conn)
1425893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
14261da177e4SLinus Torvalds 		}
14271da177e4SLinus Torvalds 	}
14281da177e4SLinus Torvalds 
14291da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14301da177e4SLinus Torvalds }
14311da177e4SLinus Torvalds 
1432a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
14331da177e4SLinus Torvalds {
1434a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
14351da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
14361da177e4SLinus Torvalds 	__u16 handle;
14371da177e4SLinus Torvalds 
14389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1439b6a0dc82SMarcel Holtmann 
1440a9de9248SMarcel Holtmann 	if (!status)
1441a9de9248SMarcel Holtmann 		return;
1442a9de9248SMarcel Holtmann 
1443a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
14441da177e4SLinus Torvalds 	if (!cp)
1445a9de9248SMarcel Holtmann 		return;
14461da177e4SLinus Torvalds 
14471da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
14481da177e4SLinus Torvalds 
14499f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
14501da177e4SLinus Torvalds 
14511da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14521da177e4SLinus Torvalds 
14531da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14545a08ecceSAndrei Emeltchenko 	if (acl) {
14555a08ecceSAndrei Emeltchenko 		sco = acl->link;
14565a08ecceSAndrei Emeltchenko 		if (sco) {
14571da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
14581da177e4SLinus Torvalds 
14591da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
14601da177e4SLinus Torvalds 			hci_conn_del(sco);
14611da177e4SLinus Torvalds 		}
14625a08ecceSAndrei Emeltchenko 	}
14631da177e4SLinus Torvalds 
14641da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14651da177e4SLinus Torvalds }
14661da177e4SLinus Torvalds 
1467f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1468f8558555SMarcel Holtmann {
1469f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1470f8558555SMarcel Holtmann 	struct hci_conn *conn;
1471f8558555SMarcel Holtmann 
14729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1473f8558555SMarcel Holtmann 
1474f8558555SMarcel Holtmann 	if (!status)
1475f8558555SMarcel Holtmann 		return;
1476f8558555SMarcel Holtmann 
1477f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1478f8558555SMarcel Holtmann 	if (!cp)
1479f8558555SMarcel Holtmann 		return;
1480f8558555SMarcel Holtmann 
1481f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1482f8558555SMarcel Holtmann 
1483f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1484f8558555SMarcel Holtmann 	if (conn) {
1485f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1486f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
148776a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1488f8558555SMarcel Holtmann 		}
1489f8558555SMarcel Holtmann 	}
1490f8558555SMarcel Holtmann 
1491f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1492f8558555SMarcel Holtmann }
1493f8558555SMarcel Holtmann 
1494f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1495f8558555SMarcel Holtmann {
1496f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1497f8558555SMarcel Holtmann 	struct hci_conn *conn;
1498f8558555SMarcel Holtmann 
14999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1500f8558555SMarcel Holtmann 
1501f8558555SMarcel Holtmann 	if (!status)
1502f8558555SMarcel Holtmann 		return;
1503f8558555SMarcel Holtmann 
1504f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1505f8558555SMarcel Holtmann 	if (!cp)
1506f8558555SMarcel Holtmann 		return;
1507f8558555SMarcel Holtmann 
1508f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1509f8558555SMarcel Holtmann 
1510f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1511f8558555SMarcel Holtmann 	if (conn) {
1512f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1513f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
151476a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1515f8558555SMarcel Holtmann 		}
1516f8558555SMarcel Holtmann 	}
1517f8558555SMarcel Holtmann 
1518f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1519f8558555SMarcel Holtmann }
1520f8558555SMarcel Holtmann 
1521127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1522392599b9SJohan Hedberg 				    struct hci_conn *conn)
1523392599b9SJohan Hedberg {
1524392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1525392599b9SJohan Hedberg 		return 0;
1526392599b9SJohan Hedberg 
1527765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1528392599b9SJohan Hedberg 		return 0;
1529392599b9SJohan Hedberg 
1530392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1531264b8b4eSJohan Hedberg 	 * devices with sec_level MEDIUM or HIGH or if MITM protection
1532264b8b4eSJohan Hedberg 	 * is requested.
1533264b8b4eSJohan Hedberg 	 */
1534807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
15357e3691e1SJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_FIPS &&
1536264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
1537264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
1538392599b9SJohan Hedberg 		return 0;
1539392599b9SJohan Hedberg 
1540392599b9SJohan Hedberg 	return 1;
1541392599b9SJohan Hedberg }
1542392599b9SJohan Hedberg 
15436039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
154400abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
154530dc78e1SJohan Hedberg {
154630dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
154730dc78e1SJohan Hedberg 
154830dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
154930dc78e1SJohan Hedberg 
155030dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
155130dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
155230dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
155330dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
155430dc78e1SJohan Hedberg 
155530dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
155630dc78e1SJohan Hedberg }
155730dc78e1SJohan Hedberg 
1558b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
155930dc78e1SJohan Hedberg {
156030dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
156130dc78e1SJohan Hedberg 	struct inquiry_entry *e;
156230dc78e1SJohan Hedberg 
1563b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1564b644ba33SJohan Hedberg 		return false;
1565b644ba33SJohan Hedberg 
1566b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1567c810089cSRam Malovany 	if (!e)
1568c810089cSRam Malovany 		return false;
1569c810089cSRam Malovany 
1570b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1571b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1572b644ba33SJohan Hedberg 		return true;
1573b644ba33SJohan Hedberg 	}
1574b644ba33SJohan Hedberg 
1575b644ba33SJohan Hedberg 	return false;
1576b644ba33SJohan Hedberg }
1577b644ba33SJohan Hedberg 
1578b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1579b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1580b644ba33SJohan Hedberg {
1581b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1582b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1583b644ba33SJohan Hedberg 
1584b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
158548ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, name, name_len);
1586b644ba33SJohan Hedberg 
1587b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1588b644ba33SJohan Hedberg 		return;
1589b644ba33SJohan Hedberg 
159030dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
159130dc78e1SJohan Hedberg 		goto discov_complete;
159230dc78e1SJohan Hedberg 
159330dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
159430dc78e1SJohan Hedberg 		return;
159530dc78e1SJohan Hedberg 
159630dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
15977cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
15987cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
15997cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
16007cc8380eSRam Malovany 	 * Event */
16017cc8380eSRam Malovany 	if (!e)
16027cc8380eSRam Malovany 		return;
16037cc8380eSRam Malovany 
160430dc78e1SJohan Hedberg 	list_del(&e->list);
16057cc8380eSRam Malovany 	if (name) {
16067cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1607b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1608b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1609c3e7c0d9SRam Malovany 	} else {
1610c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
161130dc78e1SJohan Hedberg 	}
161230dc78e1SJohan Hedberg 
1613b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
161430dc78e1SJohan Hedberg 		return;
161530dc78e1SJohan Hedberg 
161630dc78e1SJohan Hedberg discov_complete:
161730dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
161830dc78e1SJohan Hedberg }
161930dc78e1SJohan Hedberg 
1620a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
16211da177e4SLinus Torvalds {
1622127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1623127178d2SJohan Hedberg 	struct hci_conn *conn;
1624127178d2SJohan Hedberg 
16259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1626127178d2SJohan Hedberg 
1627127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1628127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1629127178d2SJohan Hedberg 	if (!status)
1630127178d2SJohan Hedberg 		return;
1631127178d2SJohan Hedberg 
1632127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1633127178d2SJohan Hedberg 	if (!cp)
1634127178d2SJohan Hedberg 		return;
1635127178d2SJohan Hedberg 
1636127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1637127178d2SJohan Hedberg 
1638127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1639b644ba33SJohan Hedberg 
1640b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1641b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1642b644ba33SJohan Hedberg 
164379c6c70cSJohan Hedberg 	if (!conn)
164479c6c70cSJohan Hedberg 		goto unlock;
164579c6c70cSJohan Hedberg 
164679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
164779c6c70cSJohan Hedberg 		goto unlock;
164879c6c70cSJohan Hedberg 
164951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1650c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
1651c1f23a2bSJohannes Berg 
1652977f8fceSJohan Hedberg 		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
1653977f8fceSJohan Hedberg 
1654c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
1655c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1656c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
1657127178d2SJohan Hedberg 	}
1658127178d2SJohan Hedberg 
165979c6c70cSJohan Hedberg unlock:
1660127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1661a9de9248SMarcel Holtmann }
16621da177e4SLinus Torvalds 
1663769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1664769be974SMarcel Holtmann {
1665769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1666769be974SMarcel Holtmann 	struct hci_conn *conn;
1667769be974SMarcel Holtmann 
16689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1669769be974SMarcel Holtmann 
1670769be974SMarcel Holtmann 	if (!status)
1671769be974SMarcel Holtmann 		return;
1672769be974SMarcel Holtmann 
1673769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1674769be974SMarcel Holtmann 	if (!cp)
1675769be974SMarcel Holtmann 		return;
1676769be974SMarcel Holtmann 
1677769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1678769be974SMarcel Holtmann 
1679769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1680769be974SMarcel Holtmann 	if (conn) {
1681769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1682769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
168376a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1684769be974SMarcel Holtmann 		}
1685769be974SMarcel Holtmann 	}
1686769be974SMarcel Holtmann 
1687769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1688769be974SMarcel Holtmann }
1689769be974SMarcel Holtmann 
1690769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1691769be974SMarcel Holtmann {
1692769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1693769be974SMarcel Holtmann 	struct hci_conn *conn;
1694769be974SMarcel Holtmann 
16959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1696769be974SMarcel Holtmann 
1697769be974SMarcel Holtmann 	if (!status)
1698769be974SMarcel Holtmann 		return;
1699769be974SMarcel Holtmann 
1700769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1701769be974SMarcel Holtmann 	if (!cp)
1702769be974SMarcel Holtmann 		return;
1703769be974SMarcel Holtmann 
1704769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1705769be974SMarcel Holtmann 
1706769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1707769be974SMarcel Holtmann 	if (conn) {
1708769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1709769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
171076a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1711769be974SMarcel Holtmann 		}
1712769be974SMarcel Holtmann 	}
1713769be974SMarcel Holtmann 
1714769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1715769be974SMarcel Holtmann }
1716769be974SMarcel Holtmann 
1717a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1718a9de9248SMarcel Holtmann {
1719b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1720b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1721b6a0dc82SMarcel Holtmann 	__u16 handle;
1722b6a0dc82SMarcel Holtmann 
17239f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1724b6a0dc82SMarcel Holtmann 
1725b6a0dc82SMarcel Holtmann 	if (!status)
1726b6a0dc82SMarcel Holtmann 		return;
1727b6a0dc82SMarcel Holtmann 
1728b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1729b6a0dc82SMarcel Holtmann 	if (!cp)
1730b6a0dc82SMarcel Holtmann 		return;
1731b6a0dc82SMarcel Holtmann 
1732b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1733b6a0dc82SMarcel Holtmann 
17349f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1735b6a0dc82SMarcel Holtmann 
1736b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1737b6a0dc82SMarcel Holtmann 
1738b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
17395a08ecceSAndrei Emeltchenko 	if (acl) {
17405a08ecceSAndrei Emeltchenko 		sco = acl->link;
17415a08ecceSAndrei Emeltchenko 		if (sco) {
1742b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1743b6a0dc82SMarcel Holtmann 
1744b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1745b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1746b6a0dc82SMarcel Holtmann 		}
17475a08ecceSAndrei Emeltchenko 	}
1748b6a0dc82SMarcel Holtmann 
1749b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1750a9de9248SMarcel Holtmann }
1751a9de9248SMarcel Holtmann 
1752a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1753a9de9248SMarcel Holtmann {
1754a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
175504837f64SMarcel Holtmann 	struct hci_conn *conn;
175604837f64SMarcel Holtmann 
17579f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1758a9de9248SMarcel Holtmann 
1759a9de9248SMarcel Holtmann 	if (!status)
1760a9de9248SMarcel Holtmann 		return;
1761a9de9248SMarcel Holtmann 
1762a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
176304837f64SMarcel Holtmann 	if (!cp)
1764a9de9248SMarcel Holtmann 		return;
176504837f64SMarcel Holtmann 
176604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
176704837f64SMarcel Holtmann 
176804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1769e73439d8SMarcel Holtmann 	if (conn) {
177051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
177104837f64SMarcel Holtmann 
177251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1773e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1774e73439d8SMarcel Holtmann 	}
1775e73439d8SMarcel Holtmann 
177604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
177704837f64SMarcel Holtmann }
177804837f64SMarcel Holtmann 
1779a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1780a9de9248SMarcel Holtmann {
1781a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
178204837f64SMarcel Holtmann 	struct hci_conn *conn;
178304837f64SMarcel Holtmann 
17849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1785a9de9248SMarcel Holtmann 
1786a9de9248SMarcel Holtmann 	if (!status)
1787a9de9248SMarcel Holtmann 		return;
1788a9de9248SMarcel Holtmann 
1789a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
179004837f64SMarcel Holtmann 	if (!cp)
1791a9de9248SMarcel Holtmann 		return;
179204837f64SMarcel Holtmann 
179304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
179404837f64SMarcel Holtmann 
179504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1796e73439d8SMarcel Holtmann 	if (conn) {
179751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
179804837f64SMarcel Holtmann 
179951a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1800e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1801e73439d8SMarcel Holtmann 	}
1802e73439d8SMarcel Holtmann 
180304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
180404837f64SMarcel Holtmann }
180504837f64SMarcel Holtmann 
180688c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
180788c3df13SJohan Hedberg {
180888c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
180988c3df13SJohan Hedberg 	struct hci_conn *conn;
181088c3df13SJohan Hedberg 
181188c3df13SJohan Hedberg 	if (!status)
181288c3df13SJohan Hedberg 		return;
181388c3df13SJohan Hedberg 
181488c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
181588c3df13SJohan Hedberg 	if (!cp)
181688c3df13SJohan Hedberg 		return;
181788c3df13SJohan Hedberg 
181888c3df13SJohan Hedberg 	hci_dev_lock(hdev);
181988c3df13SJohan Hedberg 
182088c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
182188c3df13SJohan Hedberg 	if (conn)
182288c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
182388c3df13SJohan Hedberg 				       conn->dst_type, status);
182488c3df13SJohan Hedberg 
182588c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
182688c3df13SJohan Hedberg }
182788c3df13SJohan Hedberg 
1828a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1829a02226d6SAndrei Emeltchenko {
183093c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
183193c284eeSAndrei Emeltchenko 
1832a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
183393c284eeSAndrei Emeltchenko 
183493c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
183593c284eeSAndrei Emeltchenko 	if (!cp)
183693c284eeSAndrei Emeltchenko 		return;
183793c284eeSAndrei Emeltchenko 
1838e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1839e58917b9SAndrei Emeltchenko 
1840e58917b9SAndrei Emeltchenko 	if (status) {
1841e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1842e58917b9SAndrei Emeltchenko 
1843e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1844e58917b9SAndrei Emeltchenko 		if (hcon)
1845e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1846e58917b9SAndrei Emeltchenko 	} else {
184793c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1848a02226d6SAndrei Emeltchenko 	}
1849a02226d6SAndrei Emeltchenko 
1850e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1851e58917b9SAndrei Emeltchenko }
1852e58917b9SAndrei Emeltchenko 
18530b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
18540b26ab9dSAndrei Emeltchenko {
18550b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
18560b26ab9dSAndrei Emeltchenko 
18570b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18580b26ab9dSAndrei Emeltchenko 
18590b26ab9dSAndrei Emeltchenko 	if (status)
18600b26ab9dSAndrei Emeltchenko 		return;
18610b26ab9dSAndrei Emeltchenko 
18620b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
18630b26ab9dSAndrei Emeltchenko 	if (!cp)
18640b26ab9dSAndrei Emeltchenko 		return;
18650b26ab9dSAndrei Emeltchenko 
18660b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
18670b26ab9dSAndrei Emeltchenko }
18680b26ab9dSAndrei Emeltchenko 
1869cb1d68f7SJohan Hedberg static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
1870cb1d68f7SJohan Hedberg {
1871cb1d68f7SJohan Hedberg 	struct hci_cp_le_create_conn *cp;
1872cb1d68f7SJohan Hedberg 	struct hci_conn *conn;
1873cb1d68f7SJohan Hedberg 
1874cb1d68f7SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1875cb1d68f7SJohan Hedberg 
1876cb1d68f7SJohan Hedberg 	/* All connection failure handling is taken care of by the
1877cb1d68f7SJohan Hedberg 	 * hci_le_conn_failed function which is triggered by the HCI
1878cb1d68f7SJohan Hedberg 	 * request completion callbacks used for connecting.
1879cb1d68f7SJohan Hedberg 	 */
1880cb1d68f7SJohan Hedberg 	if (status)
1881cb1d68f7SJohan Hedberg 		return;
1882cb1d68f7SJohan Hedberg 
1883cb1d68f7SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1884cb1d68f7SJohan Hedberg 	if (!cp)
1885cb1d68f7SJohan Hedberg 		return;
1886cb1d68f7SJohan Hedberg 
1887cb1d68f7SJohan Hedberg 	hci_dev_lock(hdev);
1888cb1d68f7SJohan Hedberg 
1889cb1d68f7SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1890cb1d68f7SJohan Hedberg 	if (!conn)
1891cb1d68f7SJohan Hedberg 		goto unlock;
1892cb1d68f7SJohan Hedberg 
1893cb1d68f7SJohan Hedberg 	/* Store the initiator and responder address information which
1894cb1d68f7SJohan Hedberg 	 * is needed for SMP. These values will not change during the
1895cb1d68f7SJohan Hedberg 	 * lifetime of the connection.
1896cb1d68f7SJohan Hedberg 	 */
1897cb1d68f7SJohan Hedberg 	conn->init_addr_type = cp->own_address_type;
1898cb1d68f7SJohan Hedberg 	if (cp->own_address_type == ADDR_LE_DEV_RANDOM)
1899cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &hdev->random_addr);
1900cb1d68f7SJohan Hedberg 	else
1901cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &hdev->bdaddr);
1902cb1d68f7SJohan Hedberg 
1903cb1d68f7SJohan Hedberg 	conn->resp_addr_type = cp->peer_addr_type;
1904cb1d68f7SJohan Hedberg 	bacpy(&conn->resp_addr, &cp->peer_addr);
1905cb1d68f7SJohan Hedberg 
19069489eca4SJohan Hedberg 	/* We don't want the connection attempt to stick around
19079489eca4SJohan Hedberg 	 * indefinitely since LE doesn't have a page timeout concept
19089489eca4SJohan Hedberg 	 * like BR/EDR. Set a timer for any connection that doesn't use
19099489eca4SJohan Hedberg 	 * the white list for connecting.
19109489eca4SJohan Hedberg 	 */
19119489eca4SJohan Hedberg 	if (cp->filter_policy == HCI_LE_USE_PEER_ADDR)
19129489eca4SJohan Hedberg 		queue_delayed_work(conn->hdev->workqueue,
19139489eca4SJohan Hedberg 				   &conn->le_conn_timeout,
191409ae260bSJohan Hedberg 				   conn->conn_timeout);
19159489eca4SJohan Hedberg 
1916cb1d68f7SJohan Hedberg unlock:
1917cb1d68f7SJohan Hedberg 	hci_dev_unlock(hdev);
1918cb1d68f7SJohan Hedberg }
1919cb1d68f7SJohan Hedberg 
192081d0c8adSJohan Hedberg static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
192181d0c8adSJohan Hedberg {
192281d0c8adSJohan Hedberg 	struct hci_cp_le_start_enc *cp;
192381d0c8adSJohan Hedberg 	struct hci_conn *conn;
192481d0c8adSJohan Hedberg 
192581d0c8adSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
192681d0c8adSJohan Hedberg 
192781d0c8adSJohan Hedberg 	if (!status)
192881d0c8adSJohan Hedberg 		return;
192981d0c8adSJohan Hedberg 
193081d0c8adSJohan Hedberg 	hci_dev_lock(hdev);
193181d0c8adSJohan Hedberg 
193281d0c8adSJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC);
193381d0c8adSJohan Hedberg 	if (!cp)
193481d0c8adSJohan Hedberg 		goto unlock;
193581d0c8adSJohan Hedberg 
193681d0c8adSJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
193781d0c8adSJohan Hedberg 	if (!conn)
193881d0c8adSJohan Hedberg 		goto unlock;
193981d0c8adSJohan Hedberg 
194081d0c8adSJohan Hedberg 	if (conn->state != BT_CONNECTED)
194181d0c8adSJohan Hedberg 		goto unlock;
194281d0c8adSJohan Hedberg 
194381d0c8adSJohan Hedberg 	hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
194481d0c8adSJohan Hedberg 	hci_conn_drop(conn);
194581d0c8adSJohan Hedberg 
194681d0c8adSJohan Hedberg unlock:
194781d0c8adSJohan Hedberg 	hci_dev_unlock(hdev);
194881d0c8adSJohan Hedberg }
194981d0c8adSJohan Hedberg 
195050fc85f1SKuba Pawlak static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
195150fc85f1SKuba Pawlak {
195250fc85f1SKuba Pawlak 	struct hci_cp_switch_role *cp;
195350fc85f1SKuba Pawlak 	struct hci_conn *conn;
195450fc85f1SKuba Pawlak 
195550fc85f1SKuba Pawlak 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
195650fc85f1SKuba Pawlak 
195750fc85f1SKuba Pawlak 	if (!status)
195850fc85f1SKuba Pawlak 		return;
195950fc85f1SKuba Pawlak 
196050fc85f1SKuba Pawlak 	cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE);
196150fc85f1SKuba Pawlak 	if (!cp)
196250fc85f1SKuba Pawlak 		return;
196350fc85f1SKuba Pawlak 
196450fc85f1SKuba Pawlak 	hci_dev_lock(hdev);
196550fc85f1SKuba Pawlak 
196650fc85f1SKuba Pawlak 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
196750fc85f1SKuba Pawlak 	if (conn)
196850fc85f1SKuba Pawlak 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
196950fc85f1SKuba Pawlak 
197050fc85f1SKuba Pawlak 	hci_dev_unlock(hdev);
197150fc85f1SKuba Pawlak }
197250fc85f1SKuba Pawlak 
19736039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19741da177e4SLinus Torvalds {
19751da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
197630dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
197730dc78e1SJohan Hedberg 	struct inquiry_entry *e;
19781da177e4SLinus Torvalds 
19799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
19801da177e4SLinus Torvalds 
1981a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
198289352e7dSAndre Guedes 
198389352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
198489352e7dSAndre Guedes 		return;
198589352e7dSAndre Guedes 
19864e857c58SPeter Zijlstra 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
19873e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
19883e13fa1eSAndre Guedes 
1989a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
199030dc78e1SJohan Hedberg 		return;
199130dc78e1SJohan Hedberg 
199256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
199330dc78e1SJohan Hedberg 
1994343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
199530dc78e1SJohan Hedberg 		goto unlock;
199630dc78e1SJohan Hedberg 
199730dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1998ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
199930dc78e1SJohan Hedberg 		goto unlock;
200030dc78e1SJohan Hedberg 	}
200130dc78e1SJohan Hedberg 
200230dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
200330dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
200430dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
200530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
200630dc78e1SJohan Hedberg 	} else {
200730dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
200830dc78e1SJohan Hedberg 	}
200930dc78e1SJohan Hedberg 
201030dc78e1SJohan Hedberg unlock:
201156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
20121da177e4SLinus Torvalds }
20131da177e4SLinus Torvalds 
20146039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
20151da177e4SLinus Torvalds {
201645bb4bf0SMarcel Holtmann 	struct inquiry_data data;
2017a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
20181da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
20191da177e4SLinus Torvalds 
20201da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
20211da177e4SLinus Torvalds 
202245bb4bf0SMarcel Holtmann 	if (!num_rsp)
202345bb4bf0SMarcel Holtmann 		return;
202445bb4bf0SMarcel Holtmann 
20251519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
20261519cc17SAndre Guedes 		return;
20271519cc17SAndre Guedes 
20281da177e4SLinus Torvalds 	hci_dev_lock(hdev);
202945bb4bf0SMarcel Holtmann 
2030e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2031af58925cSMarcel Holtmann 		u32 flags;
20323175405bSJohan Hedberg 
20331da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
20341da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
20351da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
20361da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
20371da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
20381da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
20391da177e4SLinus Torvalds 		data.rssi		= 0x00;
204041a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
20413175405bSJohan Hedberg 
2042af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, false);
2043af58925cSMarcel Holtmann 
204448264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2045af58925cSMarcel Holtmann 				  info->dev_class, 0, flags, NULL, 0, NULL, 0);
20461da177e4SLinus Torvalds 	}
204745bb4bf0SMarcel Holtmann 
20481da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
20491da177e4SLinus Torvalds }
20501da177e4SLinus Torvalds 
20516039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
20521da177e4SLinus Torvalds {
2053a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
2054a9de9248SMarcel Holtmann 	struct hci_conn *conn;
20551da177e4SLinus Torvalds 
2056a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
205745bb4bf0SMarcel Holtmann 
20581da177e4SLinus Torvalds 	hci_dev_lock(hdev);
205945bb4bf0SMarcel Holtmann 
2060a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
20619499237aSMarcel Holtmann 	if (!conn) {
20629499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
20639499237aSMarcel Holtmann 			goto unlock;
20649499237aSMarcel Holtmann 
20659499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2066a9de9248SMarcel Holtmann 		if (!conn)
2067a9de9248SMarcel Holtmann 			goto unlock;
206845bb4bf0SMarcel Holtmann 
20699499237aSMarcel Holtmann 		conn->type = SCO_LINK;
20709499237aSMarcel Holtmann 	}
20719499237aSMarcel Holtmann 
2072a9de9248SMarcel Holtmann 	if (!ev->status) {
2073a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2074769be974SMarcel Holtmann 
2075769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2076769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
2077769be974SMarcel Holtmann 			hci_conn_hold(conn);
2078a9ea3ed9SSzymon Janc 
2079a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
2080a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
2081a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2082a9ea3ed9SSzymon Janc 			else
2083052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2084769be974SMarcel Holtmann 		} else
2085a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
2086a9de9248SMarcel Holtmann 
20877d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
20887d0db0a3SMarcel Holtmann 
2089a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
20904dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2091a9de9248SMarcel Holtmann 
2092a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
20934dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2094a9de9248SMarcel Holtmann 
2095a9de9248SMarcel Holtmann 		/* Get remote features */
2096a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2097a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
2098a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2099769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
2100769be974SMarcel Holtmann 				     sizeof(cp), &cp);
210122f433dcSJohan Hedberg 
210222f433dcSJohan Hedberg 			hci_update_page_scan(hdev, NULL);
210345bb4bf0SMarcel Holtmann 		}
2104a9de9248SMarcel Holtmann 
2105a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
2106d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
2107a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
2108a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2109a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
211004124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
211104124681SGustavo F. Padovan 				     &cp);
2112a9de9248SMarcel Holtmann 		}
211317d5c04cSJohan Hedberg 	} else {
2114a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
211517d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
211664c7b77cSMarcel Holtmann 			mgmt_connect_failed(hdev, &conn->dst, conn->type,
211748264f06SJohan Hedberg 					    conn->dst_type, ev->status);
211817d5c04cSJohan Hedberg 	}
211945bb4bf0SMarcel Holtmann 
2120e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
2121e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
212245bb4bf0SMarcel Holtmann 
2123769be974SMarcel Holtmann 	if (ev->status) {
2124a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2125a9de9248SMarcel Holtmann 		hci_conn_del(conn);
2126c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
2127c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2128a9de9248SMarcel Holtmann 
2129a9de9248SMarcel Holtmann unlock:
21301da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
2131a9de9248SMarcel Holtmann 
2132a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
21331da177e4SLinus Torvalds }
21341da177e4SLinus Torvalds 
213570c46425SJohan Hedberg static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr)
213670c46425SJohan Hedberg {
213770c46425SJohan Hedberg 	struct hci_cp_reject_conn_req cp;
213870c46425SJohan Hedberg 
213970c46425SJohan Hedberg 	bacpy(&cp.bdaddr, bdaddr);
214070c46425SJohan Hedberg 	cp.reason = HCI_ERROR_REJ_BAD_ADDR;
214170c46425SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
214270c46425SJohan Hedberg }
214370c46425SJohan Hedberg 
21446039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
21451da177e4SLinus Torvalds {
2146a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
21471da177e4SLinus Torvalds 	int mask = hdev->link_mode;
214870c46425SJohan Hedberg 	struct inquiry_entry *ie;
214970c46425SJohan Hedberg 	struct hci_conn *conn;
215020714bfeSFrédéric Dalleau 	__u8 flags = 0;
21511da177e4SLinus Torvalds 
21526ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
2153807deac2SGustavo Padovan 	       ev->link_type);
21541da177e4SLinus Torvalds 
215520714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
215620714bfeSFrédéric Dalleau 				      &flags);
21571da177e4SLinus Torvalds 
215870c46425SJohan Hedberg 	if (!(mask & HCI_LM_ACCEPT)) {
215970c46425SJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
216070c46425SJohan Hedberg 		return;
216170c46425SJohan Hedberg 	}
216270c46425SJohan Hedberg 
2163a55bd29dSJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr,
2164dcc36c16SJohan Hedberg 				   BDADDR_BREDR)) {
216570c46425SJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
216670c46425SJohan Hedberg 		return;
216770c46425SJohan Hedberg 	}
216846c4c941SJohan Hedberg 
216946c4c941SJohan Hedberg 	if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) &&
217046c4c941SJohan Hedberg 	    !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr,
2171a55bd29dSJohan Hedberg 				    BDADDR_BREDR)) {
2172a55bd29dSJohan Hedberg 		    hci_reject_conn(hdev, &ev->bdaddr);
2173a55bd29dSJohan Hedberg 		    return;
2174a55bd29dSJohan Hedberg 	}
217570c46425SJohan Hedberg 
21761da177e4SLinus Torvalds 	/* Connection accepted */
21771da177e4SLinus Torvalds 
21781da177e4SLinus Torvalds 	hci_dev_lock(hdev);
2179b6a0dc82SMarcel Holtmann 
2180cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2181cc11b9c1SAndrei Emeltchenko 	if (ie)
2182c7bdd502SMarcel Holtmann 		memcpy(ie->data.dev_class, ev->dev_class, 3);
2183c7bdd502SMarcel Holtmann 
21848fc9ced3SGustavo Padovan 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
21858fc9ced3SGustavo Padovan 			&ev->bdaddr);
21861da177e4SLinus Torvalds 	if (!conn) {
2187a5c4e309SJohan Hedberg 		conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
2188a5c4e309SJohan Hedberg 				    HCI_ROLE_SLAVE);
2189cc11b9c1SAndrei Emeltchenko 		if (!conn) {
2190893ef971SGustavo F. Padovan 			BT_ERR("No memory for new connection");
21911da177e4SLinus Torvalds 			hci_dev_unlock(hdev);
21921da177e4SLinus Torvalds 			return;
21931da177e4SLinus Torvalds 		}
21941da177e4SLinus Torvalds 	}
2195b6a0dc82SMarcel Holtmann 
21961da177e4SLinus Torvalds 	memcpy(conn->dev_class, ev->dev_class, 3);
2197b6a0dc82SMarcel Holtmann 
21981da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
21991da177e4SLinus Torvalds 
220020714bfeSFrédéric Dalleau 	if (ev->link_type == ACL_LINK ||
220120714bfeSFrédéric Dalleau 	    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
2202b6a0dc82SMarcel Holtmann 		struct hci_cp_accept_conn_req cp;
220320714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT;
2204b6a0dc82SMarcel Holtmann 
22051da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
22061da177e4SLinus Torvalds 
22071da177e4SLinus Torvalds 		if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
22081da177e4SLinus Torvalds 			cp.role = 0x00; /* Become master */
22091da177e4SLinus Torvalds 		else
22101da177e4SLinus Torvalds 			cp.role = 0x01; /* Remain slave */
22111da177e4SLinus Torvalds 
221270c46425SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
221320714bfeSFrédéric Dalleau 	} else if (!(flags & HCI_PROTO_DEFER)) {
2214b6a0dc82SMarcel Holtmann 		struct hci_cp_accept_sync_conn_req cp;
221520714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT;
2216b6a0dc82SMarcel Holtmann 
2217b6a0dc82SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
2218a8746417SMarcel Holtmann 		cp.pkt_type = cpu_to_le16(conn->pkt_type);
2219b6a0dc82SMarcel Holtmann 
2220dcf4adbfSJoe Perches 		cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
2221dcf4adbfSJoe Perches 		cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
2222dcf4adbfSJoe Perches 		cp.max_latency    = cpu_to_le16(0xffff);
2223b6a0dc82SMarcel Holtmann 		cp.content_format = cpu_to_le16(hdev->voice_setting);
2224b6a0dc82SMarcel Holtmann 		cp.retrans_effort = 0xff;
2225b6a0dc82SMarcel Holtmann 
222670c46425SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(cp),
222770c46425SJohan Hedberg 			     &cp);
222820714bfeSFrédéric Dalleau 	} else {
222920714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT2;
223020714bfeSFrédéric Dalleau 		hci_proto_connect_cfm(conn, 0);
2231b6a0dc82SMarcel Holtmann 	}
22321da177e4SLinus Torvalds }
22331da177e4SLinus Torvalds 
2234f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2235f0d6a0eaSMikel Astiz {
2236f0d6a0eaSMikel Astiz 	switch (err) {
2237f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2238f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2239f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2240f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2241f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2242f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2243f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2244f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2245f0d6a0eaSMikel Astiz 	default:
2246f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2247f0d6a0eaSMikel Astiz 	}
2248f0d6a0eaSMikel Astiz }
2249f0d6a0eaSMikel Astiz 
22506039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
22511da177e4SLinus Torvalds {
2252a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
2253abf54a50SAndre Guedes 	u8 reason = hci_to_mgmt_reason(ev->reason);
22549fcb18efSAndre Guedes 	struct hci_conn_params *params;
225504837f64SMarcel Holtmann 	struct hci_conn *conn;
225612d4a3b2SJohan Hedberg 	bool mgmt_connected;
22573846220bSAndre Guedes 	u8 type;
22581da177e4SLinus Torvalds 
22599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
22601da177e4SLinus Torvalds 
22611da177e4SLinus Torvalds 	hci_dev_lock(hdev);
22621da177e4SLinus Torvalds 
226304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2264f7520543SJohan Hedberg 	if (!conn)
2265f7520543SJohan Hedberg 		goto unlock;
2266f7520543SJohan Hedberg 
2267f0d6a0eaSMikel Astiz 	if (ev->status) {
226888c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
226988c3df13SJohan Hedberg 				       conn->dst_type, ev->status);
2270abf54a50SAndre Guedes 		goto unlock;
2271abf54a50SAndre Guedes 	}
2272f0d6a0eaSMikel Astiz 
22733846220bSAndre Guedes 	conn->state = BT_CLOSED;
22743846220bSAndre Guedes 
227512d4a3b2SJohan Hedberg 	mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
227612d4a3b2SJohan Hedberg 	mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
227712d4a3b2SJohan Hedberg 				reason, mgmt_connected);
2278f7520543SJohan Hedberg 
227922f433dcSJohan Hedberg 	if (conn->type == ACL_LINK) {
228022f433dcSJohan Hedberg 		if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
22816ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
22823846220bSAndre Guedes 
228322f433dcSJohan Hedberg 		hci_update_page_scan(hdev, NULL);
228422f433dcSJohan Hedberg 	}
228522f433dcSJohan Hedberg 
22869fcb18efSAndre Guedes 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
22879fcb18efSAndre Guedes 	if (params) {
22889fcb18efSAndre Guedes 		switch (params->auto_connect) {
22899fcb18efSAndre Guedes 		case HCI_AUTO_CONN_LINK_LOSS:
22909fcb18efSAndre Guedes 			if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
22919fcb18efSAndre Guedes 				break;
22929fcb18efSAndre Guedes 			/* Fall through */
22939fcb18efSAndre Guedes 
22944b9e7e75SMarcel Holtmann 		case HCI_AUTO_CONN_DIRECT:
22959fcb18efSAndre Guedes 		case HCI_AUTO_CONN_ALWAYS:
2296418025d1SJohan Hedberg 			list_del_init(&params->action);
2297418025d1SJohan Hedberg 			list_add(&params->action, &hdev->pend_le_conns);
2298418025d1SJohan Hedberg 			hci_update_background_scan(hdev);
22999fcb18efSAndre Guedes 			break;
23009fcb18efSAndre Guedes 
23019fcb18efSAndre Guedes 		default:
23029fcb18efSAndre Guedes 			break;
23039fcb18efSAndre Guedes 		}
23049fcb18efSAndre Guedes 	}
23059fcb18efSAndre Guedes 
23063846220bSAndre Guedes 	type = conn->type;
23073846220bSAndre Guedes 
23082950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
23091da177e4SLinus Torvalds 	hci_conn_del(conn);
23102210246cSJohan Hedberg 
23112210246cSJohan Hedberg 	/* Re-enable advertising if necessary, since it might
23122210246cSJohan Hedberg 	 * have been disabled by the connection. From the
23132210246cSJohan Hedberg 	 * HCI_LE_Set_Advertise_Enable command description in
23142210246cSJohan Hedberg 	 * the core specification (v4.0):
23152210246cSJohan Hedberg 	 * "The Controller shall continue advertising until the Host
23162210246cSJohan Hedberg 	 * issues an LE_Set_Advertise_Enable command with
23172210246cSJohan Hedberg 	 * Advertising_Enable set to 0x00 (Advertising is disabled)
23182210246cSJohan Hedberg 	 * or until a connection is created or until the Advertising
23192210246cSJohan Hedberg 	 * is timed out due to Directed Advertising."
23202210246cSJohan Hedberg 	 */
23212210246cSJohan Hedberg 	if (type == LE_LINK)
23225976e608SMarcel Holtmann 		mgmt_reenable_advertising(hdev);
23231da177e4SLinus Torvalds 
2324f7520543SJohan Hedberg unlock:
23251da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
23261da177e4SLinus Torvalds }
23271da177e4SLinus Torvalds 
23286039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2329a9de9248SMarcel Holtmann {
2330a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2331a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2332a9de9248SMarcel Holtmann 
23339f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2334a9de9248SMarcel Holtmann 
2335a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2336a9de9248SMarcel Holtmann 
2337a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2338d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2339d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2340d7556e20SWaldemar Rymarkiewicz 
2341765c2a96SJohan Hedberg 	if (!ev->status) {
2342aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
234351a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2344d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
234519f8def0SWaldemar Rymarkiewicz 		} else {
23464dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2347765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
234819f8def0SWaldemar Rymarkiewicz 		}
23492a611692SJohan Hedberg 	} else {
2350e1e930f5SJohan Hedberg 		mgmt_auth_failed(conn, ev->status);
23512a611692SJohan Hedberg 	}
2352a9de9248SMarcel Holtmann 
235351a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
235451a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2355a9de9248SMarcel Holtmann 
2356f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2357aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2358f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2359f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2360f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2361d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2362d7556e20SWaldemar Rymarkiewicz 				     &cp);
2363f8558555SMarcel Holtmann 		} else {
2364f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2365f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
236676a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2367f8558555SMarcel Holtmann 		}
2368052b30b0SMarcel Holtmann 	} else {
2369a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2370a9de9248SMarcel Holtmann 
2371052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2372052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
237376a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2374052b30b0SMarcel Holtmann 	}
2375052b30b0SMarcel Holtmann 
237651a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2377a9de9248SMarcel Holtmann 		if (!ev->status) {
2378a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2379f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2380f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2381d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2382d7556e20SWaldemar Rymarkiewicz 				     &cp);
2383a9de9248SMarcel Holtmann 		} else {
238451a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2385a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2386a9de9248SMarcel Holtmann 		}
2387a9de9248SMarcel Holtmann 	}
2388a9de9248SMarcel Holtmann 
2389d7556e20SWaldemar Rymarkiewicz unlock:
2390a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2391a9de9248SMarcel Holtmann }
2392a9de9248SMarcel Holtmann 
23936039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2394a9de9248SMarcel Holtmann {
2395127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2396127178d2SJohan Hedberg 	struct hci_conn *conn;
2397127178d2SJohan Hedberg 
2398a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2399a9de9248SMarcel Holtmann 
2400a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2401127178d2SJohan Hedberg 
2402127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2403127178d2SJohan Hedberg 
2404127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2405b644ba33SJohan Hedberg 
2406b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2407b644ba33SJohan Hedberg 		goto check_auth;
2408b644ba33SJohan Hedberg 
2409b644ba33SJohan Hedberg 	if (ev->status == 0)
2410b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2411b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2412b644ba33SJohan Hedberg 	else
2413b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2414b644ba33SJohan Hedberg 
2415b644ba33SJohan Hedberg check_auth:
241679c6c70cSJohan Hedberg 	if (!conn)
241779c6c70cSJohan Hedberg 		goto unlock;
241879c6c70cSJohan Hedberg 
241979c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
242079c6c70cSJohan Hedberg 		goto unlock;
242179c6c70cSJohan Hedberg 
242251a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2423127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2424977f8fceSJohan Hedberg 
2425977f8fceSJohan Hedberg 		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
2426977f8fceSJohan Hedberg 
2427127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2428127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2429127178d2SJohan Hedberg 	}
2430127178d2SJohan Hedberg 
243179c6c70cSJohan Hedberg unlock:
2432127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2433a9de9248SMarcel Holtmann }
2434a9de9248SMarcel Holtmann 
24356039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2436a9de9248SMarcel Holtmann {
2437a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2438a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2439a9de9248SMarcel Holtmann 
24409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2441a9de9248SMarcel Holtmann 
2442a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2443a9de9248SMarcel Holtmann 
2444a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2445dc8357ccSMarcel Holtmann 	if (!conn)
2446dc8357ccSMarcel Holtmann 		goto unlock;
2447dc8357ccSMarcel Holtmann 
2448a9de9248SMarcel Holtmann 	if (!ev->status) {
2449ae293196SMarcel Holtmann 		if (ev->encrypt) {
2450ae293196SMarcel Holtmann 			/* Encryption implies authentication */
24514dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
24524dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2453da85e5e5SVinicius Costa Gomes 			conn->sec_level = conn->pending_sec_level;
2454abf76badSMarcel Holtmann 
2455914a6ffeSMarcel Holtmann 			/* P-256 authentication key implies FIPS */
2456914a6ffeSMarcel Holtmann 			if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
24574dae2798SJohan Hedberg 				set_bit(HCI_CONN_FIPS, &conn->flags);
2458914a6ffeSMarcel Holtmann 
2459abf76badSMarcel Holtmann 			if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
2460abf76badSMarcel Holtmann 			    conn->type == LE_LINK)
2461abf76badSMarcel Holtmann 				set_bit(HCI_CONN_AES_CCM, &conn->flags);
2462abf76badSMarcel Holtmann 		} else {
24634dae2798SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
2464abf76badSMarcel Holtmann 			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
2465abf76badSMarcel Holtmann 		}
2466a9de9248SMarcel Holtmann 	}
2467a9de9248SMarcel Holtmann 
24687ed3fa20SJohan Hedberg 	/* We should disregard the current RPA and generate a new one
24697ed3fa20SJohan Hedberg 	 * whenever the encryption procedure fails.
24707ed3fa20SJohan Hedberg 	 */
24717ed3fa20SJohan Hedberg 	if (ev->status && conn->type == LE_LINK)
24727ed3fa20SJohan Hedberg 		set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
24737ed3fa20SJohan Hedberg 
247451a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2475a9de9248SMarcel Holtmann 
2476a7d7723aSGustavo Padovan 	if (ev->status && conn->state == BT_CONNECTED) {
2477bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
247876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2479a7d7723aSGustavo Padovan 		goto unlock;
2480a7d7723aSGustavo Padovan 	}
2481a7d7723aSGustavo Padovan 
2482f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2483f8558555SMarcel Holtmann 		if (!ev->status)
2484f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2485f8558555SMarcel Holtmann 
248640b552aaSMarcel Holtmann 		/* In Secure Connections Only mode, do not allow any
248740b552aaSMarcel Holtmann 		 * connections that are not encrypted with AES-CCM
248840b552aaSMarcel Holtmann 		 * using a P-256 authenticated combination key.
248940b552aaSMarcel Holtmann 		 */
249040b552aaSMarcel Holtmann 		if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) &&
249140b552aaSMarcel Holtmann 		    (!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
249240b552aaSMarcel Holtmann 		     conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) {
249340b552aaSMarcel Holtmann 			hci_proto_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE);
249440b552aaSMarcel Holtmann 			hci_conn_drop(conn);
249540b552aaSMarcel Holtmann 			goto unlock;
249640b552aaSMarcel Holtmann 		}
249740b552aaSMarcel Holtmann 
2498f8558555SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
249976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2500f8558555SMarcel Holtmann 	} else
2501a9de9248SMarcel Holtmann 		hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2502a9de9248SMarcel Holtmann 
2503a7d7723aSGustavo Padovan unlock:
2504a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2505a9de9248SMarcel Holtmann }
2506a9de9248SMarcel Holtmann 
25076039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2508807deac2SGustavo Padovan 					     struct sk_buff *skb)
2509a9de9248SMarcel Holtmann {
2510a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2511a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2512a9de9248SMarcel Holtmann 
25139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2514a9de9248SMarcel Holtmann 
2515a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2516a9de9248SMarcel Holtmann 
2517a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2518a9de9248SMarcel Holtmann 	if (conn) {
2519a9de9248SMarcel Holtmann 		if (!ev->status)
25204dae2798SJohan Hedberg 			set_bit(HCI_CONN_SECURE, &conn->flags);
2521a9de9248SMarcel Holtmann 
252251a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2523a9de9248SMarcel Holtmann 
2524a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2525a9de9248SMarcel Holtmann 	}
2526a9de9248SMarcel Holtmann 
2527a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2528a9de9248SMarcel Holtmann }
2529a9de9248SMarcel Holtmann 
25306039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2531807deac2SGustavo Padovan 				    struct sk_buff *skb)
2532a9de9248SMarcel Holtmann {
2533a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2534a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2535a9de9248SMarcel Holtmann 
25369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2537a9de9248SMarcel Holtmann 
2538a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2539a9de9248SMarcel Holtmann 
2540a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2541ccd556feSJohan Hedberg 	if (!conn)
2542ccd556feSJohan Hedberg 		goto unlock;
2543ccd556feSJohan Hedberg 
2544769be974SMarcel Holtmann 	if (!ev->status)
2545cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
2546a9de9248SMarcel Holtmann 
2547ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2548ccd556feSJohan Hedberg 		goto unlock;
2549ccd556feSJohan Hedberg 
2550ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2551769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2552769be974SMarcel Holtmann 		cp.handle = ev->handle;
2553769be974SMarcel Holtmann 		cp.page = 0x01;
2554ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2555769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2556392599b9SJohan Hedberg 		goto unlock;
2557392599b9SJohan Hedberg 	}
2558392599b9SJohan Hedberg 
2559671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2560127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2561127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2562127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2563127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2564127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2565b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
256648ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
2567392599b9SJohan Hedberg 
2568127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2569769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2570769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
257176a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2572769be974SMarcel Holtmann 	}
2573769be974SMarcel Holtmann 
2574ccd556feSJohan Hedberg unlock:
2575a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2576a9de9248SMarcel Holtmann }
2577a9de9248SMarcel Holtmann 
25786039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2579a9de9248SMarcel Holtmann {
2580a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
25819238f36aSJohan Hedberg 	u8 status = skb->data[sizeof(*ev)];
2582a9de9248SMarcel Holtmann 	__u16 opcode;
2583a9de9248SMarcel Holtmann 
2584a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2585a9de9248SMarcel Holtmann 
2586a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2587a9de9248SMarcel Holtmann 
2588a9de9248SMarcel Holtmann 	switch (opcode) {
2589a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2590a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2591a9de9248SMarcel Holtmann 		break;
2592a9de9248SMarcel Holtmann 
25934d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
25944d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
25954d93483bSAndre Guedes 		break;
25964d93483bSAndre Guedes 
2597a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2598a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2599a9de9248SMarcel Holtmann 		break;
2600a9de9248SMarcel Holtmann 
2601a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2602a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2603a9de9248SMarcel Holtmann 		break;
2604a9de9248SMarcel Holtmann 
2605a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2606a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2607a9de9248SMarcel Holtmann 		break;
2608a9de9248SMarcel Holtmann 
2609e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2610e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2611e4e8e37cSMarcel Holtmann 		break;
2612e4e8e37cSMarcel Holtmann 
2613a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2614a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2615a9de9248SMarcel Holtmann 		break;
2616a9de9248SMarcel Holtmann 
2617e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2618e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2619e4e8e37cSMarcel Holtmann 		break;
2620e4e8e37cSMarcel Holtmann 
2621e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2622e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2623e4e8e37cSMarcel Holtmann 		break;
2624e4e8e37cSMarcel Holtmann 
2625a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2626a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2627a9de9248SMarcel Holtmann 		break;
2628a9de9248SMarcel Holtmann 
2629a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2630a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2631a9de9248SMarcel Holtmann 		break;
2632a9de9248SMarcel Holtmann 
2633a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2634a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2635a9de9248SMarcel Holtmann 		break;
2636a9de9248SMarcel Holtmann 
2637a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2638a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2639a9de9248SMarcel Holtmann 		break;
2640a9de9248SMarcel Holtmann 
2641a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2642a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2643a9de9248SMarcel Holtmann 		break;
2644a9de9248SMarcel Holtmann 
2645a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2646a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2647a9de9248SMarcel Holtmann 		break;
2648a9de9248SMarcel Holtmann 
2649a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2650a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2651a9de9248SMarcel Holtmann 		break;
2652a9de9248SMarcel Holtmann 
2653a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2654a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2655a9de9248SMarcel Holtmann 		break;
2656a9de9248SMarcel Holtmann 
2657a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2658a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2659a9de9248SMarcel Holtmann 		break;
2660a9de9248SMarcel Holtmann 
2661a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2662a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2663a9de9248SMarcel Holtmann 		break;
2664a9de9248SMarcel Holtmann 
2665b4cb9fb2SMarcel Holtmann 	case HCI_OP_READ_NUM_SUPPORTED_IAC:
2666b4cb9fb2SMarcel Holtmann 		hci_cc_read_num_supported_iac(hdev, skb);
2667b4cb9fb2SMarcel Holtmann 		break;
2668b4cb9fb2SMarcel Holtmann 
2669333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2670333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2671333140b5SMarcel Holtmann 		break;
2672333140b5SMarcel Holtmann 
2673eac83dc6SMarcel Holtmann 	case HCI_OP_WRITE_SC_SUPPORT:
2674eac83dc6SMarcel Holtmann 		hci_cc_write_sc_support(hdev, skb);
2675eac83dc6SMarcel Holtmann 		break;
2676eac83dc6SMarcel Holtmann 
2677a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2678a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2679a9de9248SMarcel Holtmann 		break;
2680a9de9248SMarcel Holtmann 
2681a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2682a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2683a9de9248SMarcel Holtmann 		break;
2684a9de9248SMarcel Holtmann 
2685a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2686a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2687a9de9248SMarcel Holtmann 		break;
2688a9de9248SMarcel Holtmann 
2689971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2690971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2691971e3a4bSAndre Guedes 		break;
2692971e3a4bSAndre Guedes 
2693a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2694a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2695a9de9248SMarcel Holtmann 		break;
2696a9de9248SMarcel Holtmann 
2697a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2698a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2699a9de9248SMarcel Holtmann 		break;
2700a9de9248SMarcel Holtmann 
2701f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2702f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
2703f332ec66SJohan Hedberg 		break;
2704f332ec66SJohan Hedberg 
27054a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
27064a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
27074a3ee763SJohan Hedberg 		break;
27084a3ee763SJohan Hedberg 
2709f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
2710f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
2711f332ec66SJohan Hedberg 		break;
2712f332ec66SJohan Hedberg 
27134a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
27144a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
27154a3ee763SJohan Hedberg 		break;
27164a3ee763SJohan Hedberg 
2717350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2718350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2719350ee4cfSAndrei Emeltchenko 		break;
2720350ee4cfSAndrei Emeltchenko 
27211e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
27221e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
27231e89cffbSAndrei Emeltchenko 		break;
27241e89cffbSAndrei Emeltchenko 
2725928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2726928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2727928abaa7SAndrei Emeltchenko 		break;
2728928abaa7SAndrei Emeltchenko 
272933f35721SJohan Hedberg 	case HCI_OP_READ_CLOCK:
273033f35721SJohan Hedberg 		hci_cc_read_clock(hdev, skb);
273133f35721SJohan Hedberg 		break;
273233f35721SJohan Hedberg 
2733903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2734903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2735903e4541SAndrei Emeltchenko 		break;
2736903e4541SAndrei Emeltchenko 
2737d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2738d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2739d5859e22SJohan Hedberg 		break;
2740d5859e22SJohan Hedberg 
2741980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2742980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2743980e1a53SJohan Hedberg 		break;
2744980e1a53SJohan Hedberg 
2745980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2746980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2747980e1a53SJohan Hedberg 		break;
2748980e1a53SJohan Hedberg 
2749c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
27504d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_data(hdev, skb);
27514d2d2796SMarcel Holtmann 		break;
27524d2d2796SMarcel Holtmann 
27534d2d2796SMarcel Holtmann 	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
27544d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_ext_data(hdev, skb);
2755c35938b2SSzymon Janc 		break;
2756c35938b2SSzymon Janc 
27576ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
27586ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
27596ed58ec5SVille Tervo 		break;
27606ed58ec5SVille Tervo 
276160e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
276260e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
276360e77321SJohan Hedberg 		break;
276460e77321SJohan Hedberg 
27658fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
27668fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
27678fa19098SJohan Hedberg 		break;
27688fa19098SJohan Hedberg 
2769a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2770a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2771a5c29683SJohan Hedberg 		break;
2772a5c29683SJohan Hedberg 
2773a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2774a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2775a5c29683SJohan Hedberg 		break;
2776a5c29683SJohan Hedberg 
27771143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
27781143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
27791143d458SBrian Gix 		break;
27801143d458SBrian Gix 
27811143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
27821143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
278316cde993SSzymon Janc 		break;
278407f7fa5dSAndre Guedes 
27857a4cd51dSMarcel Holtmann 	case HCI_OP_LE_SET_RANDOM_ADDR:
27867a4cd51dSMarcel Holtmann 		hci_cc_le_set_random_addr(hdev, skb);
27877a4cd51dSMarcel Holtmann 		break;
27887a4cd51dSMarcel Holtmann 
2789c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2790c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2791c1d5dc4aSJohan Hedberg 		break;
2792c1d5dc4aSJohan Hedberg 
2793533553f8SMarcel Holtmann 	case HCI_OP_LE_SET_SCAN_PARAM:
2794533553f8SMarcel Holtmann 		hci_cc_le_set_scan_param(hdev, skb);
2795533553f8SMarcel Holtmann 		break;
2796533553f8SMarcel Holtmann 
2797eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2798eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2799eb9d91f5SAndre Guedes 		break;
2800eb9d91f5SAndre Guedes 
2801cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2802cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2803cf1d081fSJohan Hedberg 		break;
2804cf1d081fSJohan Hedberg 
28050f36b589SMarcel Holtmann 	case HCI_OP_LE_CLEAR_WHITE_LIST:
28060f36b589SMarcel Holtmann 		hci_cc_le_clear_white_list(hdev, skb);
28070f36b589SMarcel Holtmann 		break;
28080f36b589SMarcel Holtmann 
28090f36b589SMarcel Holtmann 	case HCI_OP_LE_ADD_TO_WHITE_LIST:
28100f36b589SMarcel Holtmann 		hci_cc_le_add_to_white_list(hdev, skb);
28110f36b589SMarcel Holtmann 		break;
28120f36b589SMarcel Holtmann 
28130f36b589SMarcel Holtmann 	case HCI_OP_LE_DEL_FROM_WHITE_LIST:
28140f36b589SMarcel Holtmann 		hci_cc_le_del_from_white_list(hdev, skb);
28150f36b589SMarcel Holtmann 		break;
28160f36b589SMarcel Holtmann 
28179b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
28189b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
28199b008c04SJohan Hedberg 		break;
28209b008c04SJohan Hedberg 
2821f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2822f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2823f9b49306SAndre Guedes 		break;
2824f9b49306SAndre Guedes 
282556ed2cb8SJohan Hedberg 	case HCI_OP_LE_SET_ADV_PARAM:
282656ed2cb8SJohan Hedberg 		hci_cc_set_adv_param(hdev, skb);
282756ed2cb8SJohan Hedberg 		break;
282856ed2cb8SJohan Hedberg 
282993c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
283093c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
283193c284eeSAndrei Emeltchenko 		break;
283293c284eeSAndrei Emeltchenko 
28335ae76a94SAndrzej Kaczmarek 	case HCI_OP_READ_RSSI:
28345ae76a94SAndrzej Kaczmarek 		hci_cc_read_rssi(hdev, skb);
28355ae76a94SAndrzej Kaczmarek 		break;
28365ae76a94SAndrzej Kaczmarek 
28375a134faeSAndrzej Kaczmarek 	case HCI_OP_READ_TX_POWER:
28385a134faeSAndrzej Kaczmarek 		hci_cc_read_tx_power(hdev, skb);
28395a134faeSAndrzej Kaczmarek 		break;
28405a134faeSAndrzej Kaczmarek 
2841a9de9248SMarcel Holtmann 	default:
28429f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2843a9de9248SMarcel Holtmann 		break;
2844a9de9248SMarcel Holtmann 	}
2845a9de9248SMarcel Holtmann 
2846ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
284765cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
28486bd32326SVille Tervo 
2849ad82cdd1SJohan Hedberg 	hci_req_cmd_complete(hdev, opcode, status);
28509238f36aSJohan Hedberg 
2851dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2852a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2853a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2854c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2855a9de9248SMarcel Holtmann 	}
2856a9de9248SMarcel Holtmann }
2857a9de9248SMarcel Holtmann 
28586039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2859a9de9248SMarcel Holtmann {
2860a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2861a9de9248SMarcel Holtmann 	__u16 opcode;
2862a9de9248SMarcel Holtmann 
2863a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2864a9de9248SMarcel Holtmann 
2865a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2866a9de9248SMarcel Holtmann 
2867a9de9248SMarcel Holtmann 	switch (opcode) {
2868a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2869a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2870a9de9248SMarcel Holtmann 		break;
2871a9de9248SMarcel Holtmann 
2872a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2873a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2874a9de9248SMarcel Holtmann 		break;
2875a9de9248SMarcel Holtmann 
28769645c76cSKuba Pawlak 	case HCI_OP_DISCONNECT:
28779645c76cSKuba Pawlak 		hci_cs_disconnect(hdev, ev->status);
28789645c76cSKuba Pawlak 		break;
28799645c76cSKuba Pawlak 
2880a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2881a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2882a9de9248SMarcel Holtmann 		break;
2883a9de9248SMarcel Holtmann 
2884f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2885f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2886f8558555SMarcel Holtmann 		break;
2887f8558555SMarcel Holtmann 
2888f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2889f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2890f8558555SMarcel Holtmann 		break;
2891f8558555SMarcel Holtmann 
2892a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2893a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2894a9de9248SMarcel Holtmann 		break;
2895a9de9248SMarcel Holtmann 
2896769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2897769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2898769be974SMarcel Holtmann 		break;
2899769be974SMarcel Holtmann 
2900769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2901769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2902769be974SMarcel Holtmann 		break;
2903769be974SMarcel Holtmann 
2904a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2905a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2906a9de9248SMarcel Holtmann 		break;
2907a9de9248SMarcel Holtmann 
29089645c76cSKuba Pawlak 	case HCI_OP_CREATE_PHY_LINK:
29099645c76cSKuba Pawlak 		hci_cs_create_phylink(hdev, ev->status);
29109645c76cSKuba Pawlak 		break;
29119645c76cSKuba Pawlak 
29129645c76cSKuba Pawlak 	case HCI_OP_ACCEPT_PHY_LINK:
29139645c76cSKuba Pawlak 		hci_cs_accept_phylink(hdev, ev->status);
29149645c76cSKuba Pawlak 		break;
29159645c76cSKuba Pawlak 
2916a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2917a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2918a9de9248SMarcel Holtmann 		break;
2919a9de9248SMarcel Holtmann 
2920a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2921a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2922a9de9248SMarcel Holtmann 		break;
2923a9de9248SMarcel Holtmann 
292450fc85f1SKuba Pawlak 	case HCI_OP_SWITCH_ROLE:
292550fc85f1SKuba Pawlak 		hci_cs_switch_role(hdev, ev->status);
292650fc85f1SKuba Pawlak 		break;
292750fc85f1SKuba Pawlak 
2928cb1d68f7SJohan Hedberg 	case HCI_OP_LE_CREATE_CONN:
2929cb1d68f7SJohan Hedberg 		hci_cs_le_create_conn(hdev, ev->status);
2930cb1d68f7SJohan Hedberg 		break;
2931cb1d68f7SJohan Hedberg 
293281d0c8adSJohan Hedberg 	case HCI_OP_LE_START_ENC:
293381d0c8adSJohan Hedberg 		hci_cs_le_start_enc(hdev, ev->status);
293481d0c8adSJohan Hedberg 		break;
293581d0c8adSJohan Hedberg 
2936a9de9248SMarcel Holtmann 	default:
29379f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2938a9de9248SMarcel Holtmann 		break;
2939a9de9248SMarcel Holtmann 	}
2940a9de9248SMarcel Holtmann 
2941ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
294265cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
29436bd32326SVille Tervo 
294402350a72SJohan Hedberg 	if (ev->status ||
294502350a72SJohan Hedberg 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
294633720450SAndre Guedes 		hci_req_cmd_complete(hdev, opcode, ev->status);
29479238f36aSJohan Hedberg 
294810572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2949a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2950a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2951c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2952a9de9248SMarcel Holtmann 	}
2953a9de9248SMarcel Holtmann }
2954a9de9248SMarcel Holtmann 
295524dfa343SMarcel Holtmann static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
295624dfa343SMarcel Holtmann {
295724dfa343SMarcel Holtmann 	struct hci_ev_hardware_error *ev = (void *) skb->data;
295824dfa343SMarcel Holtmann 
295924dfa343SMarcel Holtmann 	BT_ERR("%s hardware error 0x%2.2x", hdev->name, ev->code);
296024dfa343SMarcel Holtmann }
296124dfa343SMarcel Holtmann 
29626039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2963a9de9248SMarcel Holtmann {
2964a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2965a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2966a9de9248SMarcel Holtmann 
29679f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2968a9de9248SMarcel Holtmann 
2969a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2970a9de9248SMarcel Holtmann 
2971a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2972a9de9248SMarcel Holtmann 	if (conn) {
297340bef302SJohan Hedberg 		if (!ev->status)
297440bef302SJohan Hedberg 			conn->role = ev->role;
2975a9de9248SMarcel Holtmann 
297651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2977a9de9248SMarcel Holtmann 
2978a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2979a9de9248SMarcel Holtmann 	}
2980a9de9248SMarcel Holtmann 
2981a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2982a9de9248SMarcel Holtmann }
2983a9de9248SMarcel Holtmann 
29846039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
29851da177e4SLinus Torvalds {
2986a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
29871da177e4SLinus Torvalds 	int i;
29881da177e4SLinus Torvalds 
298932ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
299032ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
299132ac5b9bSAndrei Emeltchenko 		return;
299232ac5b9bSAndrei Emeltchenko 	}
299332ac5b9bSAndrei Emeltchenko 
2994c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2995c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
29961da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
29971da177e4SLinus Torvalds 		return;
29981da177e4SLinus Torvalds 	}
29991da177e4SLinus Torvalds 
3000c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
3001c5993de8SAndrei Emeltchenko 
3002613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
3003613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
30041da177e4SLinus Torvalds 		struct hci_conn *conn;
30051da177e4SLinus Torvalds 		__u16  handle, count;
30061da177e4SLinus Torvalds 
3007613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
3008613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
30091da177e4SLinus Torvalds 
30101da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
3011f4280918SAndrei Emeltchenko 		if (!conn)
3012f4280918SAndrei Emeltchenko 			continue;
3013f4280918SAndrei Emeltchenko 
30141da177e4SLinus Torvalds 		conn->sent -= count;
30151da177e4SLinus Torvalds 
3016f4280918SAndrei Emeltchenko 		switch (conn->type) {
3017f4280918SAndrei Emeltchenko 		case ACL_LINK:
301870f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
301970f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
30201da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
3021f4280918SAndrei Emeltchenko 			break;
3022f4280918SAndrei Emeltchenko 
3023f4280918SAndrei Emeltchenko 		case LE_LINK:
30246ed58ec5SVille Tervo 			if (hdev->le_pkts) {
30256ed58ec5SVille Tervo 				hdev->le_cnt += count;
30266ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
30276ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
30286ed58ec5SVille Tervo 			} else {
30296ed58ec5SVille Tervo 				hdev->acl_cnt += count;
30306ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
30316ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
30326ed58ec5SVille Tervo 			}
3033f4280918SAndrei Emeltchenko 			break;
3034f4280918SAndrei Emeltchenko 
3035f4280918SAndrei Emeltchenko 		case SCO_LINK:
303670f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
303770f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
30385b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
3039f4280918SAndrei Emeltchenko 			break;
3040f4280918SAndrei Emeltchenko 
3041f4280918SAndrei Emeltchenko 		default:
3042f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
3043f4280918SAndrei Emeltchenko 			break;
30441da177e4SLinus Torvalds 		}
30451da177e4SLinus Torvalds 	}
3046a9de9248SMarcel Holtmann 
30473eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
30481da177e4SLinus Torvalds }
30491da177e4SLinus Torvalds 
305076ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
305176ef7cf7SAndrei Emeltchenko 						 __u16 handle)
305276ef7cf7SAndrei Emeltchenko {
305376ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
305476ef7cf7SAndrei Emeltchenko 
305576ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
305676ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
305776ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
305876ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
305976ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
306076ef7cf7SAndrei Emeltchenko 		if (chan)
306176ef7cf7SAndrei Emeltchenko 			return chan->conn;
306276ef7cf7SAndrei Emeltchenko 		break;
306376ef7cf7SAndrei Emeltchenko 	default:
306476ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
306576ef7cf7SAndrei Emeltchenko 		break;
306676ef7cf7SAndrei Emeltchenko 	}
306776ef7cf7SAndrei Emeltchenko 
306876ef7cf7SAndrei Emeltchenko 	return NULL;
306976ef7cf7SAndrei Emeltchenko }
307076ef7cf7SAndrei Emeltchenko 
30716039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
307225e89e99SAndrei Emeltchenko {
307325e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
307425e89e99SAndrei Emeltchenko 	int i;
307525e89e99SAndrei Emeltchenko 
307625e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
307725e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
307825e89e99SAndrei Emeltchenko 		return;
307925e89e99SAndrei Emeltchenko 	}
308025e89e99SAndrei Emeltchenko 
308125e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
308225e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
308325e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
308425e89e99SAndrei Emeltchenko 		return;
308525e89e99SAndrei Emeltchenko 	}
308625e89e99SAndrei Emeltchenko 
308725e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
308825e89e99SAndrei Emeltchenko 	       ev->num_hndl);
308925e89e99SAndrei Emeltchenko 
309025e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
309125e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
309276ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
309325e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
309425e89e99SAndrei Emeltchenko 
309525e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
309625e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
309725e89e99SAndrei Emeltchenko 
309876ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
309925e89e99SAndrei Emeltchenko 		if (!conn)
310025e89e99SAndrei Emeltchenko 			continue;
310125e89e99SAndrei Emeltchenko 
310225e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
310325e89e99SAndrei Emeltchenko 
310425e89e99SAndrei Emeltchenko 		switch (conn->type) {
310525e89e99SAndrei Emeltchenko 		case ACL_LINK:
3106bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
310725e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
310825e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
310925e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
311025e89e99SAndrei Emeltchenko 			break;
311125e89e99SAndrei Emeltchenko 
311225e89e99SAndrei Emeltchenko 		default:
311325e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
311425e89e99SAndrei Emeltchenko 			break;
311525e89e99SAndrei Emeltchenko 		}
311625e89e99SAndrei Emeltchenko 	}
311725e89e99SAndrei Emeltchenko 
311825e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
311925e89e99SAndrei Emeltchenko }
312025e89e99SAndrei Emeltchenko 
31216039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
31221da177e4SLinus Torvalds {
3123a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
312404837f64SMarcel Holtmann 	struct hci_conn *conn;
31251da177e4SLinus Torvalds 
31269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
31271da177e4SLinus Torvalds 
31281da177e4SLinus Torvalds 	hci_dev_lock(hdev);
31291da177e4SLinus Torvalds 
313004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
313104837f64SMarcel Holtmann 	if (conn) {
313204837f64SMarcel Holtmann 		conn->mode = ev->mode;
313304837f64SMarcel Holtmann 
31348fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
31358fc9ced3SGustavo Padovan 					&conn->flags)) {
313604837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
313758a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
313804837f64SMarcel Holtmann 			else
313958a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
314004837f64SMarcel Holtmann 		}
3141e73439d8SMarcel Holtmann 
314251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
3143e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
314404837f64SMarcel Holtmann 	}
314504837f64SMarcel Holtmann 
314604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
314704837f64SMarcel Holtmann }
314804837f64SMarcel Holtmann 
31496039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
31501da177e4SLinus Torvalds {
3151052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
3152052b30b0SMarcel Holtmann 	struct hci_conn *conn;
3153052b30b0SMarcel Holtmann 
3154a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3155052b30b0SMarcel Holtmann 
3156052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3157052b30b0SMarcel Holtmann 
3158052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3159b6f98044SWaldemar Rymarkiewicz 	if (!conn)
3160b6f98044SWaldemar Rymarkiewicz 		goto unlock;
3161b6f98044SWaldemar Rymarkiewicz 
3162b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
3163052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3164052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
316576a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3166052b30b0SMarcel Holtmann 	}
3167052b30b0SMarcel Holtmann 
3168b6ae8457SJohan Hedberg 	if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) &&
31692f407f0aSJohan Hedberg 	    !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) {
317003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
317103b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
31722f407f0aSJohan Hedberg 	} else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
3173a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
3174a770bb5aSWaldemar Rymarkiewicz 
3175a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
3176a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
3177a770bb5aSWaldemar Rymarkiewicz 		else
3178a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
3179a770bb5aSWaldemar Rymarkiewicz 
3180744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
3181a770bb5aSWaldemar Rymarkiewicz 	}
3182980e1a53SJohan Hedberg 
3183b6f98044SWaldemar Rymarkiewicz unlock:
3184052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
31851da177e4SLinus Torvalds }
31861da177e4SLinus Torvalds 
31876039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
31881da177e4SLinus Torvalds {
318955ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
319055ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
319155ed8ca1SJohan Hedberg 	struct hci_conn *conn;
319255ed8ca1SJohan Hedberg 	struct link_key *key;
319355ed8ca1SJohan Hedberg 
3194a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
319555ed8ca1SJohan Hedberg 
3196034cbea0SAndrei Emeltchenko 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
319755ed8ca1SJohan Hedberg 		return;
319855ed8ca1SJohan Hedberg 
319955ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
320055ed8ca1SJohan Hedberg 
320155ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
320255ed8ca1SJohan Hedberg 	if (!key) {
32036ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
32046ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
320555ed8ca1SJohan Hedberg 		goto not_found;
320655ed8ca1SJohan Hedberg 	}
320755ed8ca1SJohan Hedberg 
32086ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
32096ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
321055ed8ca1SJohan Hedberg 
321155ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
321260b83f57SWaldemar Rymarkiewicz 	if (conn) {
321366138ce8SMarcel Holtmann 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
321466138ce8SMarcel Holtmann 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
3215807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
321655ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
321755ed8ca1SJohan Hedberg 			goto not_found;
321855ed8ca1SJohan Hedberg 		}
321955ed8ca1SJohan Hedberg 
322060b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
3221f3fb0b58SJohan Hedberg 		    (conn->pending_sec_level == BT_SECURITY_HIGH ||
3222f3fb0b58SJohan Hedberg 		     conn->pending_sec_level == BT_SECURITY_FIPS)) {
32238fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
32248fc9ced3SGustavo Padovan 			       hdev->name);
322560b83f57SWaldemar Rymarkiewicz 			goto not_found;
322660b83f57SWaldemar Rymarkiewicz 		}
322760b83f57SWaldemar Rymarkiewicz 
322860b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
322960b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
323060b83f57SWaldemar Rymarkiewicz 	}
323160b83f57SWaldemar Rymarkiewicz 
323255ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
32339b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
323455ed8ca1SJohan Hedberg 
323555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
323655ed8ca1SJohan Hedberg 
323755ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
323855ed8ca1SJohan Hedberg 
323955ed8ca1SJohan Hedberg 	return;
324055ed8ca1SJohan Hedberg 
324155ed8ca1SJohan Hedberg not_found:
324255ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
324355ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
32441da177e4SLinus Torvalds }
32451da177e4SLinus Torvalds 
32466039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
32471da177e4SLinus Torvalds {
3248052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
3249052b30b0SMarcel Holtmann 	struct hci_conn *conn;
32507652ff6aSJohan Hedberg 	struct link_key *key;
32517652ff6aSJohan Hedberg 	bool persistent;
325255ed8ca1SJohan Hedberg 	u8 pin_len = 0;
3253052b30b0SMarcel Holtmann 
3254a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3255052b30b0SMarcel Holtmann 
3256052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3257052b30b0SMarcel Holtmann 
3258052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3259052b30b0SMarcel Holtmann 	if (conn) {
3260052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3261052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3262980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
326313d39315SWaldemar Rymarkiewicz 
326413d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
326513d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
326613d39315SWaldemar Rymarkiewicz 
326776a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3268052b30b0SMarcel Holtmann 	}
3269052b30b0SMarcel Holtmann 
32707652ff6aSJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
32717652ff6aSJohan Hedberg 		goto unlock;
327255ed8ca1SJohan Hedberg 
32737652ff6aSJohan Hedberg 	key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key,
32747652ff6aSJohan Hedberg 			        ev->key_type, pin_len, &persistent);
32757652ff6aSJohan Hedberg 	if (!key)
32767652ff6aSJohan Hedberg 		goto unlock;
32777652ff6aSJohan Hedberg 
32787652ff6aSJohan Hedberg 	mgmt_new_link_key(hdev, key, persistent);
32797652ff6aSJohan Hedberg 
32806d5650c4SJohan Hedberg 	/* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
32816d5650c4SJohan Hedberg 	 * is set. If it's not set simply remove the key from the kernel
32826d5650c4SJohan Hedberg 	 * list (we've still notified user space about it but with
32836d5650c4SJohan Hedberg 	 * store_hint being 0).
32846d5650c4SJohan Hedberg 	 */
32856d5650c4SJohan Hedberg 	if (key->type == HCI_LK_DEBUG_COMBINATION &&
32866d5650c4SJohan Hedberg 	    !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) {
32876d5650c4SJohan Hedberg 		list_del(&key->list);
32886d5650c4SJohan Hedberg 		kfree(key);
32896d5650c4SJohan Hedberg 	} else if (conn) {
3290af6a9c32SJohan Hedberg 		if (persistent)
3291af6a9c32SJohan Hedberg 			clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
3292af6a9c32SJohan Hedberg 		else
3293af6a9c32SJohan Hedberg 			set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
32946d5650c4SJohan Hedberg 	}
32957652ff6aSJohan Hedberg 
32967652ff6aSJohan Hedberg unlock:
3297052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
32981da177e4SLinus Torvalds }
32991da177e4SLinus Torvalds 
33006039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
330104837f64SMarcel Holtmann {
3302a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
330304837f64SMarcel Holtmann 	struct hci_conn *conn;
330404837f64SMarcel Holtmann 
33059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
330604837f64SMarcel Holtmann 
330704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
330804837f64SMarcel Holtmann 
330904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
33101da177e4SLinus Torvalds 	if (conn && !ev->status) {
33111da177e4SLinus Torvalds 		struct inquiry_entry *ie;
33121da177e4SLinus Torvalds 
3313cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3314cc11b9c1SAndrei Emeltchenko 		if (ie) {
33151da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
33161da177e4SLinus Torvalds 			ie->timestamp = jiffies;
33171da177e4SLinus Torvalds 		}
33181da177e4SLinus Torvalds 	}
33191da177e4SLinus Torvalds 
33201da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
33211da177e4SLinus Torvalds }
33221da177e4SLinus Torvalds 
33236039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3324a8746417SMarcel Holtmann {
3325a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3326a8746417SMarcel Holtmann 	struct hci_conn *conn;
3327a8746417SMarcel Holtmann 
33289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3329a8746417SMarcel Holtmann 
3330a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
3331a8746417SMarcel Holtmann 
3332a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3333a8746417SMarcel Holtmann 	if (conn && !ev->status)
3334a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3335a8746417SMarcel Holtmann 
3336a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
3337a8746417SMarcel Holtmann }
3338a8746417SMarcel Holtmann 
33396039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
334085a1e930SMarcel Holtmann {
3341a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
334285a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
334385a1e930SMarcel Holtmann 
334485a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
334585a1e930SMarcel Holtmann 
334685a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
334785a1e930SMarcel Holtmann 
3348cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3349cc11b9c1SAndrei Emeltchenko 	if (ie) {
335085a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
335185a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
335285a1e930SMarcel Holtmann 	}
335385a1e930SMarcel Holtmann 
335485a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
335585a1e930SMarcel Holtmann }
335685a1e930SMarcel Holtmann 
33576039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3358807deac2SGustavo Padovan 					     struct sk_buff *skb)
3359a9de9248SMarcel Holtmann {
3360a9de9248SMarcel Holtmann 	struct inquiry_data data;
3361a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
3362a9de9248SMarcel Holtmann 
3363a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3364a9de9248SMarcel Holtmann 
3365a9de9248SMarcel Holtmann 	if (!num_rsp)
3366a9de9248SMarcel Holtmann 		return;
3367a9de9248SMarcel Holtmann 
33681519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
33691519cc17SAndre Guedes 		return;
33701519cc17SAndre Guedes 
3371a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3372a9de9248SMarcel Holtmann 
3373a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3374138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3375138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3376a9de9248SMarcel Holtmann 
3377e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3378af58925cSMarcel Holtmann 			u32 flags;
3379af58925cSMarcel Holtmann 
3380a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3381a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3382a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3383a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3384a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3385a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3386a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
338741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
33883175405bSJohan Hedberg 
3389af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
3390af58925cSMarcel Holtmann 
339148264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3392e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3393af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
3394a9de9248SMarcel Holtmann 		}
3395a9de9248SMarcel Holtmann 	} else {
3396a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3397a9de9248SMarcel Holtmann 
3398e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3399af58925cSMarcel Holtmann 			u32 flags;
3400af58925cSMarcel Holtmann 
3401a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3402a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3403a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3404a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3405a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3406a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3407a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
340841a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
3409af58925cSMarcel Holtmann 
3410af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
3411af58925cSMarcel Holtmann 
341248264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3413e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3414af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
3415a9de9248SMarcel Holtmann 		}
3416a9de9248SMarcel Holtmann 	}
3417a9de9248SMarcel Holtmann 
3418a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3419a9de9248SMarcel Holtmann }
3420a9de9248SMarcel Holtmann 
34216039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3422807deac2SGustavo Padovan 					struct sk_buff *skb)
3423a9de9248SMarcel Holtmann {
342441a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
342541a96212SMarcel Holtmann 	struct hci_conn *conn;
342641a96212SMarcel Holtmann 
3427a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
342841a96212SMarcel Holtmann 
342941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
343041a96212SMarcel Holtmann 
343141a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3432ccd556feSJohan Hedberg 	if (!conn)
3433ccd556feSJohan Hedberg 		goto unlock;
3434ccd556feSJohan Hedberg 
3435cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
3436cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
3437cad718edSJohan Hedberg 
3438769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
343941a96212SMarcel Holtmann 		struct inquiry_entry *ie;
344041a96212SMarcel Holtmann 
3441cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3442cc11b9c1SAndrei Emeltchenko 		if (ie)
344302b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
344441a96212SMarcel Holtmann 
3445bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
344658a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
3447bbb0eadaSJaganath Kanakkassery 		} else {
3448bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
3449bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
3450bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
3451bbb0eadaSJaganath Kanakkassery 			 * this.
3452bbb0eadaSJaganath Kanakkassery 			 *
3453bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
3454bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
3455bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
3456bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
3457bbb0eadaSJaganath Kanakkassery 		}
3458eb9a8f3fSMarcel Holtmann 
3459eb9a8f3fSMarcel Holtmann 		if (ev->features[0] & LMP_HOST_SC)
3460eb9a8f3fSMarcel Holtmann 			set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
346141a96212SMarcel Holtmann 	}
346241a96212SMarcel Holtmann 
3463ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3464ccd556feSJohan Hedberg 		goto unlock;
3465ccd556feSJohan Hedberg 
3466671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3467127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3468127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3469127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3470127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3471127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3472b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
347348ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
3474392599b9SJohan Hedberg 
3475127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3476769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3477769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
347876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3479769be974SMarcel Holtmann 	}
3480769be974SMarcel Holtmann 
3481ccd556feSJohan Hedberg unlock:
348241a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3483a9de9248SMarcel Holtmann }
3484a9de9248SMarcel Holtmann 
34856039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3486807deac2SGustavo Padovan 				       struct sk_buff *skb)
3487a9de9248SMarcel Holtmann {
3488b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3489b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3490b6a0dc82SMarcel Holtmann 
34919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3492b6a0dc82SMarcel Holtmann 
3493b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3494b6a0dc82SMarcel Holtmann 
3495b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
34969dc0a3afSMarcel Holtmann 	if (!conn) {
34979dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
34989dc0a3afSMarcel Holtmann 			goto unlock;
34999dc0a3afSMarcel Holtmann 
35009dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3501b6a0dc82SMarcel Holtmann 		if (!conn)
3502b6a0dc82SMarcel Holtmann 			goto unlock;
3503b6a0dc82SMarcel Holtmann 
35049dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
35059dc0a3afSMarcel Holtmann 	}
35069dc0a3afSMarcel Holtmann 
3507732547f9SMarcel Holtmann 	switch (ev->status) {
3508732547f9SMarcel Holtmann 	case 0x00:
3509732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3510732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3511732547f9SMarcel Holtmann 
3512732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3513732547f9SMarcel Holtmann 		break;
3514732547f9SMarcel Holtmann 
351581218d20SNick Pelly 	case 0x10:	/* Connection Accept Timeout */
35161a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
3517705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3518732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
35191038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3520732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
352127539bc4SAndrew Earl 	case 0x20:	/* Unsupported LMP Parameter value */
35222dea632fSFrédéric Dalleau 		if (conn->out) {
3523efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3524efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
35252dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
3526efc7688bSMarcel Holtmann 				goto unlock;
3527efc7688bSMarcel Holtmann 		}
3528732547f9SMarcel Holtmann 		/* fall through */
3529efc7688bSMarcel Holtmann 
3530732547f9SMarcel Holtmann 	default:
3531b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3532732547f9SMarcel Holtmann 		break;
3533732547f9SMarcel Holtmann 	}
3534b6a0dc82SMarcel Holtmann 
3535b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3536b6a0dc82SMarcel Holtmann 	if (ev->status)
3537b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3538b6a0dc82SMarcel Holtmann 
3539b6a0dc82SMarcel Holtmann unlock:
3540b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3541a9de9248SMarcel Holtmann }
3542a9de9248SMarcel Holtmann 
3543efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len)
3544efdcf8e3SMarcel Holtmann {
3545efdcf8e3SMarcel Holtmann 	size_t parsed = 0;
3546efdcf8e3SMarcel Holtmann 
3547efdcf8e3SMarcel Holtmann 	while (parsed < eir_len) {
3548efdcf8e3SMarcel Holtmann 		u8 field_len = eir[0];
3549efdcf8e3SMarcel Holtmann 
3550efdcf8e3SMarcel Holtmann 		if (field_len == 0)
3551efdcf8e3SMarcel Holtmann 			return parsed;
3552efdcf8e3SMarcel Holtmann 
3553efdcf8e3SMarcel Holtmann 		parsed += field_len + 1;
3554efdcf8e3SMarcel Holtmann 		eir += field_len + 1;
3555efdcf8e3SMarcel Holtmann 	}
3556efdcf8e3SMarcel Holtmann 
3557efdcf8e3SMarcel Holtmann 	return eir_len;
3558efdcf8e3SMarcel Holtmann }
3559efdcf8e3SMarcel Holtmann 
35606039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3561807deac2SGustavo Padovan 					    struct sk_buff *skb)
3562a9de9248SMarcel Holtmann {
3563a9de9248SMarcel Holtmann 	struct inquiry_data data;
3564a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3565a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
35669d939d94SVishal Agarwal 	size_t eir_len;
3567a9de9248SMarcel Holtmann 
3568a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3569a9de9248SMarcel Holtmann 
3570a9de9248SMarcel Holtmann 	if (!num_rsp)
3571a9de9248SMarcel Holtmann 		return;
3572a9de9248SMarcel Holtmann 
35731519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
35741519cc17SAndre Guedes 		return;
35751519cc17SAndre Guedes 
3576a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3577a9de9248SMarcel Holtmann 
3578e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3579af58925cSMarcel Holtmann 		u32 flags;
3580af58925cSMarcel Holtmann 		bool name_known;
3581561aafbcSJohan Hedberg 
3582a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3583a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3584a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3585a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3586a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3587a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3588a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
358941a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3590561aafbcSJohan Hedberg 
3591a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
35924ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
35934ddb1930SJohan Hedberg 						       sizeof(info->data),
35944ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3595561aafbcSJohan Hedberg 		else
3596561aafbcSJohan Hedberg 			name_known = true;
3597561aafbcSJohan Hedberg 
3598af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, name_known);
3599af58925cSMarcel Holtmann 
36009d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
3601af58925cSMarcel Holtmann 
360248264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3603af58925cSMarcel Holtmann 				  info->dev_class, info->rssi,
3604af58925cSMarcel Holtmann 				  flags, info->data, eir_len, NULL, 0);
3605a9de9248SMarcel Holtmann 	}
3606a9de9248SMarcel Holtmann 
3607a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3608a9de9248SMarcel Holtmann }
3609a9de9248SMarcel Holtmann 
36101c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
36111c2e0041SJohan Hedberg 					 struct sk_buff *skb)
36121c2e0041SJohan Hedberg {
36131c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
36141c2e0041SJohan Hedberg 	struct hci_conn *conn;
36151c2e0041SJohan Hedberg 
36169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
36171c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
36181c2e0041SJohan Hedberg 
36191c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
36201c2e0041SJohan Hedberg 
36211c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
36221c2e0041SJohan Hedberg 	if (!conn)
36231c2e0041SJohan Hedberg 		goto unlock;
36241c2e0041SJohan Hedberg 
36259eb1fbfaSJohan Hedberg 	/* For BR/EDR the necessary steps are taken through the
36269eb1fbfaSJohan Hedberg 	 * auth_complete event.
36279eb1fbfaSJohan Hedberg 	 */
36289eb1fbfaSJohan Hedberg 	if (conn->type != LE_LINK)
36299eb1fbfaSJohan Hedberg 		goto unlock;
36309eb1fbfaSJohan Hedberg 
36311c2e0041SJohan Hedberg 	if (!ev->status)
36321c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
36331c2e0041SJohan Hedberg 
36341c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
36351c2e0041SJohan Hedberg 
36361c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3637bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
363876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
36391c2e0041SJohan Hedberg 		goto unlock;
36401c2e0041SJohan Hedberg 	}
36411c2e0041SJohan Hedberg 
36421c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
36431c2e0041SJohan Hedberg 		if (!ev->status)
36441c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
36451c2e0041SJohan Hedberg 
36461c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
364776a68ba0SDavid Herrmann 		hci_conn_drop(conn);
36481c2e0041SJohan Hedberg 	} else {
36491c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
36501c2e0041SJohan Hedberg 
36511c2e0041SJohan Hedberg 		hci_conn_hold(conn);
36521c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
365376a68ba0SDavid Herrmann 		hci_conn_drop(conn);
36541c2e0041SJohan Hedberg 	}
36551c2e0041SJohan Hedberg 
36561c2e0041SJohan Hedberg unlock:
36571c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
36581c2e0041SJohan Hedberg }
36591c2e0041SJohan Hedberg 
36606039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
366117fa4b9dSJohan Hedberg {
366217fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
3663acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
3664acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
366558797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
366617fa4b9dSJohan Hedberg 
3667b7f94c88SMikel Astiz 	/* If both remote and local have enough IO capabilities, require
3668b7f94c88SMikel Astiz 	 * MITM protection
3669b7f94c88SMikel Astiz 	 */
3670b7f94c88SMikel Astiz 	if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT &&
3671b7f94c88SMikel Astiz 	    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT)
3672b7f94c88SMikel Astiz 		return conn->remote_auth | 0x01;
3673b7f94c88SMikel Astiz 
36747e74170aSTimo Mueller 	/* No MITM protection possible so ignore remote requirement */
36757e74170aSTimo Mueller 	return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01);
367617fa4b9dSJohan Hedberg }
367717fa4b9dSJohan Hedberg 
36786039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
36790493684eSMarcel Holtmann {
36800493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
36810493684eSMarcel Holtmann 	struct hci_conn *conn;
36820493684eSMarcel Holtmann 
36830493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
36840493684eSMarcel Holtmann 
36850493684eSMarcel Holtmann 	hci_dev_lock(hdev);
36860493684eSMarcel Holtmann 
36870493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
368803b555e1SJohan Hedberg 	if (!conn)
368903b555e1SJohan Hedberg 		goto unlock;
369003b555e1SJohan Hedberg 
36910493684eSMarcel Holtmann 	hci_conn_hold(conn);
36920493684eSMarcel Holtmann 
3693a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
369403b555e1SJohan Hedberg 		goto unlock;
369503b555e1SJohan Hedberg 
36962f407f0aSJohan Hedberg 	/* Allow pairing if we're pairable, the initiators of the
36972f407f0aSJohan Hedberg 	 * pairing or if the remote is not requesting bonding.
36982f407f0aSJohan Hedberg 	 */
3699b6ae8457SJohan Hedberg 	if (test_bit(HCI_BONDABLE, &hdev->dev_flags) ||
37002f407f0aSJohan Hedberg 	    test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) ||
370103b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
370217fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
370317fa4b9dSJohan Hedberg 
370417fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
37057a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
37067a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
37077a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
3708a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
3709b7f94c88SMikel Astiz 
3710b7f94c88SMikel Astiz 		/* If we are initiators, there is no remote information yet */
3711b7f94c88SMikel Astiz 		if (conn->remote_auth == 0xff) {
3712b16c6604SMikel Astiz 			/* Request MITM protection if our IO caps allow it
37134ad51a75SJohan Hedberg 			 * except for the no-bonding case.
3714b16c6604SMikel Astiz 			 */
37156fd6b915SMikel Astiz 			if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
37169f743d74SJohan Hedberg 			    conn->auth_type != HCI_AT_NO_BONDING)
37176c53823aSJohan Hedberg 				conn->auth_type |= 0x01;
3718b7f94c88SMikel Astiz 		} else {
37197cbc9bd9SJohan Hedberg 			conn->auth_type = hci_get_auth_req(conn);
3720b7f94c88SMikel Astiz 		}
372117fa4b9dSJohan Hedberg 
372282c295b1SJohan Hedberg 		/* If we're not bondable, force one of the non-bondable
372382c295b1SJohan Hedberg 		 * authentication requirement values.
372482c295b1SJohan Hedberg 		 */
372582c295b1SJohan Hedberg 		if (!test_bit(HCI_BONDABLE, &hdev->dev_flags))
372682c295b1SJohan Hedberg 			conn->auth_type &= HCI_AT_NO_BONDING_MITM;
372782c295b1SJohan Hedberg 
372882c295b1SJohan Hedberg 		cp.authentication = conn->auth_type;
372982c295b1SJohan Hedberg 
37308fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
37318fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3732ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3733ce85ee13SSzymon Janc 		else
3734ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3735ce85ee13SSzymon Janc 
373617fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
373717fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
373803b555e1SJohan Hedberg 	} else {
373903b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
374003b555e1SJohan Hedberg 
374103b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
37429f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
374303b555e1SJohan Hedberg 
374403b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
374503b555e1SJohan Hedberg 			     sizeof(cp), &cp);
374603b555e1SJohan Hedberg 	}
374703b555e1SJohan Hedberg 
374803b555e1SJohan Hedberg unlock:
374903b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
375003b555e1SJohan Hedberg }
375103b555e1SJohan Hedberg 
37526039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
375303b555e1SJohan Hedberg {
375403b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
375503b555e1SJohan Hedberg 	struct hci_conn *conn;
375603b555e1SJohan Hedberg 
375703b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
375803b555e1SJohan Hedberg 
375903b555e1SJohan Hedberg 	hci_dev_lock(hdev);
376003b555e1SJohan Hedberg 
376103b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
376203b555e1SJohan Hedberg 	if (!conn)
376303b555e1SJohan Hedberg 		goto unlock;
376403b555e1SJohan Hedberg 
376503b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
376603b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
376758a681efSJohan Hedberg 	if (ev->oob_data)
376858a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
376903b555e1SJohan Hedberg 
377003b555e1SJohan Hedberg unlock:
37710493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
37720493684eSMarcel Holtmann }
37730493684eSMarcel Holtmann 
37746039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3775a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3776a5c29683SJohan Hedberg {
3777a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
377855bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
37797a828908SJohan Hedberg 	struct hci_conn *conn;
3780a5c29683SJohan Hedberg 
3781a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3782a5c29683SJohan Hedberg 
3783a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3784a5c29683SJohan Hedberg 
3785a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
37867a828908SJohan Hedberg 		goto unlock;
37877a828908SJohan Hedberg 
37887a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
37897a828908SJohan Hedberg 	if (!conn)
37907a828908SJohan Hedberg 		goto unlock;
37917a828908SJohan Hedberg 
37927a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
37937a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
37947a828908SJohan Hedberg 
37957a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
37966c53823aSJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
37976c53823aSJohan Hedberg 	 * request. We check the security level here since it doesn't
37986c53823aSJohan Hedberg 	 * necessarily match conn->auth_type.
37996fd6b915SMikel Astiz 	 */
38006c53823aSJohan Hedberg 	if (conn->pending_sec_level > BT_SECURITY_MEDIUM &&
38016c53823aSJohan Hedberg 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
38027a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
38037a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
38047a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
38057a828908SJohan Hedberg 		goto unlock;
38067a828908SJohan Hedberg 	}
38077a828908SJohan Hedberg 
38087a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
3809a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
3810a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
381155bc1a37SJohan Hedberg 
381255bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
381355bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
3814ba15a58bSJohan Hedberg 		 * confirm_hint set to 1). The exception is if neither
381502f3e254SJohan Hedberg 		 * side had MITM or if the local IO capability is
381602f3e254SJohan Hedberg 		 * NoInputNoOutput, in which case we do auto-accept
3817ba15a58bSJohan Hedberg 		 */
3818ba15a58bSJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
381902f3e254SJohan Hedberg 		    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
3820ba15a58bSJohan Hedberg 		    (loc_mitm || rem_mitm)) {
382155bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
382255bc1a37SJohan Hedberg 			confirm_hint = 1;
382355bc1a37SJohan Hedberg 			goto confirm;
382455bc1a37SJohan Hedberg 		}
382555bc1a37SJohan Hedberg 
38269f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
38279f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
38289f61656aSJohan Hedberg 
38299f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
38309f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
38317bc18d9dSJohan Hedberg 			queue_delayed_work(conn->hdev->workqueue,
38327bc18d9dSJohan Hedberg 					   &conn->auto_accept_work, delay);
38339f61656aSJohan Hedberg 			goto unlock;
38349f61656aSJohan Hedberg 		}
38359f61656aSJohan Hedberg 
38367a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
38377a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
38387a828908SJohan Hedberg 		goto unlock;
38397a828908SJohan Hedberg 	}
38407a828908SJohan Hedberg 
384155bc1a37SJohan Hedberg confirm:
384239adbffeSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0,
384339adbffeSJohan Hedberg 				  le32_to_cpu(ev->passkey), confirm_hint);
3844a5c29683SJohan Hedberg 
38457a828908SJohan Hedberg unlock:
3846a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3847a5c29683SJohan Hedberg }
3848a5c29683SJohan Hedberg 
38496039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
38501143d458SBrian Gix 					 struct sk_buff *skb)
38511143d458SBrian Gix {
38521143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
38531143d458SBrian Gix 
38541143d458SBrian Gix 	BT_DBG("%s", hdev->name);
38551143d458SBrian Gix 
3856a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3857272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
38581143d458SBrian Gix }
38591143d458SBrian Gix 
386092a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
386192a25256SJohan Hedberg 					struct sk_buff *skb)
386292a25256SJohan Hedberg {
386392a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
386492a25256SJohan Hedberg 	struct hci_conn *conn;
386592a25256SJohan Hedberg 
386692a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
386792a25256SJohan Hedberg 
386892a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
386992a25256SJohan Hedberg 	if (!conn)
387092a25256SJohan Hedberg 		return;
387192a25256SJohan Hedberg 
387292a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
387392a25256SJohan Hedberg 	conn->passkey_entered = 0;
387492a25256SJohan Hedberg 
387592a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
387692a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
387792a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
387892a25256SJohan Hedberg 					 conn->passkey_entered);
387992a25256SJohan Hedberg }
388092a25256SJohan Hedberg 
388192a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
388292a25256SJohan Hedberg {
388392a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
388492a25256SJohan Hedberg 	struct hci_conn *conn;
388592a25256SJohan Hedberg 
388692a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
388792a25256SJohan Hedberg 
388892a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
388992a25256SJohan Hedberg 	if (!conn)
389092a25256SJohan Hedberg 		return;
389192a25256SJohan Hedberg 
389292a25256SJohan Hedberg 	switch (ev->type) {
389392a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
389492a25256SJohan Hedberg 		conn->passkey_entered = 0;
389592a25256SJohan Hedberg 		return;
389692a25256SJohan Hedberg 
389792a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
389892a25256SJohan Hedberg 		conn->passkey_entered++;
389992a25256SJohan Hedberg 		break;
390092a25256SJohan Hedberg 
390192a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
390292a25256SJohan Hedberg 		conn->passkey_entered--;
390392a25256SJohan Hedberg 		break;
390492a25256SJohan Hedberg 
390592a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
390692a25256SJohan Hedberg 		conn->passkey_entered = 0;
390792a25256SJohan Hedberg 		break;
390892a25256SJohan Hedberg 
390992a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
391092a25256SJohan Hedberg 		return;
391192a25256SJohan Hedberg 	}
391292a25256SJohan Hedberg 
391392a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
391492a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
391592a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
391692a25256SJohan Hedberg 					 conn->passkey_entered);
391792a25256SJohan Hedberg }
391892a25256SJohan Hedberg 
39196039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3920807deac2SGustavo Padovan 					 struct sk_buff *skb)
39210493684eSMarcel Holtmann {
39220493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
39230493684eSMarcel Holtmann 	struct hci_conn *conn;
39240493684eSMarcel Holtmann 
39250493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
39260493684eSMarcel Holtmann 
39270493684eSMarcel Holtmann 	hci_dev_lock(hdev);
39280493684eSMarcel Holtmann 
39290493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
39302a611692SJohan Hedberg 	if (!conn)
39312a611692SJohan Hedberg 		goto unlock;
39322a611692SJohan Hedberg 
3933c1d4fa7aSJohan Hedberg 	/* Reset the authentication requirement to unknown */
3934c1d4fa7aSJohan Hedberg 	conn->remote_auth = 0xff;
3935c1d4fa7aSJohan Hedberg 
39362a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
39372a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
39382a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
39392a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
39402a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3941fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3942e1e930f5SJohan Hedberg 		mgmt_auth_failed(conn, ev->status);
39432a611692SJohan Hedberg 
394476a68ba0SDavid Herrmann 	hci_conn_drop(conn);
39450493684eSMarcel Holtmann 
39462a611692SJohan Hedberg unlock:
39470493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
39480493684eSMarcel Holtmann }
39490493684eSMarcel Holtmann 
39506039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3951807deac2SGustavo Padovan 					 struct sk_buff *skb)
395241a96212SMarcel Holtmann {
395341a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
395441a96212SMarcel Holtmann 	struct inquiry_entry *ie;
3955cad718edSJohan Hedberg 	struct hci_conn *conn;
395641a96212SMarcel Holtmann 
395741a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
395841a96212SMarcel Holtmann 
395941a96212SMarcel Holtmann 	hci_dev_lock(hdev);
396041a96212SMarcel Holtmann 
3961cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3962cad718edSJohan Hedberg 	if (conn)
3963cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
3964cad718edSJohan Hedberg 
3965cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3966cc11b9c1SAndrei Emeltchenko 	if (ie)
396702b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
396841a96212SMarcel Holtmann 
396941a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
397041a96212SMarcel Holtmann }
397141a96212SMarcel Holtmann 
39726039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
39732763eda6SSzymon Janc 					    struct sk_buff *skb)
39742763eda6SSzymon Janc {
39752763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
39762763eda6SSzymon Janc 	struct oob_data *data;
39772763eda6SSzymon Janc 
39782763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
39792763eda6SSzymon Janc 
39802763eda6SSzymon Janc 	hci_dev_lock(hdev);
39812763eda6SSzymon Janc 
3982a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3983e1ba1f15SSzymon Janc 		goto unlock;
3984e1ba1f15SSzymon Janc 
39852763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
39862763eda6SSzymon Janc 	if (data) {
3987519ca9d0SMarcel Holtmann 		if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
3988519ca9d0SMarcel Holtmann 			struct hci_cp_remote_oob_ext_data_reply cp;
3989519ca9d0SMarcel Holtmann 
3990519ca9d0SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
3991519ca9d0SMarcel Holtmann 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
3992519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer192, data->randomizer192,
3993519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer192));
3994519ca9d0SMarcel Holtmann 			memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
3995519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer256, data->randomizer256,
3996519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer256));
3997519ca9d0SMarcel Holtmann 
3998519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
3999519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
4000519ca9d0SMarcel Holtmann 		} else {
40012763eda6SSzymon Janc 			struct hci_cp_remote_oob_data_reply cp;
40022763eda6SSzymon Janc 
40032763eda6SSzymon Janc 			bacpy(&cp.bdaddr, &ev->bdaddr);
4004519ca9d0SMarcel Holtmann 			memcpy(cp.hash, data->hash192, sizeof(cp.hash));
4005519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer, data->randomizer192,
4006519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer));
40072763eda6SSzymon Janc 
4008519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
4009519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
4010519ca9d0SMarcel Holtmann 		}
40112763eda6SSzymon Janc 	} else {
40122763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
40132763eda6SSzymon Janc 
40142763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
4015519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
4016519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
40172763eda6SSzymon Janc 	}
40182763eda6SSzymon Janc 
4019e1ba1f15SSzymon Janc unlock:
40202763eda6SSzymon Janc 	hci_dev_unlock(hdev);
40212763eda6SSzymon Janc }
40222763eda6SSzymon Janc 
4023d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
4024d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
4025d5e91192SAndrei Emeltchenko {
4026d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
4027d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
4028d5e91192SAndrei Emeltchenko 
4029d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
4030d5e91192SAndrei Emeltchenko 	       ev->status);
4031d5e91192SAndrei Emeltchenko 
4032d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
4033d5e91192SAndrei Emeltchenko 
4034d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
4035d5e91192SAndrei Emeltchenko 	if (!hcon) {
4036d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
4037d5e91192SAndrei Emeltchenko 		return;
4038d5e91192SAndrei Emeltchenko 	}
4039d5e91192SAndrei Emeltchenko 
4040d5e91192SAndrei Emeltchenko 	if (ev->status) {
4041d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
4042d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
4043d5e91192SAndrei Emeltchenko 		return;
4044d5e91192SAndrei Emeltchenko 	}
4045d5e91192SAndrei Emeltchenko 
4046d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
4047d5e91192SAndrei Emeltchenko 
4048d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
4049d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
4050d5e91192SAndrei Emeltchenko 
4051d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
4052d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
405376a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
4054d5e91192SAndrei Emeltchenko 
4055d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
4056d5e91192SAndrei Emeltchenko 
4057cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
4058cf70ff22SAndrei Emeltchenko 
4059d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
4060d5e91192SAndrei Emeltchenko }
4061d5e91192SAndrei Emeltchenko 
406227695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
406327695fb4SAndrei Emeltchenko {
406427695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
406527695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
406627695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
406727695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
406827695fb4SAndrei Emeltchenko 
406927695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
407027695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
407127695fb4SAndrei Emeltchenko 	       ev->status);
407227695fb4SAndrei Emeltchenko 
407327695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
407427695fb4SAndrei Emeltchenko 	if (!hcon)
407527695fb4SAndrei Emeltchenko 		return;
407627695fb4SAndrei Emeltchenko 
407727695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
407827695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
407927695fb4SAndrei Emeltchenko 	if (!hchan)
408027695fb4SAndrei Emeltchenko 		return;
408127695fb4SAndrei Emeltchenko 
408227695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
408327695fb4SAndrei Emeltchenko 
408427695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
408527695fb4SAndrei Emeltchenko 
408627695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
408727695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
408827695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
408927695fb4SAndrei Emeltchenko 
409027695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
409127695fb4SAndrei Emeltchenko 
409227695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
409327695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
409427695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
409527695fb4SAndrei Emeltchenko 
409627695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
409727695fb4SAndrei Emeltchenko 	}
409827695fb4SAndrei Emeltchenko }
409927695fb4SAndrei Emeltchenko 
4100606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
4101606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
4102606e2a10SAndrei Emeltchenko {
4103606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
4104606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
4105606e2a10SAndrei Emeltchenko 
4106606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
4107606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
4108606e2a10SAndrei Emeltchenko 
4109606e2a10SAndrei Emeltchenko 	if (ev->status)
4110606e2a10SAndrei Emeltchenko 		return;
4111606e2a10SAndrei Emeltchenko 
4112606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
4113606e2a10SAndrei Emeltchenko 
4114606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
4115606e2a10SAndrei Emeltchenko 	if (!hchan)
4116606e2a10SAndrei Emeltchenko 		goto unlock;
4117606e2a10SAndrei Emeltchenko 
4118606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
4119606e2a10SAndrei Emeltchenko 
4120606e2a10SAndrei Emeltchenko unlock:
4121606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
4122606e2a10SAndrei Emeltchenko }
4123606e2a10SAndrei Emeltchenko 
41249eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
41259eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
41269eef6b3aSAndrei Emeltchenko {
41279eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
41289eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
41299eef6b3aSAndrei Emeltchenko 
41309eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
41319eef6b3aSAndrei Emeltchenko 
41329eef6b3aSAndrei Emeltchenko 	if (ev->status)
41339eef6b3aSAndrei Emeltchenko 		return;
41349eef6b3aSAndrei Emeltchenko 
41359eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
41369eef6b3aSAndrei Emeltchenko 
41379eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
41389eef6b3aSAndrei Emeltchenko 	if (hcon) {
41399eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
41409eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
41419eef6b3aSAndrei Emeltchenko 	}
41429eef6b3aSAndrei Emeltchenko 
41439eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
41449eef6b3aSAndrei Emeltchenko }
41459eef6b3aSAndrei Emeltchenko 
41466039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
4147fcd89c09SVille Tervo {
4148fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
4149912b42efSJohan Hedberg 	struct hci_conn_params *params;
4150fcd89c09SVille Tervo 	struct hci_conn *conn;
415168d6f6deSJohan Hedberg 	struct smp_irk *irk;
4152837d502eSJohan Hedberg 	u8 addr_type;
4153fcd89c09SVille Tervo 
41549f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
4155fcd89c09SVille Tervo 
4156fcd89c09SVille Tervo 	hci_dev_lock(hdev);
4157fcd89c09SVille Tervo 
4158fbd96c15SJohan Hedberg 	/* All controllers implicitly stop advertising in the event of a
4159fbd96c15SJohan Hedberg 	 * connection, so ensure that the state bit is cleared.
4160fbd96c15SJohan Hedberg 	 */
4161fbd96c15SJohan Hedberg 	clear_bit(HCI_LE_ADV, &hdev->dev_flags);
4162fbd96c15SJohan Hedberg 
41634f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
4164b62f328bSVille Tervo 	if (!conn) {
4165a5c4e309SJohan Hedberg 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr, ev->role);
4166b62f328bSVille Tervo 		if (!conn) {
4167b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
4168230fd16aSAndre Guedes 			goto unlock;
4169b62f328bSVille Tervo 		}
417029b7988aSAndre Guedes 
417129b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
4172b9b343d2SAndre Guedes 
4173cb1d68f7SJohan Hedberg 		/* If we didn't have a hci_conn object previously
4174cb1d68f7SJohan Hedberg 		 * but we're in master role this must be something
4175cb1d68f7SJohan Hedberg 		 * initiated using a white list. Since white list based
4176cb1d68f7SJohan Hedberg 		 * connections are not "first class citizens" we don't
4177cb1d68f7SJohan Hedberg 		 * have full tracking of them. Therefore, we go ahead
4178cb1d68f7SJohan Hedberg 		 * with a "best effort" approach of determining the
4179cb1d68f7SJohan Hedberg 		 * initiator address based on the HCI_PRIVACY flag.
4180cb1d68f7SJohan Hedberg 		 */
4181cb1d68f7SJohan Hedberg 		if (conn->out) {
4182cb1d68f7SJohan Hedberg 			conn->resp_addr_type = ev->bdaddr_type;
4183cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &ev->bdaddr);
4184cb1d68f7SJohan Hedberg 			if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) {
4185cb1d68f7SJohan Hedberg 				conn->init_addr_type = ADDR_LE_DEV_RANDOM;
4186cb1d68f7SJohan Hedberg 				bacpy(&conn->init_addr, &hdev->rpa);
4187cb1d68f7SJohan Hedberg 			} else {
4188cb1d68f7SJohan Hedberg 				hci_copy_identity_address(hdev,
4189cb1d68f7SJohan Hedberg 							  &conn->init_addr,
4190cb1d68f7SJohan Hedberg 							  &conn->init_addr_type);
4191cb1d68f7SJohan Hedberg 			}
419280c24ab8SJohan Hedberg 		}
4193cb1d68f7SJohan Hedberg 	} else {
419480c24ab8SJohan Hedberg 		cancel_delayed_work(&conn->le_conn_timeout);
419580c24ab8SJohan Hedberg 	}
419680c24ab8SJohan Hedberg 
419780c24ab8SJohan Hedberg 	if (!conn->out) {
4198cb1d68f7SJohan Hedberg 		/* Set the responder (our side) address type based on
4199cb1d68f7SJohan Hedberg 		 * the advertising address type.
4200cb1d68f7SJohan Hedberg 		 */
4201cb1d68f7SJohan Hedberg 		conn->resp_addr_type = hdev->adv_addr_type;
4202cb1d68f7SJohan Hedberg 		if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM)
4203cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &hdev->random_addr);
4204cb1d68f7SJohan Hedberg 		else
4205cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &hdev->bdaddr);
4206cb1d68f7SJohan Hedberg 
4207cb1d68f7SJohan Hedberg 		conn->init_addr_type = ev->bdaddr_type;
4208cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &ev->bdaddr);
4209a720d735SMarcel Holtmann 
4210a720d735SMarcel Holtmann 		/* For incoming connections, set the default minimum
4211a720d735SMarcel Holtmann 		 * and maximum connection interval. They will be used
4212a720d735SMarcel Holtmann 		 * to check if the parameters are in range and if not
4213a720d735SMarcel Holtmann 		 * trigger the connection update procedure.
4214a720d735SMarcel Holtmann 		 */
4215a720d735SMarcel Holtmann 		conn->le_conn_min_interval = hdev->le_conn_min_interval;
4216a720d735SMarcel Holtmann 		conn->le_conn_max_interval = hdev->le_conn_max_interval;
4217cb1d68f7SJohan Hedberg 	}
42187be2edbbSJohan Hedberg 
4219edb4b466SMarcel Holtmann 	/* Lookup the identity address from the stored connection
4220edb4b466SMarcel Holtmann 	 * address and address type.
4221edb4b466SMarcel Holtmann 	 *
4222edb4b466SMarcel Holtmann 	 * When establishing connections to an identity address, the
4223edb4b466SMarcel Holtmann 	 * connection procedure will store the resolvable random
4224edb4b466SMarcel Holtmann 	 * address first. Now if it can be converted back into the
4225edb4b466SMarcel Holtmann 	 * identity address, start using the identity address from
4226edb4b466SMarcel Holtmann 	 * now on.
4227edb4b466SMarcel Holtmann 	 */
4228edb4b466SMarcel Holtmann 	irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
422968d6f6deSJohan Hedberg 	if (irk) {
423068d6f6deSJohan Hedberg 		bacpy(&conn->dst, &irk->bdaddr);
423168d6f6deSJohan Hedberg 		conn->dst_type = irk->addr_type;
423268d6f6deSJohan Hedberg 	}
423368d6f6deSJohan Hedberg 
42342d3c2260SJohan Hedberg 	if (ev->status) {
42352d3c2260SJohan Hedberg 		hci_le_conn_failed(conn, ev->status);
4236837d502eSJohan Hedberg 		goto unlock;
4237837d502eSJohan Hedberg 	}
4238837d502eSJohan Hedberg 
423908853f18SJohan Hedberg 	if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
424008853f18SJohan Hedberg 		addr_type = BDADDR_LE_PUBLIC;
424108853f18SJohan Hedberg 	else
424208853f18SJohan Hedberg 		addr_type = BDADDR_LE_RANDOM;
424308853f18SJohan Hedberg 
42442d3c2260SJohan Hedberg 	/* Drop the connection if the device is blocked */
42452d3c2260SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) {
42462d3c2260SJohan Hedberg 		hci_conn_drop(conn);
4247cd17decbSAndre Guedes 		goto unlock;
4248cd17decbSAndre Guedes 	}
4249cd17decbSAndre Guedes 
4250b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
425148ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, conn, 0, NULL, 0);
425283bc71b4SVinicius Costa Gomes 
42537b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
4254fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
4255fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
4256fcd89c09SVille Tervo 
4257e04fde60SMarcel Holtmann 	conn->le_conn_interval = le16_to_cpu(ev->interval);
4258e04fde60SMarcel Holtmann 	conn->le_conn_latency = le16_to_cpu(ev->latency);
4259e04fde60SMarcel Holtmann 	conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
4260e04fde60SMarcel Holtmann 
4261fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
4262fcd89c09SVille Tervo 
4263fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
4264fcd89c09SVille Tervo 
42655477610fSJohan Hedberg 	params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
42665477610fSJohan Hedberg 					   conn->dst_type);
4267f161dd41SJohan Hedberg 	if (params) {
426895305baaSJohan Hedberg 		list_del_init(&params->action);
4269f161dd41SJohan Hedberg 		if (params->conn) {
4270f161dd41SJohan Hedberg 			hci_conn_drop(params->conn);
4271f8aaf9b6SJohan Hedberg 			hci_conn_put(params->conn);
4272f161dd41SJohan Hedberg 			params->conn = NULL;
4273f161dd41SJohan Hedberg 		}
4274f161dd41SJohan Hedberg 	}
4275a4790dbdSAndre Guedes 
4276fcd89c09SVille Tervo unlock:
4277223683a5SJohan Hedberg 	hci_update_background_scan(hdev);
4278fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
4279fcd89c09SVille Tervo }
4280fcd89c09SVille Tervo 
42811855d92dSMarcel Holtmann static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
42821855d92dSMarcel Holtmann 					    struct sk_buff *skb)
42831855d92dSMarcel Holtmann {
42841855d92dSMarcel Holtmann 	struct hci_ev_le_conn_update_complete *ev = (void *) skb->data;
42851855d92dSMarcel Holtmann 	struct hci_conn *conn;
42861855d92dSMarcel Holtmann 
42871855d92dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
42881855d92dSMarcel Holtmann 
42891855d92dSMarcel Holtmann 	if (ev->status)
42901855d92dSMarcel Holtmann 		return;
42911855d92dSMarcel Holtmann 
42921855d92dSMarcel Holtmann 	hci_dev_lock(hdev);
42931855d92dSMarcel Holtmann 
42941855d92dSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
42951855d92dSMarcel Holtmann 	if (conn) {
42961855d92dSMarcel Holtmann 		conn->le_conn_interval = le16_to_cpu(ev->interval);
42971855d92dSMarcel Holtmann 		conn->le_conn_latency = le16_to_cpu(ev->latency);
42981855d92dSMarcel Holtmann 		conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
42991855d92dSMarcel Holtmann 	}
43001855d92dSMarcel Holtmann 
43011855d92dSMarcel Holtmann 	hci_dev_unlock(hdev);
43021855d92dSMarcel Holtmann }
43031855d92dSMarcel Holtmann 
4304a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */
4305fd45ada9SAlfonso Acosta static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
4306fd45ada9SAlfonso Acosta 					      bdaddr_t *addr,
43071c1abcabSJohan Hedberg 					      u8 addr_type, u8 adv_type)
4308a4790dbdSAndre Guedes {
4309a4790dbdSAndre Guedes 	struct hci_conn *conn;
43104b9e7e75SMarcel Holtmann 	struct hci_conn_params *params;
4311a4790dbdSAndre Guedes 
43121c1abcabSJohan Hedberg 	/* If the event is not connectable don't proceed further */
43131c1abcabSJohan Hedberg 	if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND)
4314fd45ada9SAlfonso Acosta 		return NULL;
43151c1abcabSJohan Hedberg 
43161c1abcabSJohan Hedberg 	/* Ignore if the device is blocked */
4317dcc36c16SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type))
4318fd45ada9SAlfonso Acosta 		return NULL;
43191c1abcabSJohan Hedberg 
4320f99353cfSJohan Hedberg 	/* Most controller will fail if we try to create new connections
4321f99353cfSJohan Hedberg 	 * while we have an existing one in slave role.
4322f99353cfSJohan Hedberg 	 */
4323f99353cfSJohan Hedberg 	if (hdev->conn_hash.le_num_slave > 0)
4324fd45ada9SAlfonso Acosta 		return NULL;
4325f99353cfSJohan Hedberg 
43261c1abcabSJohan Hedberg 	/* If we're not connectable only connect devices that we have in
43271c1abcabSJohan Hedberg 	 * our pend_le_conns list.
43281c1abcabSJohan Hedberg 	 */
43294b9e7e75SMarcel Holtmann 	params = hci_pend_le_action_lookup(&hdev->pend_le_conns,
43304b9e7e75SMarcel Holtmann 					   addr, addr_type);
43314b9e7e75SMarcel Holtmann 	if (!params)
4332fd45ada9SAlfonso Acosta 		return NULL;
4333a4790dbdSAndre Guedes 
43344b9e7e75SMarcel Holtmann 	switch (params->auto_connect) {
43354b9e7e75SMarcel Holtmann 	case HCI_AUTO_CONN_DIRECT:
43364b9e7e75SMarcel Holtmann 		/* Only devices advertising with ADV_DIRECT_IND are
43374b9e7e75SMarcel Holtmann 		 * triggering a connection attempt. This is allowing
43384b9e7e75SMarcel Holtmann 		 * incoming connections from slave devices.
43394b9e7e75SMarcel Holtmann 		 */
43404b9e7e75SMarcel Holtmann 		if (adv_type != LE_ADV_DIRECT_IND)
4341fd45ada9SAlfonso Acosta 			return NULL;
43424b9e7e75SMarcel Holtmann 		break;
43434b9e7e75SMarcel Holtmann 	case HCI_AUTO_CONN_ALWAYS:
43444b9e7e75SMarcel Holtmann 		/* Devices advertising with ADV_IND or ADV_DIRECT_IND
43454b9e7e75SMarcel Holtmann 		 * are triggering a connection attempt. This means
43464b9e7e75SMarcel Holtmann 		 * that incoming connectioms from slave device are
43474b9e7e75SMarcel Holtmann 		 * accepted and also outgoing connections to slave
43484b9e7e75SMarcel Holtmann 		 * devices are established when found.
43494b9e7e75SMarcel Holtmann 		 */
43504b9e7e75SMarcel Holtmann 		break;
43514b9e7e75SMarcel Holtmann 	default:
4352fd45ada9SAlfonso Acosta 		return NULL;
43534b9e7e75SMarcel Holtmann 	}
43544b9e7e75SMarcel Holtmann 
4355a4790dbdSAndre Guedes 	conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
4356e804d25dSJohan Hedberg 			      HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
4357f161dd41SJohan Hedberg 	if (!IS_ERR(conn)) {
4358f161dd41SJohan Hedberg 		/* Store the pointer since we don't really have any
4359f161dd41SJohan Hedberg 		 * other owner of the object besides the params that
4360f161dd41SJohan Hedberg 		 * triggered it. This way we can abort the connection if
4361f161dd41SJohan Hedberg 		 * the parameters get removed and keep the reference
4362f161dd41SJohan Hedberg 		 * count consistent once the connection is established.
4363f161dd41SJohan Hedberg 		 */
4364f8aaf9b6SJohan Hedberg 		params->conn = hci_conn_get(conn);
4365fd45ada9SAlfonso Acosta 		return conn;
4366f161dd41SJohan Hedberg 	}
4367a4790dbdSAndre Guedes 
4368a4790dbdSAndre Guedes 	switch (PTR_ERR(conn)) {
4369a4790dbdSAndre Guedes 	case -EBUSY:
4370a4790dbdSAndre Guedes 		/* If hci_connect() returns -EBUSY it means there is already
4371a4790dbdSAndre Guedes 		 * an LE connection attempt going on. Since controllers don't
4372a4790dbdSAndre Guedes 		 * support more than one connection attempt at the time, we
4373a4790dbdSAndre Guedes 		 * don't consider this an error case.
4374a4790dbdSAndre Guedes 		 */
4375a4790dbdSAndre Guedes 		break;
4376a4790dbdSAndre Guedes 	default:
4377a4790dbdSAndre Guedes 		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
4378fd45ada9SAlfonso Acosta 		return NULL;
4379a4790dbdSAndre Guedes 	}
4380fd45ada9SAlfonso Acosta 
4381fd45ada9SAlfonso Acosta 	return NULL;
4382a4790dbdSAndre Guedes }
4383a4790dbdSAndre Guedes 
43844af605d8SJohan Hedberg static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
43854af605d8SJohan Hedberg 			       u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
43864af605d8SJohan Hedberg {
4387b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
43881c1abcabSJohan Hedberg 	struct smp_irk *irk;
4389fd45ada9SAlfonso Acosta 	struct hci_conn *conn;
4390474ee066SJohan Hedberg 	bool match;
4391c70a7e4cSMarcel Holtmann 	u32 flags;
4392b9a6328fSJohan Hedberg 
4393435a13d8SJohan Hedberg 	/* Check if we need to convert to identity address */
4394435a13d8SJohan Hedberg 	irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
4395435a13d8SJohan Hedberg 	if (irk) {
4396435a13d8SJohan Hedberg 		bdaddr = &irk->bdaddr;
4397435a13d8SJohan Hedberg 		bdaddr_type = irk->addr_type;
4398435a13d8SJohan Hedberg 	}
4399435a13d8SJohan Hedberg 
44001c1abcabSJohan Hedberg 	/* Check if we have been requested to connect to this device */
4401fd45ada9SAlfonso Acosta 	conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type);
4402fd45ada9SAlfonso Acosta 	if (conn && type == LE_ADV_IND) {
4403fd45ada9SAlfonso Acosta 		/* Store report for later inclusion by
4404fd45ada9SAlfonso Acosta 		 * mgmt_device_connected
4405fd45ada9SAlfonso Acosta 		 */
4406fd45ada9SAlfonso Acosta 		memcpy(conn->le_adv_data, data, len);
4407fd45ada9SAlfonso Acosta 		conn->le_adv_data_len = len;
4408fd45ada9SAlfonso Acosta 	}
440999a6768eSJohan Hedberg 
44101c1abcabSJohan Hedberg 	/* Passive scanning shouldn't trigger any device found events,
44111c1abcabSJohan Hedberg 	 * except for devices marked as CONN_REPORT for which we do send
44121c1abcabSJohan Hedberg 	 * device found events.
44131c1abcabSJohan Hedberg 	 */
44141c1abcabSJohan Hedberg 	if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
44150d2bf134SJohan Hedberg 		if (type == LE_ADV_DIRECT_IND)
44160d2bf134SJohan Hedberg 			return;
44170d2bf134SJohan Hedberg 
44183a19b6feSJohan Hedberg 		if (!hci_pend_le_action_lookup(&hdev->pend_le_reports,
44193a19b6feSJohan Hedberg 					       bdaddr, bdaddr_type))
44200d2bf134SJohan Hedberg 			return;
44210d2bf134SJohan Hedberg 
44220d2bf134SJohan Hedberg 		if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND)
44230d2bf134SJohan Hedberg 			flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
44240d2bf134SJohan Hedberg 		else
44250d2bf134SJohan Hedberg 			flags = 0;
44260d2bf134SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
44270d2bf134SJohan Hedberg 				  rssi, flags, data, len, NULL, 0);
442897bf2e99SJohan Hedberg 		return;
4429ca5c4be7SJohan Hedberg 	}
44304af605d8SJohan Hedberg 
4431c70a7e4cSMarcel Holtmann 	/* When receiving non-connectable or scannable undirected
4432c70a7e4cSMarcel Holtmann 	 * advertising reports, this means that the remote device is
4433c70a7e4cSMarcel Holtmann 	 * not connectable and then clearly indicate this in the
4434c70a7e4cSMarcel Holtmann 	 * device found event.
4435c70a7e4cSMarcel Holtmann 	 *
4436c70a7e4cSMarcel Holtmann 	 * When receiving a scan response, then there is no way to
4437c70a7e4cSMarcel Holtmann 	 * know if the remote device is connectable or not. However
4438c70a7e4cSMarcel Holtmann 	 * since scan responses are merged with a previously seen
4439c70a7e4cSMarcel Holtmann 	 * advertising report, the flags field from that report
4440c70a7e4cSMarcel Holtmann 	 * will be used.
4441c70a7e4cSMarcel Holtmann 	 *
4442c70a7e4cSMarcel Holtmann 	 * In the really unlikely case that a controller get confused
4443c70a7e4cSMarcel Holtmann 	 * and just sends a scan response event, then it is marked as
4444c70a7e4cSMarcel Holtmann 	 * not connectable as well.
4445c70a7e4cSMarcel Holtmann 	 */
4446c70a7e4cSMarcel Holtmann 	if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND ||
4447c70a7e4cSMarcel Holtmann 	    type == LE_ADV_SCAN_RSP)
4448c70a7e4cSMarcel Holtmann 		flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
4449c70a7e4cSMarcel Holtmann 	else
4450c70a7e4cSMarcel Holtmann 		flags = 0;
4451c70a7e4cSMarcel Holtmann 
4452b9a6328fSJohan Hedberg 	/* If there's nothing pending either store the data from this
4453b9a6328fSJohan Hedberg 	 * event or send an immediate device found event if the data
4454b9a6328fSJohan Hedberg 	 * should not be stored for later.
4455b9a6328fSJohan Hedberg 	 */
4456b9a6328fSJohan Hedberg 	if (!has_pending_adv_report(hdev)) {
4457b9a6328fSJohan Hedberg 		/* If the report will trigger a SCAN_REQ store it for
4458b9a6328fSJohan Hedberg 		 * later merging.
4459b9a6328fSJohan Hedberg 		 */
4460b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
4461b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
4462c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
4463b9a6328fSJohan Hedberg 			return;
4464b9a6328fSJohan Hedberg 		}
4465b9a6328fSJohan Hedberg 
4466b9a6328fSJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
4467c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
4468b9a6328fSJohan Hedberg 		return;
4469b9a6328fSJohan Hedberg 	}
4470b9a6328fSJohan Hedberg 
4471474ee066SJohan Hedberg 	/* Check if the pending report is for the same device as the new one */
4472474ee066SJohan Hedberg 	match = (!bacmp(bdaddr, &d->last_adv_addr) &&
4473474ee066SJohan Hedberg 		 bdaddr_type == d->last_adv_addr_type);
4474474ee066SJohan Hedberg 
4475b9a6328fSJohan Hedberg 	/* If the pending data doesn't match this report or this isn't a
4476b9a6328fSJohan Hedberg 	 * scan response (e.g. we got a duplicate ADV_IND) then force
4477b9a6328fSJohan Hedberg 	 * sending of the pending data.
4478b9a6328fSJohan Hedberg 	 */
4479474ee066SJohan Hedberg 	if (type != LE_ADV_SCAN_RSP || !match) {
4480474ee066SJohan Hedberg 		/* Send out whatever is in the cache, but skip duplicates */
4481474ee066SJohan Hedberg 		if (!match)
4482b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4483ff5cd29fSJohan Hedberg 					  d->last_adv_addr_type, NULL,
4484c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
4485ff5cd29fSJohan Hedberg 					  d->last_adv_data,
4486474ee066SJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
4487b9a6328fSJohan Hedberg 
4488b9a6328fSJohan Hedberg 		/* If the new report will trigger a SCAN_REQ store it for
4489b9a6328fSJohan Hedberg 		 * later merging.
4490b9a6328fSJohan Hedberg 		 */
4491b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
4492b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
4493c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
4494b9a6328fSJohan Hedberg 			return;
4495b9a6328fSJohan Hedberg 		}
4496b9a6328fSJohan Hedberg 
4497b9a6328fSJohan Hedberg 		/* The advertising reports cannot be merged, so clear
4498b9a6328fSJohan Hedberg 		 * the pending report and send out a device found event.
4499b9a6328fSJohan Hedberg 		 */
4500b9a6328fSJohan Hedberg 		clear_pending_adv_report(hdev);
45015c5b93e4SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
4502c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
4503b9a6328fSJohan Hedberg 		return;
4504b9a6328fSJohan Hedberg 	}
4505b9a6328fSJohan Hedberg 
4506b9a6328fSJohan Hedberg 	/* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
4507b9a6328fSJohan Hedberg 	 * the new event is a SCAN_RSP. We can therefore proceed with
4508b9a6328fSJohan Hedberg 	 * sending a merged device found event.
4509b9a6328fSJohan Hedberg 	 */
4510b9a6328fSJohan Hedberg 	mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4511c70a7e4cSMarcel Holtmann 			  d->last_adv_addr_type, NULL, rssi, d->last_adv_flags,
451242bd6a56SMarcel Holtmann 			  d->last_adv_data, d->last_adv_data_len, data, len);
4513b9a6328fSJohan Hedberg 	clear_pending_adv_report(hdev);
45144af605d8SJohan Hedberg }
45154af605d8SJohan Hedberg 
45166039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
45179aa04c91SAndre Guedes {
4518e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
4519e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
45209aa04c91SAndre Guedes 
4521a4790dbdSAndre Guedes 	hci_dev_lock(hdev);
4522a4790dbdSAndre Guedes 
4523e95beb41SAndre Guedes 	while (num_reports--) {
4524e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
45254af605d8SJohan Hedberg 		s8 rssi;
4526a4790dbdSAndre Guedes 
45273c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
45284af605d8SJohan Hedberg 		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
45294af605d8SJohan Hedberg 				   ev->bdaddr_type, rssi, ev->data, ev->length);
45303c9e9195SAndre Guedes 
4531e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
45329aa04c91SAndre Guedes 	}
4533a4790dbdSAndre Guedes 
4534a4790dbdSAndre Guedes 	hci_dev_unlock(hdev);
45359aa04c91SAndre Guedes }
45369aa04c91SAndre Guedes 
45376039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
4538a7a595f6SVinicius Costa Gomes {
4539a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
4540a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
4541bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
4542a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
4543c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
4544a7a595f6SVinicius Costa Gomes 
45459f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
4546a7a595f6SVinicius Costa Gomes 
4547a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
4548a7a595f6SVinicius Costa Gomes 
4549a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
4550bea710feSVinicius Costa Gomes 	if (conn == NULL)
4551bea710feSVinicius Costa Gomes 		goto not_found;
4552a7a595f6SVinicius Costa Gomes 
4553e804d25dSJohan Hedberg 	ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role);
4554bea710feSVinicius Costa Gomes 	if (ltk == NULL)
4555bea710feSVinicius Costa Gomes 		goto not_found;
4556bea710feSVinicius Costa Gomes 
4557bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
4558a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
4559c9839a11SVinicius Costa Gomes 
4560a6f7833cSJohan Hedberg 	conn->pending_sec_level = smp_ltk_sec_level(ltk);
4561a7a595f6SVinicius Costa Gomes 
456289cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
4563a7a595f6SVinicius Costa Gomes 
4564a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
4565a7a595f6SVinicius Costa Gomes 
45665981a882SClaudio Takahasi 	/* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a
45675981a882SClaudio Takahasi 	 * temporary key used to encrypt a connection following
45685981a882SClaudio Takahasi 	 * pairing. It is used during the Encrypted Session Setup to
45695981a882SClaudio Takahasi 	 * distribute the keys. Later, security can be re-established
45705981a882SClaudio Takahasi 	 * using a distributed LTK.
45715981a882SClaudio Takahasi 	 */
45722ceba539SJohan Hedberg 	if (ltk->type == SMP_STK) {
4573fe59a05fSJohan Hedberg 		set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
4574c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
4575c9839a11SVinicius Costa Gomes 		kfree(ltk);
4576fe59a05fSJohan Hedberg 	} else {
4577fe59a05fSJohan Hedberg 		clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
4578c9839a11SVinicius Costa Gomes 	}
4579c9839a11SVinicius Costa Gomes 
4580a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
4581bea710feSVinicius Costa Gomes 
4582bea710feSVinicius Costa Gomes 	return;
4583bea710feSVinicius Costa Gomes 
4584bea710feSVinicius Costa Gomes not_found:
4585bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
4586bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
4587bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
4588a7a595f6SVinicius Costa Gomes }
4589a7a595f6SVinicius Costa Gomes 
45908e75b46aSAndre Guedes static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
45918e75b46aSAndre Guedes 				      u8 reason)
45928e75b46aSAndre Guedes {
45938e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_neg_reply cp;
45948e75b46aSAndre Guedes 
45958e75b46aSAndre Guedes 	cp.handle = cpu_to_le16(handle);
45968e75b46aSAndre Guedes 	cp.reason = reason;
45978e75b46aSAndre Guedes 
45988e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp),
45998e75b46aSAndre Guedes 		     &cp);
46008e75b46aSAndre Guedes }
46018e75b46aSAndre Guedes 
46028e75b46aSAndre Guedes static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
46038e75b46aSAndre Guedes 					     struct sk_buff *skb)
46048e75b46aSAndre Guedes {
46058e75b46aSAndre Guedes 	struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data;
46068e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_reply cp;
46078e75b46aSAndre Guedes 	struct hci_conn *hcon;
46088e75b46aSAndre Guedes 	u16 handle, min, max, latency, timeout;
46098e75b46aSAndre Guedes 
46108e75b46aSAndre Guedes 	handle = le16_to_cpu(ev->handle);
46118e75b46aSAndre Guedes 	min = le16_to_cpu(ev->interval_min);
46128e75b46aSAndre Guedes 	max = le16_to_cpu(ev->interval_max);
46138e75b46aSAndre Guedes 	latency = le16_to_cpu(ev->latency);
46148e75b46aSAndre Guedes 	timeout = le16_to_cpu(ev->timeout);
46158e75b46aSAndre Guedes 
46168e75b46aSAndre Guedes 	hcon = hci_conn_hash_lookup_handle(hdev, handle);
46178e75b46aSAndre Guedes 	if (!hcon || hcon->state != BT_CONNECTED)
46188e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
46198e75b46aSAndre Guedes 						 HCI_ERROR_UNKNOWN_CONN_ID);
46208e75b46aSAndre Guedes 
46218e75b46aSAndre Guedes 	if (hci_check_conn_params(min, max, latency, timeout))
46228e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
46238e75b46aSAndre Guedes 						 HCI_ERROR_INVALID_LL_PARAMS);
46248e75b46aSAndre Guedes 
462540bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_MASTER) {
4626348d50b8SJohan Hedberg 		struct hci_conn_params *params;
4627f4869e2aSJohan Hedberg 		u8 store_hint;
4628348d50b8SJohan Hedberg 
4629348d50b8SJohan Hedberg 		hci_dev_lock(hdev);
4630348d50b8SJohan Hedberg 
4631348d50b8SJohan Hedberg 		params = hci_conn_params_lookup(hdev, &hcon->dst,
4632348d50b8SJohan Hedberg 						hcon->dst_type);
4633348d50b8SJohan Hedberg 		if (params) {
4634348d50b8SJohan Hedberg 			params->conn_min_interval = min;
4635348d50b8SJohan Hedberg 			params->conn_max_interval = max;
4636348d50b8SJohan Hedberg 			params->conn_latency = latency;
4637348d50b8SJohan Hedberg 			params->supervision_timeout = timeout;
4638f4869e2aSJohan Hedberg 			store_hint = 0x01;
4639f4869e2aSJohan Hedberg 		} else{
4640f4869e2aSJohan Hedberg 			store_hint = 0x00;
4641348d50b8SJohan Hedberg 		}
4642348d50b8SJohan Hedberg 
4643348d50b8SJohan Hedberg 		hci_dev_unlock(hdev);
4644348d50b8SJohan Hedberg 
4645f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type,
4646f4869e2aSJohan Hedberg 				    store_hint, min, max, latency, timeout);
4647348d50b8SJohan Hedberg 	}
4648ffb5a827SAndre Guedes 
46498e75b46aSAndre Guedes 	cp.handle = ev->handle;
46508e75b46aSAndre Guedes 	cp.interval_min = ev->interval_min;
46518e75b46aSAndre Guedes 	cp.interval_max = ev->interval_max;
46528e75b46aSAndre Guedes 	cp.latency = ev->latency;
46538e75b46aSAndre Guedes 	cp.timeout = ev->timeout;
46548e75b46aSAndre Guedes 	cp.min_ce_len = 0;
46558e75b46aSAndre Guedes 	cp.max_ce_len = 0;
46568e75b46aSAndre Guedes 
46578e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
46588e75b46aSAndre Guedes }
46598e75b46aSAndre Guedes 
46606039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
4661fcd89c09SVille Tervo {
4662fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
4663fcd89c09SVille Tervo 
4664fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
4665fcd89c09SVille Tervo 
4666fcd89c09SVille Tervo 	switch (le_ev->subevent) {
4667fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
4668fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
4669fcd89c09SVille Tervo 		break;
4670fcd89c09SVille Tervo 
46711855d92dSMarcel Holtmann 	case HCI_EV_LE_CONN_UPDATE_COMPLETE:
46721855d92dSMarcel Holtmann 		hci_le_conn_update_complete_evt(hdev, skb);
46731855d92dSMarcel Holtmann 		break;
46741855d92dSMarcel Holtmann 
46759aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
46769aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
46779aa04c91SAndre Guedes 		break;
46789aa04c91SAndre Guedes 
4679a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
4680a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
4681a7a595f6SVinicius Costa Gomes 		break;
4682a7a595f6SVinicius Costa Gomes 
46838e75b46aSAndre Guedes 	case HCI_EV_LE_REMOTE_CONN_PARAM_REQ:
46848e75b46aSAndre Guedes 		hci_le_remote_conn_param_req_evt(hdev, skb);
46858e75b46aSAndre Guedes 		break;
46868e75b46aSAndre Guedes 
4687fcd89c09SVille Tervo 	default:
4688fcd89c09SVille Tervo 		break;
4689fcd89c09SVille Tervo 	}
4690fcd89c09SVille Tervo }
4691fcd89c09SVille Tervo 
46929495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
46939495b2eeSAndrei Emeltchenko {
46949495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
46959495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
46969495b2eeSAndrei Emeltchenko 
46979495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
46989495b2eeSAndrei Emeltchenko 
46999495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
47009495b2eeSAndrei Emeltchenko 
47019495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
47029495b2eeSAndrei Emeltchenko 	if (!hcon)
47039495b2eeSAndrei Emeltchenko 		return;
47049495b2eeSAndrei Emeltchenko 
47059495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
47069495b2eeSAndrei Emeltchenko }
47079495b2eeSAndrei Emeltchenko 
47081da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
47091da177e4SLinus Torvalds {
4710a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
4711a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
47121da177e4SLinus Torvalds 
4713b6ddb638SJohan Hedberg 	hci_dev_lock(hdev);
4714b6ddb638SJohan Hedberg 
4715b6ddb638SJohan Hedberg 	/* Received events are (currently) only needed when a request is
4716b6ddb638SJohan Hedberg 	 * ongoing so avoid unnecessary memory allocation.
4717b6ddb638SJohan Hedberg 	 */
4718899de765SMarcel Holtmann 	if (hci_req_pending(hdev)) {
4719b6ddb638SJohan Hedberg 		kfree_skb(hdev->recv_evt);
4720b6ddb638SJohan Hedberg 		hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
4721b6ddb638SJohan Hedberg 	}
4722b6ddb638SJohan Hedberg 
4723b6ddb638SJohan Hedberg 	hci_dev_unlock(hdev);
4724b6ddb638SJohan Hedberg 
47251da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
47261da177e4SLinus Torvalds 
472702350a72SJohan Hedberg 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
4728c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
4729c1f23a2bSJohannes Berg 		u16 opcode = __le16_to_cpu(cmd_hdr->opcode);
473002350a72SJohan Hedberg 
473102350a72SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, 0);
473202350a72SJohan Hedberg 	}
473302350a72SJohan Hedberg 
4734a9de9248SMarcel Holtmann 	switch (event) {
47351da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
47361da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
47371da177e4SLinus Torvalds 		break;
47381da177e4SLinus Torvalds 
47391da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
47401da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
47411da177e4SLinus Torvalds 		break;
47421da177e4SLinus Torvalds 
4743a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
4744a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
474521d9e30eSMarcel Holtmann 		break;
474621d9e30eSMarcel Holtmann 
47471da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
47481da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
47491da177e4SLinus Torvalds 		break;
47501da177e4SLinus Torvalds 
47511da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
47521da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
47531da177e4SLinus Torvalds 		break;
47541da177e4SLinus Torvalds 
47551da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
47561da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
47571da177e4SLinus Torvalds 		break;
47581da177e4SLinus Torvalds 
4759a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
4760a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
4761a9de9248SMarcel Holtmann 		break;
4762a9de9248SMarcel Holtmann 
47631da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
47641da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
47651da177e4SLinus Torvalds 		break;
47661da177e4SLinus Torvalds 
4767a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
4768a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
4769a9de9248SMarcel Holtmann 		break;
4770a9de9248SMarcel Holtmann 
4771a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
4772a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
4773a9de9248SMarcel Holtmann 		break;
4774a9de9248SMarcel Holtmann 
4775a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
4776a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
4777a9de9248SMarcel Holtmann 		break;
4778a9de9248SMarcel Holtmann 
4779a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
4780a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
4781a9de9248SMarcel Holtmann 		break;
4782a9de9248SMarcel Holtmann 
478324dfa343SMarcel Holtmann 	case HCI_EV_HARDWARE_ERROR:
478424dfa343SMarcel Holtmann 		hci_hardware_error_evt(hdev, skb);
478524dfa343SMarcel Holtmann 		break;
478624dfa343SMarcel Holtmann 
4787a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
4788a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
4789a9de9248SMarcel Holtmann 		break;
4790a9de9248SMarcel Holtmann 
4791a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
4792a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
4793a9de9248SMarcel Holtmann 		break;
4794a9de9248SMarcel Holtmann 
4795a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
4796a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
47971da177e4SLinus Torvalds 		break;
47981da177e4SLinus Torvalds 
47991da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
48001da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
48011da177e4SLinus Torvalds 		break;
48021da177e4SLinus Torvalds 
48031da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
48041da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
48051da177e4SLinus Torvalds 		break;
48061da177e4SLinus Torvalds 
48071da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
48081da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
48091da177e4SLinus Torvalds 		break;
48101da177e4SLinus Torvalds 
48111da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
48121da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
48131da177e4SLinus Torvalds 		break;
48141da177e4SLinus Torvalds 
4815a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
4816a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
4817a8746417SMarcel Holtmann 		break;
4818a8746417SMarcel Holtmann 
481985a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
482085a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
482185a1e930SMarcel Holtmann 		break;
482285a1e930SMarcel Holtmann 
4823a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4824a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
4825a9de9248SMarcel Holtmann 		break;
4826a9de9248SMarcel Holtmann 
4827a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
4828a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
4829a9de9248SMarcel Holtmann 		break;
4830a9de9248SMarcel Holtmann 
4831a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
4832a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
4833a9de9248SMarcel Holtmann 		break;
4834a9de9248SMarcel Holtmann 
4835a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
4836a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
48371da177e4SLinus Torvalds 		break;
48381da177e4SLinus Torvalds 
48391c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
48401c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
48411c2e0041SJohan Hedberg 		break;
48421c2e0041SJohan Hedberg 
48430493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
48440493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
48450493684eSMarcel Holtmann 		break;
48460493684eSMarcel Holtmann 
484703b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
484803b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
484903b555e1SJohan Hedberg 		break;
485003b555e1SJohan Hedberg 
4851a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
4852a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
4853a5c29683SJohan Hedberg 		break;
4854a5c29683SJohan Hedberg 
48551143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
48561143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
48571143d458SBrian Gix 		break;
48581143d458SBrian Gix 
485992a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
486092a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
486192a25256SJohan Hedberg 		break;
486292a25256SJohan Hedberg 
486392a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
486492a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
486592a25256SJohan Hedberg 		break;
486692a25256SJohan Hedberg 
48670493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
48680493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
48690493684eSMarcel Holtmann 		break;
48700493684eSMarcel Holtmann 
487141a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
487241a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
487341a96212SMarcel Holtmann 		break;
487441a96212SMarcel Holtmann 
4875fcd89c09SVille Tervo 	case HCI_EV_LE_META:
4876fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
4877fcd89c09SVille Tervo 		break;
4878fcd89c09SVille Tervo 
48799495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
48809495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
48819495b2eeSAndrei Emeltchenko 		break;
48829495b2eeSAndrei Emeltchenko 
48832763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
48842763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
48852763eda6SSzymon Janc 		break;
48862763eda6SSzymon Janc 
4887d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
4888d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
4889d5e91192SAndrei Emeltchenko 		break;
4890d5e91192SAndrei Emeltchenko 
489127695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
489227695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
489327695fb4SAndrei Emeltchenko 		break;
489427695fb4SAndrei Emeltchenko 
4895606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4896606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
4897606e2a10SAndrei Emeltchenko 		break;
4898606e2a10SAndrei Emeltchenko 
48999eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
49009eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
49019eef6b3aSAndrei Emeltchenko 		break;
49029eef6b3aSAndrei Emeltchenko 
490325e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
490425e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
490525e89e99SAndrei Emeltchenko 		break;
490625e89e99SAndrei Emeltchenko 
49071da177e4SLinus Torvalds 	default:
49089f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
49091da177e4SLinus Torvalds 		break;
49101da177e4SLinus Torvalds 	}
49111da177e4SLinus Torvalds 
49121da177e4SLinus Torvalds 	kfree_skb(skb);
49131da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
49141da177e4SLinus Torvalds }
4915