xref: /openbmc/linux/net/bluetooth/hci_event.c (revision b6ae8457)
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 
192a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
1932cc6fb00SJohan Hedberg 	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
19469775ff6SAndre Guedes 
19569775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
196bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
197bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
1983f0f524bSJohan Hedberg 
1993f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
2003f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
201f8e808bdSMarcel Holtmann 
202f8e808bdSMarcel Holtmann 	memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data));
203f8e808bdSMarcel Holtmann 	hdev->scan_rsp_data_len = 0;
20406f5b778SMarcel Holtmann 
205533553f8SMarcel Holtmann 	hdev->le_scan_type = LE_SCAN_PASSIVE;
206533553f8SMarcel Holtmann 
20706f5b778SMarcel Holtmann 	hdev->ssp_debug_mode = 0;
208a9de9248SMarcel Holtmann }
209a9de9248SMarcel Holtmann 
210a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
211a9de9248SMarcel Holtmann {
212a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2131da177e4SLinus Torvalds 	void *sent;
2141da177e4SLinus Torvalds 
2159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2161da177e4SLinus Torvalds 
217a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2181da177e4SLinus Torvalds 	if (!sent)
219a9de9248SMarcel Holtmann 		return;
2201da177e4SLinus Torvalds 
22156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
22256e5cb86SJohan Hedberg 
223f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
224f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
22528cc7bdeSJohan Hedberg 	else if (!status)
22628cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
227f51d5b24SJohan Hedberg 
22856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
229a9de9248SMarcel Holtmann }
230a9de9248SMarcel Holtmann 
231a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
232a9de9248SMarcel Holtmann {
233a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
234a9de9248SMarcel Holtmann 
2359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
236a9de9248SMarcel Holtmann 
237a9de9248SMarcel Holtmann 	if (rp->status)
238a9de9248SMarcel Holtmann 		return;
239a9de9248SMarcel Holtmann 
240db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2411f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
242a9de9248SMarcel Holtmann }
243a9de9248SMarcel Holtmann 
244a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
245a9de9248SMarcel Holtmann {
246a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
247a9de9248SMarcel Holtmann 	void *sent;
248a9de9248SMarcel Holtmann 
2499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
250a9de9248SMarcel Holtmann 
251a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
252a9de9248SMarcel Holtmann 	if (!sent)
253a9de9248SMarcel Holtmann 		return;
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds 	if (!status) {
256a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
257a9de9248SMarcel Holtmann 
2581da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2591da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2601da177e4SLinus Torvalds 		else
2611da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2621da177e4SLinus Torvalds 	}
263a9de9248SMarcel Holtmann 
26433ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
26533ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
266a9de9248SMarcel Holtmann }
2671da177e4SLinus Torvalds 
268a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
269a9de9248SMarcel Holtmann {
270a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
27145296acdSMarcel Holtmann 	__u8 param;
272a9de9248SMarcel Holtmann 	void *sent;
273a9de9248SMarcel Holtmann 
2749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
275a9de9248SMarcel Holtmann 
27645296acdSMarcel Holtmann 	if (status)
27745296acdSMarcel Holtmann 		return;
27845296acdSMarcel Holtmann 
279a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2801da177e4SLinus Torvalds 	if (!sent)
281a9de9248SMarcel Holtmann 		return;
2821da177e4SLinus Torvalds 
28345296acdSMarcel Holtmann 	param = *((__u8 *) sent);
284a9de9248SMarcel Holtmann 
2851da177e4SLinus Torvalds 	if (param)
2861da177e4SLinus Torvalds 		set_bit(HCI_ENCRYPT, &hdev->flags);
2871da177e4SLinus Torvalds 	else
2881da177e4SLinus Torvalds 		clear_bit(HCI_ENCRYPT, &hdev->flags);
2891da177e4SLinus Torvalds }
2901da177e4SLinus Torvalds 
291a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
292a9de9248SMarcel Holtmann {
29345296acdSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
29445296acdSMarcel Holtmann 	__u8 param;
295a9de9248SMarcel Holtmann 	void *sent;
2961da177e4SLinus Torvalds 
2979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
298a9de9248SMarcel Holtmann 
299a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3001da177e4SLinus Torvalds 	if (!sent)
301a9de9248SMarcel Holtmann 		return;
3021da177e4SLinus Torvalds 
30336f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
304a9de9248SMarcel Holtmann 
30556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
30656e5cb86SJohan Hedberg 
307fa1bd918SMikel Astiz 	if (status) {
3082d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3092d7cee58SJohan Hedberg 		goto done;
3102d7cee58SJohan Hedberg 	}
3112d7cee58SJohan Hedberg 
312bc6d2d04SJohan Hedberg 	if (param & SCAN_INQUIRY)
3131da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
314bc6d2d04SJohan Hedberg 	else
315bc6d2d04SJohan Hedberg 		clear_bit(HCI_ISCAN, &hdev->flags);
3161da177e4SLinus Torvalds 
317031547d8SJohan Hedberg 	if (param & SCAN_PAGE)
3181da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
319bc6d2d04SJohan Hedberg 	else
320204e3990SJohan Hedberg 		clear_bit(HCI_PSCAN, &hdev->flags);
321a9de9248SMarcel Holtmann 
32236f7fc7eSJohan Hedberg done:
32356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
3241da177e4SLinus Torvalds }
3251da177e4SLinus Torvalds 
326a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
327a9de9248SMarcel Holtmann {
328a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
329a9de9248SMarcel Holtmann 
3309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
331a9de9248SMarcel Holtmann 
332a9de9248SMarcel Holtmann 	if (rp->status)
333a9de9248SMarcel Holtmann 		return;
334a9de9248SMarcel Holtmann 
335a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
336a9de9248SMarcel Holtmann 
337a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
338a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
339a9de9248SMarcel Holtmann }
340a9de9248SMarcel Holtmann 
341a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
342a9de9248SMarcel Holtmann {
343a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
344a9de9248SMarcel Holtmann 	void *sent;
345a9de9248SMarcel Holtmann 
3469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
347a9de9248SMarcel Holtmann 
348a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
349a9de9248SMarcel Holtmann 	if (!sent)
350a9de9248SMarcel Holtmann 		return;
351a9de9248SMarcel Holtmann 
3527f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3537f9a903cSMarcel Holtmann 
3547f9a903cSMarcel Holtmann 	if (status == 0)
355a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3567f9a903cSMarcel Holtmann 
3577f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3587f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3597f9a903cSMarcel Holtmann 
3607f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
361a9de9248SMarcel Holtmann }
362a9de9248SMarcel Holtmann 
363a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
364a9de9248SMarcel Holtmann {
365a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
366a9de9248SMarcel Holtmann 	__u16 setting;
367a9de9248SMarcel Holtmann 
3689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
369a9de9248SMarcel Holtmann 
370a9de9248SMarcel Holtmann 	if (rp->status)
371a9de9248SMarcel Holtmann 		return;
372a9de9248SMarcel Holtmann 
373a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
374a9de9248SMarcel Holtmann 
375a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
376a9de9248SMarcel Holtmann 		return;
377a9de9248SMarcel Holtmann 
378a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
379a9de9248SMarcel Holtmann 
3809f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
381a9de9248SMarcel Holtmann 
3823c54711cSGustavo F. Padovan 	if (hdev->notify)
383a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
384a9de9248SMarcel Holtmann }
385a9de9248SMarcel Holtmann 
3868fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
3878fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
388a9de9248SMarcel Holtmann {
389a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
390f383f275SMarcel Holtmann 	__u16 setting;
391a9de9248SMarcel Holtmann 	void *sent;
392a9de9248SMarcel Holtmann 
3939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
394a9de9248SMarcel Holtmann 
395f383f275SMarcel Holtmann 	if (status)
396f383f275SMarcel Holtmann 		return;
397f383f275SMarcel Holtmann 
398a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
399a9de9248SMarcel Holtmann 	if (!sent)
400a9de9248SMarcel Holtmann 		return;
401a9de9248SMarcel Holtmann 
402f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4031da177e4SLinus Torvalds 
404f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
405f383f275SMarcel Holtmann 		return;
406f383f275SMarcel Holtmann 
4071da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4081da177e4SLinus Torvalds 
4099f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4101da177e4SLinus Torvalds 
4113c54711cSGustavo F. Padovan 	if (hdev->notify)
4121da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4131da177e4SLinus Torvalds }
4141da177e4SLinus Torvalds 
415b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev,
416b4cb9fb2SMarcel Holtmann 					  struct sk_buff *skb)
417b4cb9fb2SMarcel Holtmann {
418b4cb9fb2SMarcel Holtmann 	struct hci_rp_read_num_supported_iac *rp = (void *) skb->data;
419b4cb9fb2SMarcel Holtmann 
420b4cb9fb2SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
421b4cb9fb2SMarcel Holtmann 
422b4cb9fb2SMarcel Holtmann 	if (rp->status)
423b4cb9fb2SMarcel Holtmann 		return;
424b4cb9fb2SMarcel Holtmann 
425b4cb9fb2SMarcel Holtmann 	hdev->num_iac = rp->num_iac;
426b4cb9fb2SMarcel Holtmann 
427b4cb9fb2SMarcel Holtmann 	BT_DBG("%s num iac %d", hdev->name, hdev->num_iac);
428b4cb9fb2SMarcel Holtmann }
429b4cb9fb2SMarcel Holtmann 
430333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
431333140b5SMarcel Holtmann {
432333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4335ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
434333140b5SMarcel Holtmann 
4359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
436333140b5SMarcel Holtmann 
437333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
438333140b5SMarcel Holtmann 	if (!sent)
439333140b5SMarcel Holtmann 		return;
440333140b5SMarcel Holtmann 
4415ed8eb2fSJohan Hedberg 	if (!status) {
4425ed8eb2fSJohan Hedberg 		if (sent->mode)
443cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_SSP;
4445ed8eb2fSJohan Hedberg 		else
445cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_SSP;
4465ed8eb2fSJohan Hedberg 	}
4475ed8eb2fSJohan Hedberg 
448c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4495ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
450c0ecddc2SJohan Hedberg 	else if (!status) {
4515ed8eb2fSJohan Hedberg 		if (sent->mode)
45284bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
45384bde9d6SJohan Hedberg 		else
45484bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
455c0ecddc2SJohan Hedberg 	}
456333140b5SMarcel Holtmann }
457333140b5SMarcel Holtmann 
458eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
459eac83dc6SMarcel Holtmann {
460eac83dc6SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
461eac83dc6SMarcel Holtmann 	struct hci_cp_write_sc_support *sent;
462eac83dc6SMarcel Holtmann 
463eac83dc6SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
464eac83dc6SMarcel Holtmann 
465eac83dc6SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
466eac83dc6SMarcel Holtmann 	if (!sent)
467eac83dc6SMarcel Holtmann 		return;
468eac83dc6SMarcel Holtmann 
469eac83dc6SMarcel Holtmann 	if (!status) {
470eac83dc6SMarcel Holtmann 		if (sent->support)
471eac83dc6SMarcel Holtmann 			hdev->features[1][0] |= LMP_HOST_SC;
472eac83dc6SMarcel Holtmann 		else
473eac83dc6SMarcel Holtmann 			hdev->features[1][0] &= ~LMP_HOST_SC;
474eac83dc6SMarcel Holtmann 	}
475eac83dc6SMarcel Holtmann 
476eac83dc6SMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
477eac83dc6SMarcel Holtmann 		mgmt_sc_enable_complete(hdev, sent->support, status);
478eac83dc6SMarcel Holtmann 	else if (!status) {
479eac83dc6SMarcel Holtmann 		if (sent->support)
480eac83dc6SMarcel Holtmann 			set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
481eac83dc6SMarcel Holtmann 		else
482eac83dc6SMarcel Holtmann 			clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
483eac83dc6SMarcel Holtmann 	}
484eac83dc6SMarcel Holtmann }
485eac83dc6SMarcel Holtmann 
486a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
487a9de9248SMarcel Holtmann {
488a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
4891143e5a6SMarcel Holtmann 
4909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
4911143e5a6SMarcel Holtmann 
492a9de9248SMarcel Holtmann 	if (rp->status)
49342c6b129SJohan Hedberg 		return;
4941143e5a6SMarcel Holtmann 
4950d5551f5SMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
496a9de9248SMarcel Holtmann 		hdev->hci_ver = rp->hci_ver;
497e4e8e37cSMarcel Holtmann 		hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
498d5859e22SJohan Hedberg 		hdev->lmp_ver = rp->lmp_ver;
499e4e8e37cSMarcel Holtmann 		hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
500d5859e22SJohan Hedberg 		hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5010d5551f5SMarcel Holtmann 	}
502d5859e22SJohan Hedberg }
503d5859e22SJohan Hedberg 
5048fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
5058fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
506a9de9248SMarcel Holtmann {
507a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
508a9de9248SMarcel Holtmann 
5099f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
510a9de9248SMarcel Holtmann 
5116a070e6eSMarcel Holtmann 	if (rp->status)
5126a070e6eSMarcel Holtmann 		return;
5136a070e6eSMarcel Holtmann 
5146a070e6eSMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
515a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
516a9de9248SMarcel Holtmann }
517a9de9248SMarcel Holtmann 
5188fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
5198fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
520a9de9248SMarcel Holtmann {
521a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
522a9de9248SMarcel Holtmann 
5239f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
524a9de9248SMarcel Holtmann 
525a9de9248SMarcel Holtmann 	if (rp->status)
526a9de9248SMarcel Holtmann 		return;
527a9de9248SMarcel Holtmann 
528a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
5291da177e4SLinus Torvalds 
5301da177e4SLinus Torvalds 	/* Adjust default settings according to features
5311da177e4SLinus Torvalds 	 * supported by device. */
532a9de9248SMarcel Holtmann 
533cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_3SLOT)
5341da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
5351da177e4SLinus Torvalds 
536cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_5SLOT)
5371da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
5381da177e4SLinus Torvalds 
539cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV2) {
5401da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
5415b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
5425b7f9909SMarcel Holtmann 	}
5431da177e4SLinus Torvalds 
544cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV3) {
5451da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
5465b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
5475b7f9909SMarcel Holtmann 	}
5485b7f9909SMarcel Holtmann 
54945db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
5505b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
5515b7f9909SMarcel Holtmann 
552cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV4)
5535b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
5545b7f9909SMarcel Holtmann 
555cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV5)
5565b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
5571da177e4SLinus Torvalds 
558cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
559efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
560efc7688bSMarcel Holtmann 
561cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
562efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
563efc7688bSMarcel Holtmann 
564cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
565efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
5661da177e4SLinus Torvalds }
5671da177e4SLinus Torvalds 
568971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
569971e3a4bSAndre Guedes 					   struct sk_buff *skb)
570971e3a4bSAndre Guedes {
571971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
572971e3a4bSAndre Guedes 
5739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
574971e3a4bSAndre Guedes 
575971e3a4bSAndre Guedes 	if (rp->status)
57642c6b129SJohan Hedberg 		return;
577971e3a4bSAndre Guedes 
57857af75a8SMarcel Holtmann 	if (hdev->max_page < rp->max_page)
579d2c5d77fSJohan Hedberg 		hdev->max_page = rp->max_page;
580d2c5d77fSJohan Hedberg 
581cad718edSJohan Hedberg 	if (rp->page < HCI_MAX_PAGES)
582cad718edSJohan Hedberg 		memcpy(hdev->features[rp->page], rp->features, 8);
583971e3a4bSAndre Guedes }
584971e3a4bSAndre Guedes 
5851e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
5861e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
5871e89cffbSAndrei Emeltchenko {
5881e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
5891e89cffbSAndrei Emeltchenko 
5909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5911e89cffbSAndrei Emeltchenko 
59245296acdSMarcel Holtmann 	if (rp->status)
59345296acdSMarcel Holtmann 		return;
59445296acdSMarcel Holtmann 
5951e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
5961e89cffbSAndrei Emeltchenko }
5971e89cffbSAndrei Emeltchenko 
598a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
599a9de9248SMarcel Holtmann {
600a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
601a9de9248SMarcel Holtmann 
6029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
603a9de9248SMarcel Holtmann 
604a9de9248SMarcel Holtmann 	if (rp->status)
605a9de9248SMarcel Holtmann 		return;
606a9de9248SMarcel Holtmann 
607a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
608a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
609a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
610a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
611da1f5198SMarcel Holtmann 
612da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
613da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
614da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
615da1f5198SMarcel Holtmann 	}
616da1f5198SMarcel Holtmann 
617da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
618da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
6191da177e4SLinus Torvalds 
620807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
621807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
6221da177e4SLinus Torvalds }
6231da177e4SLinus Torvalds 
624a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
625a9de9248SMarcel Holtmann {
626a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6271da177e4SLinus Torvalds 
6289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
629a9de9248SMarcel Holtmann 
630e30d3f5fSMarcel Holtmann 	if (rp->status)
631e30d3f5fSMarcel Holtmann 		return;
632e30d3f5fSMarcel Holtmann 
633e30d3f5fSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
634a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
635e30d3f5fSMarcel Holtmann 
636e30d3f5fSMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
637e30d3f5fSMarcel Holtmann 		bacpy(&hdev->setup_addr, &rp->bdaddr);
63823bb5763SJohan Hedberg }
63923bb5763SJohan Hedberg 
640f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
641f332ec66SJohan Hedberg 					   struct sk_buff *skb)
642f332ec66SJohan Hedberg {
643f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
644f332ec66SJohan Hedberg 
645f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
646f332ec66SJohan Hedberg 
64745296acdSMarcel Holtmann 	if (rp->status)
64845296acdSMarcel Holtmann 		return;
64945296acdSMarcel Holtmann 
65045296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags)) {
651f332ec66SJohan Hedberg 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
652f332ec66SJohan Hedberg 		hdev->page_scan_window = __le16_to_cpu(rp->window);
653f332ec66SJohan Hedberg 	}
654f332ec66SJohan Hedberg }
655f332ec66SJohan Hedberg 
6564a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
6574a3ee763SJohan Hedberg 					    struct sk_buff *skb)
6584a3ee763SJohan Hedberg {
6594a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6604a3ee763SJohan Hedberg 	struct hci_cp_write_page_scan_activity *sent;
6614a3ee763SJohan Hedberg 
6624a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6634a3ee763SJohan Hedberg 
6644a3ee763SJohan Hedberg 	if (status)
6654a3ee763SJohan Hedberg 		return;
6664a3ee763SJohan Hedberg 
6674a3ee763SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
6684a3ee763SJohan Hedberg 	if (!sent)
6694a3ee763SJohan Hedberg 		return;
6704a3ee763SJohan Hedberg 
6714a3ee763SJohan Hedberg 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
6724a3ee763SJohan Hedberg 	hdev->page_scan_window = __le16_to_cpu(sent->window);
6734a3ee763SJohan Hedberg }
6744a3ee763SJohan Hedberg 
675f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
676f332ec66SJohan Hedberg 					   struct sk_buff *skb)
677f332ec66SJohan Hedberg {
678f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
679f332ec66SJohan Hedberg 
680f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
681f332ec66SJohan Hedberg 
68245296acdSMarcel Holtmann 	if (rp->status)
68345296acdSMarcel Holtmann 		return;
68445296acdSMarcel Holtmann 
68545296acdSMarcel Holtmann 	if (test_bit(HCI_INIT, &hdev->flags))
686f332ec66SJohan Hedberg 		hdev->page_scan_type = rp->type;
687f332ec66SJohan Hedberg }
688f332ec66SJohan Hedberg 
6894a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
6904a3ee763SJohan Hedberg 					struct sk_buff *skb)
6914a3ee763SJohan Hedberg {
6924a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6934a3ee763SJohan Hedberg 	u8 *type;
6944a3ee763SJohan Hedberg 
6954a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6964a3ee763SJohan Hedberg 
6974a3ee763SJohan Hedberg 	if (status)
6984a3ee763SJohan Hedberg 		return;
6994a3ee763SJohan Hedberg 
7004a3ee763SJohan Hedberg 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
7014a3ee763SJohan Hedberg 	if (type)
7024a3ee763SJohan Hedberg 		hdev->page_scan_type = *type;
7034a3ee763SJohan Hedberg }
7044a3ee763SJohan Hedberg 
705350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
706350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
707350ee4cfSAndrei Emeltchenko {
708350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
709350ee4cfSAndrei Emeltchenko 
7109f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
711350ee4cfSAndrei Emeltchenko 
712350ee4cfSAndrei Emeltchenko 	if (rp->status)
713350ee4cfSAndrei Emeltchenko 		return;
714350ee4cfSAndrei Emeltchenko 
715350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
716350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
717350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
718350ee4cfSAndrei Emeltchenko 
719350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
720350ee4cfSAndrei Emeltchenko 
721350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
722350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
723350ee4cfSAndrei Emeltchenko }
724350ee4cfSAndrei Emeltchenko 
72533f35721SJohan Hedberg static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb)
72633f35721SJohan Hedberg {
72733f35721SJohan Hedberg 	struct hci_rp_read_clock *rp = (void *) skb->data;
72833f35721SJohan Hedberg 	struct hci_cp_read_clock *cp;
72933f35721SJohan Hedberg 	struct hci_conn *conn;
73033f35721SJohan Hedberg 
73133f35721SJohan Hedberg 	BT_DBG("%s", hdev->name);
73233f35721SJohan Hedberg 
73333f35721SJohan Hedberg 	if (skb->len < sizeof(*rp))
73433f35721SJohan Hedberg 		return;
73533f35721SJohan Hedberg 
73633f35721SJohan Hedberg 	if (rp->status)
73733f35721SJohan Hedberg 		return;
73833f35721SJohan Hedberg 
73933f35721SJohan Hedberg 	hci_dev_lock(hdev);
74033f35721SJohan Hedberg 
74133f35721SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
74233f35721SJohan Hedberg 	if (!cp)
74333f35721SJohan Hedberg 		goto unlock;
74433f35721SJohan Hedberg 
74533f35721SJohan Hedberg 	if (cp->which == 0x00) {
74633f35721SJohan Hedberg 		hdev->clock = le32_to_cpu(rp->clock);
74733f35721SJohan Hedberg 		goto unlock;
74833f35721SJohan Hedberg 	}
74933f35721SJohan Hedberg 
75033f35721SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
75133f35721SJohan Hedberg 	if (conn) {
75233f35721SJohan Hedberg 		conn->clock = le32_to_cpu(rp->clock);
75333f35721SJohan Hedberg 		conn->clock_accuracy = le16_to_cpu(rp->accuracy);
75433f35721SJohan Hedberg 	}
75533f35721SJohan Hedberg 
75633f35721SJohan Hedberg unlock:
75733f35721SJohan Hedberg 	hci_dev_unlock(hdev);
75833f35721SJohan Hedberg }
75933f35721SJohan Hedberg 
760928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
761928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
762928abaa7SAndrei Emeltchenko {
763928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
764928abaa7SAndrei Emeltchenko 
7659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
766928abaa7SAndrei Emeltchenko 
767928abaa7SAndrei Emeltchenko 	if (rp->status)
7688e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
769928abaa7SAndrei Emeltchenko 
770928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
771928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
772928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
773928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
774928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
775928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
776928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
777928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
778928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
779928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
780928abaa7SAndrei Emeltchenko 
7818e2a0d92SAndrei Emeltchenko a2mp_rsp:
7828e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
783928abaa7SAndrei Emeltchenko }
784928abaa7SAndrei Emeltchenko 
785903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
786903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
787903e4541SAndrei Emeltchenko {
788903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
789903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
790903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
791903e4541SAndrei Emeltchenko 
792903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
793903e4541SAndrei Emeltchenko 
794903e4541SAndrei Emeltchenko 	if (rp->status)
795903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
796903e4541SAndrei Emeltchenko 
797903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
798903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
799903e4541SAndrei Emeltchenko 
800903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
8012e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
802903e4541SAndrei Emeltchenko 
803903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
804903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
805903e4541SAndrei Emeltchenko 
806903e4541SAndrei Emeltchenko 		/* Read other fragments */
807903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
808903e4541SAndrei Emeltchenko 
809903e4541SAndrei Emeltchenko 		return;
810903e4541SAndrei Emeltchenko 	}
811903e4541SAndrei Emeltchenko 
812903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
813903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
814903e4541SAndrei Emeltchenko 	assoc->offset = 0;
815903e4541SAndrei Emeltchenko 
816903e4541SAndrei Emeltchenko a2mp_rsp:
817903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
818903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
8199495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
820903e4541SAndrei Emeltchenko }
821903e4541SAndrei Emeltchenko 
822d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
823d5859e22SJohan Hedberg 					 struct sk_buff *skb)
824d5859e22SJohan Hedberg {
82591c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
826d5859e22SJohan Hedberg 
8279f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
828d5859e22SJohan Hedberg 
82945296acdSMarcel Holtmann 	if (rp->status)
83045296acdSMarcel Holtmann 		return;
83145296acdSMarcel Holtmann 
83291c4e9b1SMarcel Holtmann 	hdev->inq_tx_power = rp->tx_power;
833d5859e22SJohan Hedberg }
834d5859e22SJohan Hedberg 
835980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
836980e1a53SJohan Hedberg {
837980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
838980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
839980e1a53SJohan Hedberg 	struct hci_conn *conn;
840980e1a53SJohan Hedberg 
8419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
842980e1a53SJohan Hedberg 
84356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
84456e5cb86SJohan Hedberg 
845a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
846744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
847980e1a53SJohan Hedberg 
848fa1bd918SMikel Astiz 	if (rp->status)
84956e5cb86SJohan Hedberg 		goto unlock;
850980e1a53SJohan Hedberg 
851980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
852980e1a53SJohan Hedberg 	if (!cp)
85356e5cb86SJohan Hedberg 		goto unlock;
854980e1a53SJohan Hedberg 
855980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
856980e1a53SJohan Hedberg 	if (conn)
857980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
85856e5cb86SJohan Hedberg 
85956e5cb86SJohan Hedberg unlock:
86056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
861980e1a53SJohan Hedberg }
862980e1a53SJohan Hedberg 
863980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
864980e1a53SJohan Hedberg {
865980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
866980e1a53SJohan Hedberg 
8679f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
868980e1a53SJohan Hedberg 
86956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
87056e5cb86SJohan Hedberg 
871a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
872744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
873980e1a53SJohan Hedberg 						 rp->status);
87456e5cb86SJohan Hedberg 
87556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
876980e1a53SJohan Hedberg }
87756e5cb86SJohan Hedberg 
8786ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8796ed58ec5SVille Tervo 				       struct sk_buff *skb)
8806ed58ec5SVille Tervo {
8816ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
8826ed58ec5SVille Tervo 
8839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8846ed58ec5SVille Tervo 
8856ed58ec5SVille Tervo 	if (rp->status)
8866ed58ec5SVille Tervo 		return;
8876ed58ec5SVille Tervo 
8886ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
8896ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8906ed58ec5SVille Tervo 
8916ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8926ed58ec5SVille Tervo 
8936ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8946ed58ec5SVille Tervo }
895980e1a53SJohan Hedberg 
89660e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
89760e77321SJohan Hedberg 					  struct sk_buff *skb)
89860e77321SJohan Hedberg {
89960e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
90060e77321SJohan Hedberg 
90160e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
90260e77321SJohan Hedberg 
90345296acdSMarcel Holtmann 	if (rp->status)
90445296acdSMarcel Holtmann 		return;
90545296acdSMarcel Holtmann 
90660e77321SJohan Hedberg 	memcpy(hdev->le_features, rp->features, 8);
90760e77321SJohan Hedberg }
90860e77321SJohan Hedberg 
9098fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
9108fa19098SJohan Hedberg 					struct sk_buff *skb)
9118fa19098SJohan Hedberg {
9128fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
9138fa19098SJohan Hedberg 
9148fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9158fa19098SJohan Hedberg 
91645296acdSMarcel Holtmann 	if (rp->status)
91745296acdSMarcel Holtmann 		return;
91845296acdSMarcel Holtmann 
9198fa19098SJohan Hedberg 	hdev->adv_tx_power = rp->tx_power;
9208fa19098SJohan Hedberg }
9218fa19098SJohan Hedberg 
922a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
923a5c29683SJohan Hedberg {
924a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
925a5c29683SJohan Hedberg 
9269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
927a5c29683SJohan Hedberg 
92856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92956e5cb86SJohan Hedberg 
930a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
93104124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
93204124681SGustavo F. Padovan 						 rp->status);
93356e5cb86SJohan Hedberg 
93456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
935a5c29683SJohan Hedberg }
936a5c29683SJohan Hedberg 
937a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
938a5c29683SJohan Hedberg 					  struct sk_buff *skb)
939a5c29683SJohan Hedberg {
940a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
941a5c29683SJohan Hedberg 
9429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
943a5c29683SJohan Hedberg 
94456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
94556e5cb86SJohan Hedberg 
946a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
947744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
94804124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
94956e5cb86SJohan Hedberg 
95056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
951a5c29683SJohan Hedberg }
952a5c29683SJohan Hedberg 
9531143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9541143d458SBrian Gix {
9551143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9561143d458SBrian Gix 
9579f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9581143d458SBrian Gix 
9591143d458SBrian Gix 	hci_dev_lock(hdev);
9601143d458SBrian Gix 
961a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
962272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
963272d90dfSJohan Hedberg 						 0, rp->status);
9641143d458SBrian Gix 
9651143d458SBrian Gix 	hci_dev_unlock(hdev);
9661143d458SBrian Gix }
9671143d458SBrian Gix 
9681143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9691143d458SBrian Gix 					  struct sk_buff *skb)
9701143d458SBrian Gix {
9711143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9721143d458SBrian Gix 
9739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9741143d458SBrian Gix 
9751143d458SBrian Gix 	hci_dev_lock(hdev);
9761143d458SBrian Gix 
977a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9781143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
97904124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
9801143d458SBrian Gix 
9811143d458SBrian Gix 	hci_dev_unlock(hdev);
9821143d458SBrian Gix }
9831143d458SBrian Gix 
9844d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
985c35938b2SSzymon Janc 				       struct sk_buff *skb)
986c35938b2SSzymon Janc {
987c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
988c35938b2SSzymon Janc 
9899f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
990c35938b2SSzymon Janc 
99156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
9924d2d2796SMarcel Holtmann 	mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer,
9934d2d2796SMarcel Holtmann 					  NULL, NULL, rp->status);
9944d2d2796SMarcel Holtmann 	hci_dev_unlock(hdev);
9954d2d2796SMarcel Holtmann }
9964d2d2796SMarcel Holtmann 
9974d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
9984d2d2796SMarcel Holtmann 					   struct sk_buff *skb)
9994d2d2796SMarcel Holtmann {
10004d2d2796SMarcel Holtmann 	struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
10014d2d2796SMarcel Holtmann 
10024d2d2796SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10034d2d2796SMarcel Holtmann 
10044d2d2796SMarcel Holtmann 	hci_dev_lock(hdev);
10054d2d2796SMarcel Holtmann 	mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192,
10064d2d2796SMarcel Holtmann 					  rp->hash256, rp->randomizer256,
10074d2d2796SMarcel Holtmann 					  rp->status);
100856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1009c35938b2SSzymon Janc }
1010c35938b2SSzymon Janc 
10117a4cd51dSMarcel Holtmann 
10127a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
10137a4cd51dSMarcel Holtmann {
10147a4cd51dSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
10157a4cd51dSMarcel Holtmann 	bdaddr_t *sent;
10167a4cd51dSMarcel Holtmann 
10177a4cd51dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10187a4cd51dSMarcel Holtmann 
101945296acdSMarcel Holtmann 	if (status)
102045296acdSMarcel Holtmann 		return;
102145296acdSMarcel Holtmann 
10227a4cd51dSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
10237a4cd51dSMarcel Holtmann 	if (!sent)
10247a4cd51dSMarcel Holtmann 		return;
10257a4cd51dSMarcel Holtmann 
10267a4cd51dSMarcel Holtmann 	hci_dev_lock(hdev);
10277a4cd51dSMarcel Holtmann 
10287a4cd51dSMarcel Holtmann 	bacpy(&hdev->random_addr, sent);
10297a4cd51dSMarcel Holtmann 
10307a4cd51dSMarcel Holtmann 	hci_dev_unlock(hdev);
10317a4cd51dSMarcel Holtmann }
10327a4cd51dSMarcel Holtmann 
1033c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1034c1d5dc4aSJohan Hedberg {
1035c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
1036c1d5dc4aSJohan Hedberg 
1037c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1038c1d5dc4aSJohan Hedberg 
103945296acdSMarcel Holtmann 	if (status)
1040c1d5dc4aSJohan Hedberg 		return;
1041c1d5dc4aSJohan Hedberg 
104245296acdSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
104345296acdSMarcel Holtmann 	if (!sent)
10443c857757SJohan Hedberg 		return;
10453c857757SJohan Hedberg 
1046c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
1047c1d5dc4aSJohan Hedberg 
10483c857757SJohan Hedberg 	/* If we're doing connection initation as peripheral. Set a
10493c857757SJohan Hedberg 	 * timeout in case something goes wrong.
10503c857757SJohan Hedberg 	 */
10513c857757SJohan Hedberg 	if (*sent) {
10523c857757SJohan Hedberg 		struct hci_conn *conn;
10533c857757SJohan Hedberg 
105466c417c1SJohan Hedberg 		set_bit(HCI_LE_ADV, &hdev->dev_flags);
105566c417c1SJohan Hedberg 
10563c857757SJohan Hedberg 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
10573c857757SJohan Hedberg 		if (conn)
10583c857757SJohan Hedberg 			queue_delayed_work(hdev->workqueue,
10593c857757SJohan Hedberg 					   &conn->le_conn_timeout,
106009ae260bSJohan Hedberg 					   conn->conn_timeout);
106166c417c1SJohan Hedberg 	} else {
106266c417c1SJohan Hedberg 		clear_bit(HCI_LE_ADV, &hdev->dev_flags);
10633c857757SJohan Hedberg 	}
10643c857757SJohan Hedberg 
106504b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
1066c1d5dc4aSJohan Hedberg }
1067c1d5dc4aSJohan Hedberg 
1068533553f8SMarcel Holtmann static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1069533553f8SMarcel Holtmann {
1070533553f8SMarcel Holtmann 	struct hci_cp_le_set_scan_param *cp;
1071533553f8SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
1072533553f8SMarcel Holtmann 
1073533553f8SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1074533553f8SMarcel Holtmann 
107545296acdSMarcel Holtmann 	if (status)
107645296acdSMarcel Holtmann 		return;
107745296acdSMarcel Holtmann 
1078533553f8SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM);
1079533553f8SMarcel Holtmann 	if (!cp)
1080533553f8SMarcel Holtmann 		return;
1081533553f8SMarcel Holtmann 
1082533553f8SMarcel Holtmann 	hci_dev_lock(hdev);
1083533553f8SMarcel Holtmann 
1084533553f8SMarcel Holtmann 	hdev->le_scan_type = cp->type;
1085533553f8SMarcel Holtmann 
1086533553f8SMarcel Holtmann 	hci_dev_unlock(hdev);
1087533553f8SMarcel Holtmann }
1088533553f8SMarcel Holtmann 
1089b9a6328fSJohan Hedberg static bool has_pending_adv_report(struct hci_dev *hdev)
1090b9a6328fSJohan Hedberg {
1091b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1092b9a6328fSJohan Hedberg 
1093b9a6328fSJohan Hedberg 	return bacmp(&d->last_adv_addr, BDADDR_ANY);
1094b9a6328fSJohan Hedberg }
1095b9a6328fSJohan Hedberg 
1096b9a6328fSJohan Hedberg static void clear_pending_adv_report(struct hci_dev *hdev)
1097b9a6328fSJohan Hedberg {
1098b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1099b9a6328fSJohan Hedberg 
1100b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, BDADDR_ANY);
1101b9a6328fSJohan Hedberg 	d->last_adv_data_len = 0;
1102b9a6328fSJohan Hedberg }
1103b9a6328fSJohan Hedberg 
1104b9a6328fSJohan Hedberg static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
1105c70a7e4cSMarcel Holtmann 				     u8 bdaddr_type, s8 rssi, u32 flags,
1106c70a7e4cSMarcel Holtmann 				     u8 *data, u8 len)
1107b9a6328fSJohan Hedberg {
1108b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
1109b9a6328fSJohan Hedberg 
1110b9a6328fSJohan Hedberg 	bacpy(&d->last_adv_addr, bdaddr);
1111b9a6328fSJohan Hedberg 	d->last_adv_addr_type = bdaddr_type;
1112ff5cd29fSJohan Hedberg 	d->last_adv_rssi = rssi;
1113c70a7e4cSMarcel Holtmann 	d->last_adv_flags = flags;
1114b9a6328fSJohan Hedberg 	memcpy(d->last_adv_data, data, len);
1115b9a6328fSJohan Hedberg 	d->last_adv_data_len = len;
1116b9a6328fSJohan Hedberg }
1117b9a6328fSJohan Hedberg 
1118eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1119eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1120eb9d91f5SAndre Guedes {
1121eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1122eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1123eb9d91f5SAndre Guedes 
11249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1125eb9d91f5SAndre Guedes 
112645296acdSMarcel Holtmann 	if (status)
1127eb9d91f5SAndre Guedes 		return;
1128eb9d91f5SAndre Guedes 
112945296acdSMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
113045296acdSMarcel Holtmann 	if (!cp)
11317ba8b4beSAndre Guedes 		return;
11327ba8b4beSAndre Guedes 
11333fd319b8SAndre Guedes 	switch (cp->enable) {
11343fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
1135d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1136b9a6328fSJohan Hedberg 		if (hdev->le_scan_type == LE_SCAN_ACTIVE)
1137b9a6328fSJohan Hedberg 			clear_pending_adv_report(hdev);
113868a8aea4SAndrei Emeltchenko 		break;
113968a8aea4SAndrei Emeltchenko 
114076a388beSAndre Guedes 	case LE_SCAN_DISABLE:
1141b9a6328fSJohan Hedberg 		/* We do this here instead of when setting DISCOVERY_STOPPED
1142b9a6328fSJohan Hedberg 		 * since the latter would potentially require waiting for
1143b9a6328fSJohan Hedberg 		 * inquiry to stop too.
1144b9a6328fSJohan Hedberg 		 */
1145b9a6328fSJohan Hedberg 		if (has_pending_adv_report(hdev)) {
1146b9a6328fSJohan Hedberg 			struct discovery_state *d = &hdev->discovery;
1147b9a6328fSJohan Hedberg 
1148b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
1149ab0aa433SJohan Hedberg 					  d->last_adv_addr_type, NULL,
1150c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
1151ab0aa433SJohan Hedberg 					  d->last_adv_data,
1152b9a6328fSJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
1153b9a6328fSJohan Hedberg 		}
1154b9a6328fSJohan Hedberg 
1155317ac8cbSJohan Hedberg 		/* Cancel this timer so that we don't try to disable scanning
1156317ac8cbSJohan Hedberg 		 * when it's already disabled.
1157317ac8cbSJohan Hedberg 		 */
1158317ac8cbSJohan Hedberg 		cancel_delayed_work(&hdev->le_scan_disable);
1159317ac8cbSJohan Hedberg 
1160d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1161e8bb6b97SJohan Hedberg 
116281ad6fd9SJohan Hedberg 		/* The HCI_LE_SCAN_INTERRUPTED flag indicates that we
116381ad6fd9SJohan Hedberg 		 * interrupted scanning due to a connect request. Mark
1164e8bb6b97SJohan Hedberg 		 * therefore discovery as stopped. If this was not
1165e8bb6b97SJohan Hedberg 		 * because of a connect request advertising might have
1166e8bb6b97SJohan Hedberg 		 * been disabled because of active scanning, so
1167e8bb6b97SJohan Hedberg 		 * re-enable it again if necessary.
116881ad6fd9SJohan Hedberg 		 */
116981ad6fd9SJohan Hedberg 		if (test_and_clear_bit(HCI_LE_SCAN_INTERRUPTED,
117081ad6fd9SJohan Hedberg 				       &hdev->dev_flags))
117181ad6fd9SJohan Hedberg 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1172e8bb6b97SJohan Hedberg 		else if (!test_bit(HCI_LE_ADV, &hdev->dev_flags) &&
117334722277SJohan Hedberg 			 hdev->discovery.state == DISCOVERY_FINDING)
1174e8bb6b97SJohan Hedberg 			mgmt_reenable_advertising(hdev);
1175e8bb6b97SJohan Hedberg 
117668a8aea4SAndrei Emeltchenko 		break;
117768a8aea4SAndrei Emeltchenko 
117868a8aea4SAndrei Emeltchenko 	default:
117968a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
118068a8aea4SAndrei Emeltchenko 		break;
118135815085SAndre Guedes 	}
1182eb9d91f5SAndre Guedes }
1183eb9d91f5SAndre Guedes 
1184cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1185cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
1186cf1d081fSJohan Hedberg {
1187cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1188cf1d081fSJohan Hedberg 
1189cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1190cf1d081fSJohan Hedberg 
119145296acdSMarcel Holtmann 	if (rp->status)
119245296acdSMarcel Holtmann 		return;
119345296acdSMarcel Holtmann 
1194cf1d081fSJohan Hedberg 	hdev->le_white_list_size = rp->size;
1195cf1d081fSJohan Hedberg }
1196cf1d081fSJohan Hedberg 
11970f36b589SMarcel Holtmann static void hci_cc_le_clear_white_list(struct hci_dev *hdev,
11980f36b589SMarcel Holtmann 				       struct sk_buff *skb)
11990f36b589SMarcel Holtmann {
12000f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12010f36b589SMarcel Holtmann 
12020f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12030f36b589SMarcel Holtmann 
120445296acdSMarcel Holtmann 	if (status)
120545296acdSMarcel Holtmann 		return;
120645296acdSMarcel Holtmann 
1207dcc36c16SJohan Hedberg 	hci_bdaddr_list_clear(&hdev->le_white_list);
12080f36b589SMarcel Holtmann }
12090f36b589SMarcel Holtmann 
12100f36b589SMarcel Holtmann static void hci_cc_le_add_to_white_list(struct hci_dev *hdev,
12110f36b589SMarcel Holtmann 					struct sk_buff *skb)
12120f36b589SMarcel Holtmann {
12130f36b589SMarcel Holtmann 	struct hci_cp_le_add_to_white_list *sent;
12140f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12150f36b589SMarcel Holtmann 
12160f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12170f36b589SMarcel Holtmann 
121845296acdSMarcel Holtmann 	if (status)
121945296acdSMarcel Holtmann 		return;
122045296acdSMarcel Holtmann 
12210f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST);
12220f36b589SMarcel Holtmann 	if (!sent)
12230f36b589SMarcel Holtmann 		return;
12240f36b589SMarcel Holtmann 
1225dcc36c16SJohan Hedberg 	hci_bdaddr_list_add(&hdev->le_white_list, &sent->bdaddr,
1226dcc36c16SJohan Hedberg 			   sent->bdaddr_type);
12270f36b589SMarcel Holtmann }
12280f36b589SMarcel Holtmann 
12290f36b589SMarcel Holtmann static void hci_cc_le_del_from_white_list(struct hci_dev *hdev,
12300f36b589SMarcel Holtmann 					  struct sk_buff *skb)
12310f36b589SMarcel Holtmann {
12320f36b589SMarcel Holtmann 	struct hci_cp_le_del_from_white_list *sent;
12330f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
12340f36b589SMarcel Holtmann 
12350f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
12360f36b589SMarcel Holtmann 
123745296acdSMarcel Holtmann 	if (status)
123845296acdSMarcel Holtmann 		return;
123945296acdSMarcel Holtmann 
12400f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST);
12410f36b589SMarcel Holtmann 	if (!sent)
12420f36b589SMarcel Holtmann 		return;
12430f36b589SMarcel Holtmann 
1244dcc36c16SJohan Hedberg 	hci_bdaddr_list_del(&hdev->le_white_list, &sent->bdaddr,
1245dcc36c16SJohan Hedberg 			    sent->bdaddr_type);
12460f36b589SMarcel Holtmann }
12470f36b589SMarcel Holtmann 
12489b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
12499b008c04SJohan Hedberg 					    struct sk_buff *skb)
12509b008c04SJohan Hedberg {
12519b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
12529b008c04SJohan Hedberg 
12539b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
12549b008c04SJohan Hedberg 
125545296acdSMarcel Holtmann 	if (rp->status)
125645296acdSMarcel Holtmann 		return;
125745296acdSMarcel Holtmann 
12589b008c04SJohan Hedberg 	memcpy(hdev->le_states, rp->le_states, 8);
12599b008c04SJohan Hedberg }
12609b008c04SJohan Hedberg 
12616039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1262f9b49306SAndre Guedes 					   struct sk_buff *skb)
1263f9b49306SAndre Guedes {
126406199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1265f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1266f9b49306SAndre Guedes 
12679f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1268f9b49306SAndre Guedes 
126945296acdSMarcel Holtmann 	if (status)
127045296acdSMarcel Holtmann 		return;
127145296acdSMarcel Holtmann 
127206199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
12738f984dfaSJohan Hedberg 	if (!sent)
1274f9b49306SAndre Guedes 		return;
1275f9b49306SAndre Guedes 
1276416a4ae5SJohan Hedberg 	if (sent->le) {
1277cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE;
1278416a4ae5SJohan Hedberg 		set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1279416a4ae5SJohan Hedberg 	} else {
1280cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE;
1281416a4ae5SJohan Hedberg 		clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1282f3d3444aSJohan Hedberg 		clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1283416a4ae5SJohan Hedberg 	}
128453b2caabSJohan Hedberg 
128553b2caabSJohan Hedberg 	if (sent->simul)
1286cad718edSJohan Hedberg 		hdev->features[1][0] |= LMP_HOST_LE_BREDR;
128753b2caabSJohan Hedberg 	else
1288cad718edSJohan Hedberg 		hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
12898f984dfaSJohan Hedberg }
1290f9b49306SAndre Guedes 
129156ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
129256ed2cb8SJohan Hedberg {
129356ed2cb8SJohan Hedberg 	struct hci_cp_le_set_adv_param *cp;
129456ed2cb8SJohan Hedberg 	u8 status = *((u8 *) skb->data);
129556ed2cb8SJohan Hedberg 
129656ed2cb8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
129756ed2cb8SJohan Hedberg 
129856ed2cb8SJohan Hedberg 	if (status)
129956ed2cb8SJohan Hedberg 		return;
130056ed2cb8SJohan Hedberg 
130156ed2cb8SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
130256ed2cb8SJohan Hedberg 	if (!cp)
130356ed2cb8SJohan Hedberg 		return;
130456ed2cb8SJohan Hedberg 
130556ed2cb8SJohan Hedberg 	hci_dev_lock(hdev);
130656ed2cb8SJohan Hedberg 	hdev->adv_addr_type = cp->own_address_type;
130756ed2cb8SJohan Hedberg 	hci_dev_unlock(hdev);
130856ed2cb8SJohan Hedberg }
130956ed2cb8SJohan Hedberg 
131093c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
131193c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
131293c284eeSAndrei Emeltchenko {
131393c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
131493c284eeSAndrei Emeltchenko 
131593c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
131693c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
131793c284eeSAndrei Emeltchenko 
131893c284eeSAndrei Emeltchenko 	if (rp->status)
131993c284eeSAndrei Emeltchenko 		return;
132093c284eeSAndrei Emeltchenko 
132193c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
132293c284eeSAndrei Emeltchenko }
132393c284eeSAndrei Emeltchenko 
13245ae76a94SAndrzej Kaczmarek static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
13255ae76a94SAndrzej Kaczmarek {
13265ae76a94SAndrzej Kaczmarek 	struct hci_rp_read_rssi *rp = (void *) skb->data;
13275ae76a94SAndrzej Kaczmarek 	struct hci_conn *conn;
13285ae76a94SAndrzej Kaczmarek 
13295ae76a94SAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
13305ae76a94SAndrzej Kaczmarek 
13315ae76a94SAndrzej Kaczmarek 	if (rp->status)
13325ae76a94SAndrzej Kaczmarek 		return;
13335ae76a94SAndrzej Kaczmarek 
13345ae76a94SAndrzej Kaczmarek 	hci_dev_lock(hdev);
13355ae76a94SAndrzej Kaczmarek 
13365ae76a94SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
13375ae76a94SAndrzej Kaczmarek 	if (conn)
13385ae76a94SAndrzej Kaczmarek 		conn->rssi = rp->rssi;
13395ae76a94SAndrzej Kaczmarek 
13405ae76a94SAndrzej Kaczmarek 	hci_dev_unlock(hdev);
13415ae76a94SAndrzej Kaczmarek }
13425ae76a94SAndrzej Kaczmarek 
13435a134faeSAndrzej Kaczmarek static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb)
13445a134faeSAndrzej Kaczmarek {
13455a134faeSAndrzej Kaczmarek 	struct hci_cp_read_tx_power *sent;
13465a134faeSAndrzej Kaczmarek 	struct hci_rp_read_tx_power *rp = (void *) skb->data;
13475a134faeSAndrzej Kaczmarek 	struct hci_conn *conn;
13485a134faeSAndrzej Kaczmarek 
13495a134faeSAndrzej Kaczmarek 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
13505a134faeSAndrzej Kaczmarek 
13515a134faeSAndrzej Kaczmarek 	if (rp->status)
13525a134faeSAndrzej Kaczmarek 		return;
13535a134faeSAndrzej Kaczmarek 
13545a134faeSAndrzej Kaczmarek 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
13555a134faeSAndrzej Kaczmarek 	if (!sent)
13565a134faeSAndrzej Kaczmarek 		return;
13575a134faeSAndrzej Kaczmarek 
13585a134faeSAndrzej Kaczmarek 	hci_dev_lock(hdev);
13595a134faeSAndrzej Kaczmarek 
13605a134faeSAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1361d0455ed9SAndrzej Kaczmarek 	if (!conn)
1362d0455ed9SAndrzej Kaczmarek 		goto unlock;
13635a134faeSAndrzej Kaczmarek 
1364d0455ed9SAndrzej Kaczmarek 	switch (sent->type) {
1365d0455ed9SAndrzej Kaczmarek 	case 0x00:
1366d0455ed9SAndrzej Kaczmarek 		conn->tx_power = rp->tx_power;
1367d0455ed9SAndrzej Kaczmarek 		break;
1368d0455ed9SAndrzej Kaczmarek 	case 0x01:
1369d0455ed9SAndrzej Kaczmarek 		conn->max_tx_power = rp->tx_power;
1370d0455ed9SAndrzej Kaczmarek 		break;
1371d0455ed9SAndrzej Kaczmarek 	}
1372d0455ed9SAndrzej Kaczmarek 
1373d0455ed9SAndrzej Kaczmarek unlock:
13745a134faeSAndrzej Kaczmarek 	hci_dev_unlock(hdev);
13755a134faeSAndrzej Kaczmarek }
13765a134faeSAndrzej Kaczmarek 
13776039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1378a9de9248SMarcel Holtmann {
13799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1380a9de9248SMarcel Holtmann 
1381a9de9248SMarcel Holtmann 	if (status) {
1382a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1383314b2381SJohan Hedberg 		return;
1384314b2381SJohan Hedberg 	}
1385314b2381SJohan Hedberg 
138689352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1387a9de9248SMarcel Holtmann }
1388a9de9248SMarcel Holtmann 
13896039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
13901da177e4SLinus Torvalds {
1391a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
13921da177e4SLinus Torvalds 	struct hci_conn *conn;
13931da177e4SLinus Torvalds 
13949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1395a9de9248SMarcel Holtmann 
1396a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
13971da177e4SLinus Torvalds 	if (!cp)
13981da177e4SLinus Torvalds 		return;
13991da177e4SLinus Torvalds 
14001da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14011da177e4SLinus Torvalds 
14021da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
14031da177e4SLinus Torvalds 
14046ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
14051da177e4SLinus Torvalds 
14061da177e4SLinus Torvalds 	if (status) {
14071da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
14084c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
14091da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
14101da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
14111da177e4SLinus Torvalds 				hci_conn_del(conn);
14124c67bc74SMarcel Holtmann 			} else
14134c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
14141da177e4SLinus Torvalds 		}
14151da177e4SLinus Torvalds 	} else {
14161da177e4SLinus Torvalds 		if (!conn) {
1417a5c4e309SJohan Hedberg 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr,
1418a5c4e309SJohan Hedberg 					    HCI_ROLE_MASTER);
1419a5c4e309SJohan Hedberg 			if (!conn)
1420893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
14211da177e4SLinus Torvalds 		}
14221da177e4SLinus Torvalds 	}
14231da177e4SLinus Torvalds 
14241da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14251da177e4SLinus Torvalds }
14261da177e4SLinus Torvalds 
1427a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
14281da177e4SLinus Torvalds {
1429a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
14301da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
14311da177e4SLinus Torvalds 	__u16 handle;
14321da177e4SLinus Torvalds 
14339f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1434b6a0dc82SMarcel Holtmann 
1435a9de9248SMarcel Holtmann 	if (!status)
1436a9de9248SMarcel Holtmann 		return;
1437a9de9248SMarcel Holtmann 
1438a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
14391da177e4SLinus Torvalds 	if (!cp)
1440a9de9248SMarcel Holtmann 		return;
14411da177e4SLinus Torvalds 
14421da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
14431da177e4SLinus Torvalds 
14449f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
14451da177e4SLinus Torvalds 
14461da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14471da177e4SLinus Torvalds 
14481da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14495a08ecceSAndrei Emeltchenko 	if (acl) {
14505a08ecceSAndrei Emeltchenko 		sco = acl->link;
14515a08ecceSAndrei Emeltchenko 		if (sco) {
14521da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
14531da177e4SLinus Torvalds 
14541da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
14551da177e4SLinus Torvalds 			hci_conn_del(sco);
14561da177e4SLinus Torvalds 		}
14575a08ecceSAndrei Emeltchenko 	}
14581da177e4SLinus Torvalds 
14591da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14601da177e4SLinus Torvalds }
14611da177e4SLinus Torvalds 
1462f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1463f8558555SMarcel Holtmann {
1464f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1465f8558555SMarcel Holtmann 	struct hci_conn *conn;
1466f8558555SMarcel Holtmann 
14679f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1468f8558555SMarcel Holtmann 
1469f8558555SMarcel Holtmann 	if (!status)
1470f8558555SMarcel Holtmann 		return;
1471f8558555SMarcel Holtmann 
1472f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1473f8558555SMarcel Holtmann 	if (!cp)
1474f8558555SMarcel Holtmann 		return;
1475f8558555SMarcel Holtmann 
1476f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1477f8558555SMarcel Holtmann 
1478f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1479f8558555SMarcel Holtmann 	if (conn) {
1480f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1481f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
148276a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1483f8558555SMarcel Holtmann 		}
1484f8558555SMarcel Holtmann 	}
1485f8558555SMarcel Holtmann 
1486f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1487f8558555SMarcel Holtmann }
1488f8558555SMarcel Holtmann 
1489f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1490f8558555SMarcel Holtmann {
1491f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1492f8558555SMarcel Holtmann 	struct hci_conn *conn;
1493f8558555SMarcel Holtmann 
14949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1495f8558555SMarcel Holtmann 
1496f8558555SMarcel Holtmann 	if (!status)
1497f8558555SMarcel Holtmann 		return;
1498f8558555SMarcel Holtmann 
1499f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1500f8558555SMarcel Holtmann 	if (!cp)
1501f8558555SMarcel Holtmann 		return;
1502f8558555SMarcel Holtmann 
1503f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1504f8558555SMarcel Holtmann 
1505f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1506f8558555SMarcel Holtmann 	if (conn) {
1507f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1508f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
150976a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1510f8558555SMarcel Holtmann 		}
1511f8558555SMarcel Holtmann 	}
1512f8558555SMarcel Holtmann 
1513f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1514f8558555SMarcel Holtmann }
1515f8558555SMarcel Holtmann 
1516127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1517392599b9SJohan Hedberg 				    struct hci_conn *conn)
1518392599b9SJohan Hedberg {
1519392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1520392599b9SJohan Hedberg 		return 0;
1521392599b9SJohan Hedberg 
1522765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1523392599b9SJohan Hedberg 		return 0;
1524392599b9SJohan Hedberg 
1525392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1526264b8b4eSJohan Hedberg 	 * devices with sec_level MEDIUM or HIGH or if MITM protection
1527264b8b4eSJohan Hedberg 	 * is requested.
1528264b8b4eSJohan Hedberg 	 */
1529807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
15307e3691e1SJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_FIPS &&
1531264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
1532264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
1533392599b9SJohan Hedberg 		return 0;
1534392599b9SJohan Hedberg 
1535392599b9SJohan Hedberg 	return 1;
1536392599b9SJohan Hedberg }
1537392599b9SJohan Hedberg 
15386039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
153900abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
154030dc78e1SJohan Hedberg {
154130dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
154230dc78e1SJohan Hedberg 
154330dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
154430dc78e1SJohan Hedberg 
154530dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
154630dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
154730dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
154830dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
154930dc78e1SJohan Hedberg 
155030dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
155130dc78e1SJohan Hedberg }
155230dc78e1SJohan Hedberg 
1553b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
155430dc78e1SJohan Hedberg {
155530dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
155630dc78e1SJohan Hedberg 	struct inquiry_entry *e;
155730dc78e1SJohan Hedberg 
1558b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1559b644ba33SJohan Hedberg 		return false;
1560b644ba33SJohan Hedberg 
1561b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1562c810089cSRam Malovany 	if (!e)
1563c810089cSRam Malovany 		return false;
1564c810089cSRam Malovany 
1565b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1566b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1567b644ba33SJohan Hedberg 		return true;
1568b644ba33SJohan Hedberg 	}
1569b644ba33SJohan Hedberg 
1570b644ba33SJohan Hedberg 	return false;
1571b644ba33SJohan Hedberg }
1572b644ba33SJohan Hedberg 
1573b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1574b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1575b644ba33SJohan Hedberg {
1576b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1577b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1578b644ba33SJohan Hedberg 
1579b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
158004124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
158104124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1582b644ba33SJohan Hedberg 
1583b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1584b644ba33SJohan Hedberg 		return;
1585b644ba33SJohan Hedberg 
158630dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
158730dc78e1SJohan Hedberg 		goto discov_complete;
158830dc78e1SJohan Hedberg 
158930dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
159030dc78e1SJohan Hedberg 		return;
159130dc78e1SJohan Hedberg 
159230dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
15937cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
15947cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
15957cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
15967cc8380eSRam Malovany 	 * Event */
15977cc8380eSRam Malovany 	if (!e)
15987cc8380eSRam Malovany 		return;
15997cc8380eSRam Malovany 
160030dc78e1SJohan Hedberg 	list_del(&e->list);
16017cc8380eSRam Malovany 	if (name) {
16027cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1603b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1604b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1605c3e7c0d9SRam Malovany 	} else {
1606c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
160730dc78e1SJohan Hedberg 	}
160830dc78e1SJohan Hedberg 
1609b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
161030dc78e1SJohan Hedberg 		return;
161130dc78e1SJohan Hedberg 
161230dc78e1SJohan Hedberg discov_complete:
161330dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
161430dc78e1SJohan Hedberg }
161530dc78e1SJohan Hedberg 
1616a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
16171da177e4SLinus Torvalds {
1618127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1619127178d2SJohan Hedberg 	struct hci_conn *conn;
1620127178d2SJohan Hedberg 
16219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1622127178d2SJohan Hedberg 
1623127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1624127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1625127178d2SJohan Hedberg 	if (!status)
1626127178d2SJohan Hedberg 		return;
1627127178d2SJohan Hedberg 
1628127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1629127178d2SJohan Hedberg 	if (!cp)
1630127178d2SJohan Hedberg 		return;
1631127178d2SJohan Hedberg 
1632127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1633127178d2SJohan Hedberg 
1634127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1635b644ba33SJohan Hedberg 
1636b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1637b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1638b644ba33SJohan Hedberg 
163979c6c70cSJohan Hedberg 	if (!conn)
164079c6c70cSJohan Hedberg 		goto unlock;
164179c6c70cSJohan Hedberg 
164279c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
164379c6c70cSJohan Hedberg 		goto unlock;
164479c6c70cSJohan Hedberg 
164551a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1646c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
1647c1f23a2bSJohannes Berg 
1648977f8fceSJohan Hedberg 		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
1649977f8fceSJohan Hedberg 
1650c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
1651c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1652c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
1653127178d2SJohan Hedberg 	}
1654127178d2SJohan Hedberg 
165579c6c70cSJohan Hedberg unlock:
1656127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1657a9de9248SMarcel Holtmann }
16581da177e4SLinus Torvalds 
1659769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1660769be974SMarcel Holtmann {
1661769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1662769be974SMarcel Holtmann 	struct hci_conn *conn;
1663769be974SMarcel Holtmann 
16649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1665769be974SMarcel Holtmann 
1666769be974SMarcel Holtmann 	if (!status)
1667769be974SMarcel Holtmann 		return;
1668769be974SMarcel Holtmann 
1669769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1670769be974SMarcel Holtmann 	if (!cp)
1671769be974SMarcel Holtmann 		return;
1672769be974SMarcel Holtmann 
1673769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1674769be974SMarcel Holtmann 
1675769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1676769be974SMarcel Holtmann 	if (conn) {
1677769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1678769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
167976a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1680769be974SMarcel Holtmann 		}
1681769be974SMarcel Holtmann 	}
1682769be974SMarcel Holtmann 
1683769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1684769be974SMarcel Holtmann }
1685769be974SMarcel Holtmann 
1686769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1687769be974SMarcel Holtmann {
1688769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1689769be974SMarcel Holtmann 	struct hci_conn *conn;
1690769be974SMarcel Holtmann 
16919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1692769be974SMarcel Holtmann 
1693769be974SMarcel Holtmann 	if (!status)
1694769be974SMarcel Holtmann 		return;
1695769be974SMarcel Holtmann 
1696769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1697769be974SMarcel Holtmann 	if (!cp)
1698769be974SMarcel Holtmann 		return;
1699769be974SMarcel Holtmann 
1700769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1701769be974SMarcel Holtmann 
1702769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1703769be974SMarcel Holtmann 	if (conn) {
1704769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1705769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
170676a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1707769be974SMarcel Holtmann 		}
1708769be974SMarcel Holtmann 	}
1709769be974SMarcel Holtmann 
1710769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1711769be974SMarcel Holtmann }
1712769be974SMarcel Holtmann 
1713a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1714a9de9248SMarcel Holtmann {
1715b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1716b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1717b6a0dc82SMarcel Holtmann 	__u16 handle;
1718b6a0dc82SMarcel Holtmann 
17199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1720b6a0dc82SMarcel Holtmann 
1721b6a0dc82SMarcel Holtmann 	if (!status)
1722b6a0dc82SMarcel Holtmann 		return;
1723b6a0dc82SMarcel Holtmann 
1724b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1725b6a0dc82SMarcel Holtmann 	if (!cp)
1726b6a0dc82SMarcel Holtmann 		return;
1727b6a0dc82SMarcel Holtmann 
1728b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1729b6a0dc82SMarcel Holtmann 
17309f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1731b6a0dc82SMarcel Holtmann 
1732b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1733b6a0dc82SMarcel Holtmann 
1734b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
17355a08ecceSAndrei Emeltchenko 	if (acl) {
17365a08ecceSAndrei Emeltchenko 		sco = acl->link;
17375a08ecceSAndrei Emeltchenko 		if (sco) {
1738b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1739b6a0dc82SMarcel Holtmann 
1740b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1741b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1742b6a0dc82SMarcel Holtmann 		}
17435a08ecceSAndrei Emeltchenko 	}
1744b6a0dc82SMarcel Holtmann 
1745b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1746a9de9248SMarcel Holtmann }
1747a9de9248SMarcel Holtmann 
1748a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1749a9de9248SMarcel Holtmann {
1750a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
175104837f64SMarcel Holtmann 	struct hci_conn *conn;
175204837f64SMarcel Holtmann 
17539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1754a9de9248SMarcel Holtmann 
1755a9de9248SMarcel Holtmann 	if (!status)
1756a9de9248SMarcel Holtmann 		return;
1757a9de9248SMarcel Holtmann 
1758a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
175904837f64SMarcel Holtmann 	if (!cp)
1760a9de9248SMarcel Holtmann 		return;
176104837f64SMarcel Holtmann 
176204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
176304837f64SMarcel Holtmann 
176404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1765e73439d8SMarcel Holtmann 	if (conn) {
176651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
176704837f64SMarcel Holtmann 
176851a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1769e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1770e73439d8SMarcel Holtmann 	}
1771e73439d8SMarcel Holtmann 
177204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
177304837f64SMarcel Holtmann }
177404837f64SMarcel Holtmann 
1775a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1776a9de9248SMarcel Holtmann {
1777a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
177804837f64SMarcel Holtmann 	struct hci_conn *conn;
177904837f64SMarcel Holtmann 
17809f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1781a9de9248SMarcel Holtmann 
1782a9de9248SMarcel Holtmann 	if (!status)
1783a9de9248SMarcel Holtmann 		return;
1784a9de9248SMarcel Holtmann 
1785a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
178604837f64SMarcel Holtmann 	if (!cp)
1787a9de9248SMarcel Holtmann 		return;
178804837f64SMarcel Holtmann 
178904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
179004837f64SMarcel Holtmann 
179104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1792e73439d8SMarcel Holtmann 	if (conn) {
179351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
179404837f64SMarcel Holtmann 
179551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1796e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1797e73439d8SMarcel Holtmann 	}
1798e73439d8SMarcel Holtmann 
179904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
180004837f64SMarcel Holtmann }
180104837f64SMarcel Holtmann 
180288c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
180388c3df13SJohan Hedberg {
180488c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
180588c3df13SJohan Hedberg 	struct hci_conn *conn;
180688c3df13SJohan Hedberg 
180788c3df13SJohan Hedberg 	if (!status)
180888c3df13SJohan Hedberg 		return;
180988c3df13SJohan Hedberg 
181088c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
181188c3df13SJohan Hedberg 	if (!cp)
181288c3df13SJohan Hedberg 		return;
181388c3df13SJohan Hedberg 
181488c3df13SJohan Hedberg 	hci_dev_lock(hdev);
181588c3df13SJohan Hedberg 
181688c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
181788c3df13SJohan Hedberg 	if (conn)
181888c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
181988c3df13SJohan Hedberg 				       conn->dst_type, status);
182088c3df13SJohan Hedberg 
182188c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
182288c3df13SJohan Hedberg }
182388c3df13SJohan Hedberg 
1824a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1825a02226d6SAndrei Emeltchenko {
182693c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
182793c284eeSAndrei Emeltchenko 
1828a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
182993c284eeSAndrei Emeltchenko 
183093c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
183193c284eeSAndrei Emeltchenko 	if (!cp)
183293c284eeSAndrei Emeltchenko 		return;
183393c284eeSAndrei Emeltchenko 
1834e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1835e58917b9SAndrei Emeltchenko 
1836e58917b9SAndrei Emeltchenko 	if (status) {
1837e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1838e58917b9SAndrei Emeltchenko 
1839e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1840e58917b9SAndrei Emeltchenko 		if (hcon)
1841e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1842e58917b9SAndrei Emeltchenko 	} else {
184393c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1844a02226d6SAndrei Emeltchenko 	}
1845a02226d6SAndrei Emeltchenko 
1846e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1847e58917b9SAndrei Emeltchenko }
1848e58917b9SAndrei Emeltchenko 
18490b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
18500b26ab9dSAndrei Emeltchenko {
18510b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
18520b26ab9dSAndrei Emeltchenko 
18530b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18540b26ab9dSAndrei Emeltchenko 
18550b26ab9dSAndrei Emeltchenko 	if (status)
18560b26ab9dSAndrei Emeltchenko 		return;
18570b26ab9dSAndrei Emeltchenko 
18580b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
18590b26ab9dSAndrei Emeltchenko 	if (!cp)
18600b26ab9dSAndrei Emeltchenko 		return;
18610b26ab9dSAndrei Emeltchenko 
18620b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
18630b26ab9dSAndrei Emeltchenko }
18640b26ab9dSAndrei Emeltchenko 
1865cb1d68f7SJohan Hedberg static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
1866cb1d68f7SJohan Hedberg {
1867cb1d68f7SJohan Hedberg 	struct hci_cp_le_create_conn *cp;
1868cb1d68f7SJohan Hedberg 	struct hci_conn *conn;
1869cb1d68f7SJohan Hedberg 
1870cb1d68f7SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1871cb1d68f7SJohan Hedberg 
1872cb1d68f7SJohan Hedberg 	/* All connection failure handling is taken care of by the
1873cb1d68f7SJohan Hedberg 	 * hci_le_conn_failed function which is triggered by the HCI
1874cb1d68f7SJohan Hedberg 	 * request completion callbacks used for connecting.
1875cb1d68f7SJohan Hedberg 	 */
1876cb1d68f7SJohan Hedberg 	if (status)
1877cb1d68f7SJohan Hedberg 		return;
1878cb1d68f7SJohan Hedberg 
1879cb1d68f7SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1880cb1d68f7SJohan Hedberg 	if (!cp)
1881cb1d68f7SJohan Hedberg 		return;
1882cb1d68f7SJohan Hedberg 
1883cb1d68f7SJohan Hedberg 	hci_dev_lock(hdev);
1884cb1d68f7SJohan Hedberg 
1885cb1d68f7SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1886cb1d68f7SJohan Hedberg 	if (!conn)
1887cb1d68f7SJohan Hedberg 		goto unlock;
1888cb1d68f7SJohan Hedberg 
1889cb1d68f7SJohan Hedberg 	/* Store the initiator and responder address information which
1890cb1d68f7SJohan Hedberg 	 * is needed for SMP. These values will not change during the
1891cb1d68f7SJohan Hedberg 	 * lifetime of the connection.
1892cb1d68f7SJohan Hedberg 	 */
1893cb1d68f7SJohan Hedberg 	conn->init_addr_type = cp->own_address_type;
1894cb1d68f7SJohan Hedberg 	if (cp->own_address_type == ADDR_LE_DEV_RANDOM)
1895cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &hdev->random_addr);
1896cb1d68f7SJohan Hedberg 	else
1897cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &hdev->bdaddr);
1898cb1d68f7SJohan Hedberg 
1899cb1d68f7SJohan Hedberg 	conn->resp_addr_type = cp->peer_addr_type;
1900cb1d68f7SJohan Hedberg 	bacpy(&conn->resp_addr, &cp->peer_addr);
1901cb1d68f7SJohan Hedberg 
19029489eca4SJohan Hedberg 	/* We don't want the connection attempt to stick around
19039489eca4SJohan Hedberg 	 * indefinitely since LE doesn't have a page timeout concept
19049489eca4SJohan Hedberg 	 * like BR/EDR. Set a timer for any connection that doesn't use
19059489eca4SJohan Hedberg 	 * the white list for connecting.
19069489eca4SJohan Hedberg 	 */
19079489eca4SJohan Hedberg 	if (cp->filter_policy == HCI_LE_USE_PEER_ADDR)
19089489eca4SJohan Hedberg 		queue_delayed_work(conn->hdev->workqueue,
19099489eca4SJohan Hedberg 				   &conn->le_conn_timeout,
191009ae260bSJohan Hedberg 				   conn->conn_timeout);
19119489eca4SJohan Hedberg 
1912cb1d68f7SJohan Hedberg unlock:
1913cb1d68f7SJohan Hedberg 	hci_dev_unlock(hdev);
1914cb1d68f7SJohan Hedberg }
1915cb1d68f7SJohan Hedberg 
191681d0c8adSJohan Hedberg static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
191781d0c8adSJohan Hedberg {
191881d0c8adSJohan Hedberg 	struct hci_cp_le_start_enc *cp;
191981d0c8adSJohan Hedberg 	struct hci_conn *conn;
192081d0c8adSJohan Hedberg 
192181d0c8adSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
192281d0c8adSJohan Hedberg 
192381d0c8adSJohan Hedberg 	if (!status)
192481d0c8adSJohan Hedberg 		return;
192581d0c8adSJohan Hedberg 
192681d0c8adSJohan Hedberg 	hci_dev_lock(hdev);
192781d0c8adSJohan Hedberg 
192881d0c8adSJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC);
192981d0c8adSJohan Hedberg 	if (!cp)
193081d0c8adSJohan Hedberg 		goto unlock;
193181d0c8adSJohan Hedberg 
193281d0c8adSJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
193381d0c8adSJohan Hedberg 	if (!conn)
193481d0c8adSJohan Hedberg 		goto unlock;
193581d0c8adSJohan Hedberg 
193681d0c8adSJohan Hedberg 	if (conn->state != BT_CONNECTED)
193781d0c8adSJohan Hedberg 		goto unlock;
193881d0c8adSJohan Hedberg 
193981d0c8adSJohan Hedberg 	hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
194081d0c8adSJohan Hedberg 	hci_conn_drop(conn);
194181d0c8adSJohan Hedberg 
194281d0c8adSJohan Hedberg unlock:
194381d0c8adSJohan Hedberg 	hci_dev_unlock(hdev);
194481d0c8adSJohan Hedberg }
194581d0c8adSJohan Hedberg 
19466039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19471da177e4SLinus Torvalds {
19481da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
194930dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
195030dc78e1SJohan Hedberg 	struct inquiry_entry *e;
19511da177e4SLinus Torvalds 
19529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
19531da177e4SLinus Torvalds 
1954a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
195589352e7dSAndre Guedes 
195689352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
195789352e7dSAndre Guedes 		return;
195889352e7dSAndre Guedes 
19594e857c58SPeter Zijlstra 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
19603e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
19613e13fa1eSAndre Guedes 
1962a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
196330dc78e1SJohan Hedberg 		return;
196430dc78e1SJohan Hedberg 
196556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
196630dc78e1SJohan Hedberg 
1967343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
196830dc78e1SJohan Hedberg 		goto unlock;
196930dc78e1SJohan Hedberg 
197030dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1971ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
197230dc78e1SJohan Hedberg 		goto unlock;
197330dc78e1SJohan Hedberg 	}
197430dc78e1SJohan Hedberg 
197530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
197630dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
197730dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
197830dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
197930dc78e1SJohan Hedberg 	} else {
198030dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
198130dc78e1SJohan Hedberg 	}
198230dc78e1SJohan Hedberg 
198330dc78e1SJohan Hedberg unlock:
198456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
19851da177e4SLinus Torvalds }
19861da177e4SLinus Torvalds 
19876039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
19881da177e4SLinus Torvalds {
198945bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1990a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
19911da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
19921da177e4SLinus Torvalds 
19931da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
19941da177e4SLinus Torvalds 
199545bb4bf0SMarcel Holtmann 	if (!num_rsp)
199645bb4bf0SMarcel Holtmann 		return;
199745bb4bf0SMarcel Holtmann 
19981519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
19991519cc17SAndre Guedes 		return;
20001519cc17SAndre Guedes 
20011da177e4SLinus Torvalds 	hci_dev_lock(hdev);
200245bb4bf0SMarcel Holtmann 
2003e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2004af58925cSMarcel Holtmann 		u32 flags;
20053175405bSJohan Hedberg 
20061da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
20071da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
20081da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
20091da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
20101da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
20111da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
20121da177e4SLinus Torvalds 		data.rssi		= 0x00;
201341a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
20143175405bSJohan Hedberg 
2015af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, false);
2016af58925cSMarcel Holtmann 
201748264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2018af58925cSMarcel Holtmann 				  info->dev_class, 0, flags, NULL, 0, NULL, 0);
20191da177e4SLinus Torvalds 	}
202045bb4bf0SMarcel Holtmann 
20211da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
20221da177e4SLinus Torvalds }
20231da177e4SLinus Torvalds 
20246039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
20251da177e4SLinus Torvalds {
2026a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
2027a9de9248SMarcel Holtmann 	struct hci_conn *conn;
20281da177e4SLinus Torvalds 
2029a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
203045bb4bf0SMarcel Holtmann 
20311da177e4SLinus Torvalds 	hci_dev_lock(hdev);
203245bb4bf0SMarcel Holtmann 
2033a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
20349499237aSMarcel Holtmann 	if (!conn) {
20359499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
20369499237aSMarcel Holtmann 			goto unlock;
20379499237aSMarcel Holtmann 
20389499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2039a9de9248SMarcel Holtmann 		if (!conn)
2040a9de9248SMarcel Holtmann 			goto unlock;
204145bb4bf0SMarcel Holtmann 
20429499237aSMarcel Holtmann 		conn->type = SCO_LINK;
20439499237aSMarcel Holtmann 	}
20449499237aSMarcel Holtmann 
2045a9de9248SMarcel Holtmann 	if (!ev->status) {
2046a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2047769be974SMarcel Holtmann 
2048769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2049769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
2050769be974SMarcel Holtmann 			hci_conn_hold(conn);
2051a9ea3ed9SSzymon Janc 
2052a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
2053a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
2054a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2055a9ea3ed9SSzymon Janc 			else
2056052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2057769be974SMarcel Holtmann 		} else
2058a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
2059a9de9248SMarcel Holtmann 
20607d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
20617d0db0a3SMarcel Holtmann 
2062a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
20634dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2064a9de9248SMarcel Holtmann 
2065a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
20664dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2067a9de9248SMarcel Holtmann 
2068a9de9248SMarcel Holtmann 		/* Get remote features */
2069a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
2070a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
2071a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2072769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
2073769be974SMarcel Holtmann 				     sizeof(cp), &cp);
207445bb4bf0SMarcel Holtmann 		}
2075a9de9248SMarcel Holtmann 
2076a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
2077d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
2078a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
2079a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
2080a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
208104124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
208204124681SGustavo F. Padovan 				     &cp);
2083a9de9248SMarcel Holtmann 		}
208417d5c04cSJohan Hedberg 	} else {
2085a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
208617d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
208764c7b77cSMarcel Holtmann 			mgmt_connect_failed(hdev, &conn->dst, conn->type,
208848264f06SJohan Hedberg 					    conn->dst_type, ev->status);
208917d5c04cSJohan Hedberg 	}
209045bb4bf0SMarcel Holtmann 
2091e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
2092e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
209345bb4bf0SMarcel Holtmann 
2094769be974SMarcel Holtmann 	if (ev->status) {
2095a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2096a9de9248SMarcel Holtmann 		hci_conn_del(conn);
2097c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
2098c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2099a9de9248SMarcel Holtmann 
2100a9de9248SMarcel Holtmann unlock:
21011da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
2102a9de9248SMarcel Holtmann 
2103a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
21041da177e4SLinus Torvalds }
21051da177e4SLinus Torvalds 
210670c46425SJohan Hedberg static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr)
210770c46425SJohan Hedberg {
210870c46425SJohan Hedberg 	struct hci_cp_reject_conn_req cp;
210970c46425SJohan Hedberg 
211070c46425SJohan Hedberg 	bacpy(&cp.bdaddr, bdaddr);
211170c46425SJohan Hedberg 	cp.reason = HCI_ERROR_REJ_BAD_ADDR;
211270c46425SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
211370c46425SJohan Hedberg }
211470c46425SJohan Hedberg 
21156039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
21161da177e4SLinus Torvalds {
2117a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
21181da177e4SLinus Torvalds 	int mask = hdev->link_mode;
211970c46425SJohan Hedberg 	struct inquiry_entry *ie;
212070c46425SJohan Hedberg 	struct hci_conn *conn;
212120714bfeSFrédéric Dalleau 	__u8 flags = 0;
21221da177e4SLinus Torvalds 
21236ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
2124807deac2SGustavo Padovan 	       ev->link_type);
21251da177e4SLinus Torvalds 
212620714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
212720714bfeSFrédéric Dalleau 				      &flags);
21281da177e4SLinus Torvalds 
212970c46425SJohan Hedberg 	if (!(mask & HCI_LM_ACCEPT)) {
213070c46425SJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
213170c46425SJohan Hedberg 		return;
213270c46425SJohan Hedberg 	}
213370c46425SJohan Hedberg 
2134a55bd29dSJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr,
2135dcc36c16SJohan Hedberg 				   BDADDR_BREDR)) {
213670c46425SJohan Hedberg 		hci_reject_conn(hdev, &ev->bdaddr);
213770c46425SJohan Hedberg 		return;
213870c46425SJohan Hedberg 	}
213946c4c941SJohan Hedberg 
214046c4c941SJohan Hedberg 	if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) &&
214146c4c941SJohan Hedberg 	    !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr,
2142a55bd29dSJohan Hedberg 				    BDADDR_BREDR)) {
2143a55bd29dSJohan Hedberg 		    hci_reject_conn(hdev, &ev->bdaddr);
2144a55bd29dSJohan Hedberg 		    return;
2145a55bd29dSJohan Hedberg 	}
214670c46425SJohan Hedberg 
21471da177e4SLinus Torvalds 	/* Connection accepted */
21481da177e4SLinus Torvalds 
21491da177e4SLinus Torvalds 	hci_dev_lock(hdev);
2150b6a0dc82SMarcel Holtmann 
2151cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2152cc11b9c1SAndrei Emeltchenko 	if (ie)
2153c7bdd502SMarcel Holtmann 		memcpy(ie->data.dev_class, ev->dev_class, 3);
2154c7bdd502SMarcel Holtmann 
21558fc9ced3SGustavo Padovan 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
21568fc9ced3SGustavo Padovan 			&ev->bdaddr);
21571da177e4SLinus Torvalds 	if (!conn) {
2158a5c4e309SJohan Hedberg 		conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
2159a5c4e309SJohan Hedberg 				    HCI_ROLE_SLAVE);
2160cc11b9c1SAndrei Emeltchenko 		if (!conn) {
2161893ef971SGustavo F. Padovan 			BT_ERR("No memory for new connection");
21621da177e4SLinus Torvalds 			hci_dev_unlock(hdev);
21631da177e4SLinus Torvalds 			return;
21641da177e4SLinus Torvalds 		}
21651da177e4SLinus Torvalds 	}
2166b6a0dc82SMarcel Holtmann 
21671da177e4SLinus Torvalds 	memcpy(conn->dev_class, ev->dev_class, 3);
2168b6a0dc82SMarcel Holtmann 
21691da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
21701da177e4SLinus Torvalds 
217120714bfeSFrédéric Dalleau 	if (ev->link_type == ACL_LINK ||
217220714bfeSFrédéric Dalleau 	    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
2173b6a0dc82SMarcel Holtmann 		struct hci_cp_accept_conn_req cp;
217420714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT;
2175b6a0dc82SMarcel Holtmann 
21761da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
21771da177e4SLinus Torvalds 
21781da177e4SLinus Torvalds 		if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
21791da177e4SLinus Torvalds 			cp.role = 0x00; /* Become master */
21801da177e4SLinus Torvalds 		else
21811da177e4SLinus Torvalds 			cp.role = 0x01; /* Remain slave */
21821da177e4SLinus Torvalds 
218370c46425SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
218420714bfeSFrédéric Dalleau 	} else if (!(flags & HCI_PROTO_DEFER)) {
2185b6a0dc82SMarcel Holtmann 		struct hci_cp_accept_sync_conn_req cp;
218620714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT;
2187b6a0dc82SMarcel Holtmann 
2188b6a0dc82SMarcel Holtmann 		bacpy(&cp.bdaddr, &ev->bdaddr);
2189a8746417SMarcel Holtmann 		cp.pkt_type = cpu_to_le16(conn->pkt_type);
2190b6a0dc82SMarcel Holtmann 
2191dcf4adbfSJoe Perches 		cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
2192dcf4adbfSJoe Perches 		cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
2193dcf4adbfSJoe Perches 		cp.max_latency    = cpu_to_le16(0xffff);
2194b6a0dc82SMarcel Holtmann 		cp.content_format = cpu_to_le16(hdev->voice_setting);
2195b6a0dc82SMarcel Holtmann 		cp.retrans_effort = 0xff;
2196b6a0dc82SMarcel Holtmann 
219770c46425SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(cp),
219870c46425SJohan Hedberg 			     &cp);
219920714bfeSFrédéric Dalleau 	} else {
220020714bfeSFrédéric Dalleau 		conn->state = BT_CONNECT2;
220120714bfeSFrédéric Dalleau 		hci_proto_connect_cfm(conn, 0);
2202b6a0dc82SMarcel Holtmann 	}
22031da177e4SLinus Torvalds }
22041da177e4SLinus Torvalds 
2205f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2206f0d6a0eaSMikel Astiz {
2207f0d6a0eaSMikel Astiz 	switch (err) {
2208f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2209f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2210f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2211f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2212f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2213f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2214f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2215f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2216f0d6a0eaSMikel Astiz 	default:
2217f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2218f0d6a0eaSMikel Astiz 	}
2219f0d6a0eaSMikel Astiz }
2220f0d6a0eaSMikel Astiz 
22216039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
22221da177e4SLinus Torvalds {
2223a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
2224abf54a50SAndre Guedes 	u8 reason = hci_to_mgmt_reason(ev->reason);
22259fcb18efSAndre Guedes 	struct hci_conn_params *params;
222604837f64SMarcel Holtmann 	struct hci_conn *conn;
222712d4a3b2SJohan Hedberg 	bool mgmt_connected;
22283846220bSAndre Guedes 	u8 type;
22291da177e4SLinus Torvalds 
22309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
22311da177e4SLinus Torvalds 
22321da177e4SLinus Torvalds 	hci_dev_lock(hdev);
22331da177e4SLinus Torvalds 
223404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2235f7520543SJohan Hedberg 	if (!conn)
2236f7520543SJohan Hedberg 		goto unlock;
2237f7520543SJohan Hedberg 
2238f0d6a0eaSMikel Astiz 	if (ev->status) {
223988c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
224088c3df13SJohan Hedberg 				       conn->dst_type, ev->status);
2241abf54a50SAndre Guedes 		goto unlock;
2242abf54a50SAndre Guedes 	}
2243f0d6a0eaSMikel Astiz 
22443846220bSAndre Guedes 	conn->state = BT_CLOSED;
22453846220bSAndre Guedes 
224612d4a3b2SJohan Hedberg 	mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
224712d4a3b2SJohan Hedberg 	mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
224812d4a3b2SJohan Hedberg 				reason, mgmt_connected);
2249f7520543SJohan Hedberg 
2250af6a9c32SJohan Hedberg 	if (conn->type == ACL_LINK &&
2251af6a9c32SJohan Hedberg 	    test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
22526ec5bcadSVishal Agarwal 		hci_remove_link_key(hdev, &conn->dst);
22533846220bSAndre Guedes 
22549fcb18efSAndre Guedes 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
22559fcb18efSAndre Guedes 	if (params) {
22569fcb18efSAndre Guedes 		switch (params->auto_connect) {
22579fcb18efSAndre Guedes 		case HCI_AUTO_CONN_LINK_LOSS:
22589fcb18efSAndre Guedes 			if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
22599fcb18efSAndre Guedes 				break;
22609fcb18efSAndre Guedes 			/* Fall through */
22619fcb18efSAndre Guedes 
22624b9e7e75SMarcel Holtmann 		case HCI_AUTO_CONN_DIRECT:
22639fcb18efSAndre Guedes 		case HCI_AUTO_CONN_ALWAYS:
2264418025d1SJohan Hedberg 			list_del_init(&params->action);
2265418025d1SJohan Hedberg 			list_add(&params->action, &hdev->pend_le_conns);
2266418025d1SJohan Hedberg 			hci_update_background_scan(hdev);
22679fcb18efSAndre Guedes 			break;
22689fcb18efSAndre Guedes 
22699fcb18efSAndre Guedes 		default:
22709fcb18efSAndre Guedes 			break;
22719fcb18efSAndre Guedes 		}
22729fcb18efSAndre Guedes 	}
22739fcb18efSAndre Guedes 
22743846220bSAndre Guedes 	type = conn->type;
22753846220bSAndre Guedes 
22762950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
22771da177e4SLinus Torvalds 	hci_conn_del(conn);
22782210246cSJohan Hedberg 
22792210246cSJohan Hedberg 	/* Re-enable advertising if necessary, since it might
22802210246cSJohan Hedberg 	 * have been disabled by the connection. From the
22812210246cSJohan Hedberg 	 * HCI_LE_Set_Advertise_Enable command description in
22822210246cSJohan Hedberg 	 * the core specification (v4.0):
22832210246cSJohan Hedberg 	 * "The Controller shall continue advertising until the Host
22842210246cSJohan Hedberg 	 * issues an LE_Set_Advertise_Enable command with
22852210246cSJohan Hedberg 	 * Advertising_Enable set to 0x00 (Advertising is disabled)
22862210246cSJohan Hedberg 	 * or until a connection is created or until the Advertising
22872210246cSJohan Hedberg 	 * is timed out due to Directed Advertising."
22882210246cSJohan Hedberg 	 */
22892210246cSJohan Hedberg 	if (type == LE_LINK)
22905976e608SMarcel Holtmann 		mgmt_reenable_advertising(hdev);
22911da177e4SLinus Torvalds 
2292f7520543SJohan Hedberg unlock:
22931da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
22941da177e4SLinus Torvalds }
22951da177e4SLinus Torvalds 
22966039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2297a9de9248SMarcel Holtmann {
2298a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2299a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2300a9de9248SMarcel Holtmann 
23019f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2302a9de9248SMarcel Holtmann 
2303a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2304a9de9248SMarcel Holtmann 
2305a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2306d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2307d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2308d7556e20SWaldemar Rymarkiewicz 
2309765c2a96SJohan Hedberg 	if (!ev->status) {
2310aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
231151a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2312d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
231319f8def0SWaldemar Rymarkiewicz 		} else {
23144dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
2315765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
231619f8def0SWaldemar Rymarkiewicz 		}
23172a611692SJohan Hedberg 	} else {
2318bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
2319bab73cb6SJohan Hedberg 				 ev->status);
23202a611692SJohan Hedberg 	}
2321a9de9248SMarcel Holtmann 
232251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
232351a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2324a9de9248SMarcel Holtmann 
2325f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2326aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2327f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2328f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2329f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2330d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2331d7556e20SWaldemar Rymarkiewicz 				     &cp);
2332f8558555SMarcel Holtmann 		} else {
2333f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2334f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
233576a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2336f8558555SMarcel Holtmann 		}
2337052b30b0SMarcel Holtmann 	} else {
2338a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2339a9de9248SMarcel Holtmann 
2340052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2341052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
234276a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2343052b30b0SMarcel Holtmann 	}
2344052b30b0SMarcel Holtmann 
234551a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2346a9de9248SMarcel Holtmann 		if (!ev->status) {
2347a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2348f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2349f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2350d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2351d7556e20SWaldemar Rymarkiewicz 				     &cp);
2352a9de9248SMarcel Holtmann 		} else {
235351a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2354a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2355a9de9248SMarcel Holtmann 		}
2356a9de9248SMarcel Holtmann 	}
2357a9de9248SMarcel Holtmann 
2358d7556e20SWaldemar Rymarkiewicz unlock:
2359a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2360a9de9248SMarcel Holtmann }
2361a9de9248SMarcel Holtmann 
23626039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2363a9de9248SMarcel Holtmann {
2364127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2365127178d2SJohan Hedberg 	struct hci_conn *conn;
2366127178d2SJohan Hedberg 
2367a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2368a9de9248SMarcel Holtmann 
2369a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2370127178d2SJohan Hedberg 
2371127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2372127178d2SJohan Hedberg 
2373127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2374b644ba33SJohan Hedberg 
2375b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2376b644ba33SJohan Hedberg 		goto check_auth;
2377b644ba33SJohan Hedberg 
2378b644ba33SJohan Hedberg 	if (ev->status == 0)
2379b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2380b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2381b644ba33SJohan Hedberg 	else
2382b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2383b644ba33SJohan Hedberg 
2384b644ba33SJohan Hedberg check_auth:
238579c6c70cSJohan Hedberg 	if (!conn)
238679c6c70cSJohan Hedberg 		goto unlock;
238779c6c70cSJohan Hedberg 
238879c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
238979c6c70cSJohan Hedberg 		goto unlock;
239079c6c70cSJohan Hedberg 
239151a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2392127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2393977f8fceSJohan Hedberg 
2394977f8fceSJohan Hedberg 		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
2395977f8fceSJohan Hedberg 
2396127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2397127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2398127178d2SJohan Hedberg 	}
2399127178d2SJohan Hedberg 
240079c6c70cSJohan Hedberg unlock:
2401127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2402a9de9248SMarcel Holtmann }
2403a9de9248SMarcel Holtmann 
24046039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2405a9de9248SMarcel Holtmann {
2406a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2407a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2408a9de9248SMarcel Holtmann 
24099f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2410a9de9248SMarcel Holtmann 
2411a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2412a9de9248SMarcel Holtmann 
2413a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2414dc8357ccSMarcel Holtmann 	if (!conn)
2415dc8357ccSMarcel Holtmann 		goto unlock;
2416dc8357ccSMarcel Holtmann 
2417a9de9248SMarcel Holtmann 	if (!ev->status) {
2418ae293196SMarcel Holtmann 		if (ev->encrypt) {
2419ae293196SMarcel Holtmann 			/* Encryption implies authentication */
24204dae2798SJohan Hedberg 			set_bit(HCI_CONN_AUTH, &conn->flags);
24214dae2798SJohan Hedberg 			set_bit(HCI_CONN_ENCRYPT, &conn->flags);
2422da85e5e5SVinicius Costa Gomes 			conn->sec_level = conn->pending_sec_level;
2423abf76badSMarcel Holtmann 
2424914a6ffeSMarcel Holtmann 			/* P-256 authentication key implies FIPS */
2425914a6ffeSMarcel Holtmann 			if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
24264dae2798SJohan Hedberg 				set_bit(HCI_CONN_FIPS, &conn->flags);
2427914a6ffeSMarcel Holtmann 
2428abf76badSMarcel Holtmann 			if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
2429abf76badSMarcel Holtmann 			    conn->type == LE_LINK)
2430abf76badSMarcel Holtmann 				set_bit(HCI_CONN_AES_CCM, &conn->flags);
2431abf76badSMarcel Holtmann 		} else {
24324dae2798SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
2433abf76badSMarcel Holtmann 			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
2434abf76badSMarcel Holtmann 		}
2435a9de9248SMarcel Holtmann 	}
2436a9de9248SMarcel Holtmann 
243751a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2438a9de9248SMarcel Holtmann 
2439a7d7723aSGustavo Padovan 	if (ev->status && conn->state == BT_CONNECTED) {
2440bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
244176a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2442a7d7723aSGustavo Padovan 		goto unlock;
2443a7d7723aSGustavo Padovan 	}
2444a7d7723aSGustavo Padovan 
2445f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2446f8558555SMarcel Holtmann 		if (!ev->status)
2447f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2448f8558555SMarcel Holtmann 
244940b552aaSMarcel Holtmann 		/* In Secure Connections Only mode, do not allow any
245040b552aaSMarcel Holtmann 		 * connections that are not encrypted with AES-CCM
245140b552aaSMarcel Holtmann 		 * using a P-256 authenticated combination key.
245240b552aaSMarcel Holtmann 		 */
245340b552aaSMarcel Holtmann 		if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) &&
245440b552aaSMarcel Holtmann 		    (!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
245540b552aaSMarcel Holtmann 		     conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) {
245640b552aaSMarcel Holtmann 			hci_proto_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE);
245740b552aaSMarcel Holtmann 			hci_conn_drop(conn);
245840b552aaSMarcel Holtmann 			goto unlock;
245940b552aaSMarcel Holtmann 		}
246040b552aaSMarcel Holtmann 
2461f8558555SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
246276a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2463f8558555SMarcel Holtmann 	} else
2464a9de9248SMarcel Holtmann 		hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2465a9de9248SMarcel Holtmann 
2466a7d7723aSGustavo Padovan unlock:
2467a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2468a9de9248SMarcel Holtmann }
2469a9de9248SMarcel Holtmann 
24706039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2471807deac2SGustavo Padovan 					     struct sk_buff *skb)
2472a9de9248SMarcel Holtmann {
2473a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2474a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2475a9de9248SMarcel Holtmann 
24769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2477a9de9248SMarcel Holtmann 
2478a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2479a9de9248SMarcel Holtmann 
2480a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2481a9de9248SMarcel Holtmann 	if (conn) {
2482a9de9248SMarcel Holtmann 		if (!ev->status)
24834dae2798SJohan Hedberg 			set_bit(HCI_CONN_SECURE, &conn->flags);
2484a9de9248SMarcel Holtmann 
248551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2486a9de9248SMarcel Holtmann 
2487a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2488a9de9248SMarcel Holtmann 	}
2489a9de9248SMarcel Holtmann 
2490a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2491a9de9248SMarcel Holtmann }
2492a9de9248SMarcel Holtmann 
24936039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2494807deac2SGustavo Padovan 				    struct sk_buff *skb)
2495a9de9248SMarcel Holtmann {
2496a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2497a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2498a9de9248SMarcel Holtmann 
24999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2500a9de9248SMarcel Holtmann 
2501a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2502a9de9248SMarcel Holtmann 
2503a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2504ccd556feSJohan Hedberg 	if (!conn)
2505ccd556feSJohan Hedberg 		goto unlock;
2506ccd556feSJohan Hedberg 
2507769be974SMarcel Holtmann 	if (!ev->status)
2508cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
2509a9de9248SMarcel Holtmann 
2510ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2511ccd556feSJohan Hedberg 		goto unlock;
2512ccd556feSJohan Hedberg 
2513ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2514769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2515769be974SMarcel Holtmann 		cp.handle = ev->handle;
2516769be974SMarcel Holtmann 		cp.page = 0x01;
2517ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2518769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2519392599b9SJohan Hedberg 		goto unlock;
2520392599b9SJohan Hedberg 	}
2521392599b9SJohan Hedberg 
2522671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2523127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2524127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2525127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2526127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2527127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2528b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2529b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
253008c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2531b644ba33SJohan Hedberg 				      conn->dev_class);
2532392599b9SJohan Hedberg 
2533127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2534769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2535769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
253676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2537769be974SMarcel Holtmann 	}
2538769be974SMarcel Holtmann 
2539ccd556feSJohan Hedberg unlock:
2540a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2541a9de9248SMarcel Holtmann }
2542a9de9248SMarcel Holtmann 
25436039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2544a9de9248SMarcel Holtmann {
2545a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
25469238f36aSJohan Hedberg 	u8 status = skb->data[sizeof(*ev)];
2547a9de9248SMarcel Holtmann 	__u16 opcode;
2548a9de9248SMarcel Holtmann 
2549a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2550a9de9248SMarcel Holtmann 
2551a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2552a9de9248SMarcel Holtmann 
2553a9de9248SMarcel Holtmann 	switch (opcode) {
2554a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2555a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2556a9de9248SMarcel Holtmann 		break;
2557a9de9248SMarcel Holtmann 
25584d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
25594d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
25604d93483bSAndre Guedes 		break;
25614d93483bSAndre Guedes 
2562a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2563a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2564a9de9248SMarcel Holtmann 		break;
2565a9de9248SMarcel Holtmann 
2566a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2567a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2568a9de9248SMarcel Holtmann 		break;
2569a9de9248SMarcel Holtmann 
2570a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2571a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2572a9de9248SMarcel Holtmann 		break;
2573a9de9248SMarcel Holtmann 
2574e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2575e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2576e4e8e37cSMarcel Holtmann 		break;
2577e4e8e37cSMarcel Holtmann 
2578a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2579a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2580a9de9248SMarcel Holtmann 		break;
2581a9de9248SMarcel Holtmann 
2582e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2583e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2584e4e8e37cSMarcel Holtmann 		break;
2585e4e8e37cSMarcel Holtmann 
2586e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2587e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2588e4e8e37cSMarcel Holtmann 		break;
2589e4e8e37cSMarcel Holtmann 
2590a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2591a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2592a9de9248SMarcel Holtmann 		break;
2593a9de9248SMarcel Holtmann 
2594a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2595a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2596a9de9248SMarcel Holtmann 		break;
2597a9de9248SMarcel Holtmann 
2598a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2599a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2600a9de9248SMarcel Holtmann 		break;
2601a9de9248SMarcel Holtmann 
2602a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2603a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2604a9de9248SMarcel Holtmann 		break;
2605a9de9248SMarcel Holtmann 
2606a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2607a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2608a9de9248SMarcel Holtmann 		break;
2609a9de9248SMarcel Holtmann 
2610a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2611a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2612a9de9248SMarcel Holtmann 		break;
2613a9de9248SMarcel Holtmann 
2614a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2615a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2616a9de9248SMarcel Holtmann 		break;
2617a9de9248SMarcel Holtmann 
2618a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2619a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2620a9de9248SMarcel Holtmann 		break;
2621a9de9248SMarcel Holtmann 
2622a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2623a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2624a9de9248SMarcel Holtmann 		break;
2625a9de9248SMarcel Holtmann 
2626a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2627a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2628a9de9248SMarcel Holtmann 		break;
2629a9de9248SMarcel Holtmann 
2630b4cb9fb2SMarcel Holtmann 	case HCI_OP_READ_NUM_SUPPORTED_IAC:
2631b4cb9fb2SMarcel Holtmann 		hci_cc_read_num_supported_iac(hdev, skb);
2632b4cb9fb2SMarcel Holtmann 		break;
2633b4cb9fb2SMarcel Holtmann 
2634333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2635333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2636333140b5SMarcel Holtmann 		break;
2637333140b5SMarcel Holtmann 
2638eac83dc6SMarcel Holtmann 	case HCI_OP_WRITE_SC_SUPPORT:
2639eac83dc6SMarcel Holtmann 		hci_cc_write_sc_support(hdev, skb);
2640eac83dc6SMarcel Holtmann 		break;
2641eac83dc6SMarcel Holtmann 
2642a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2643a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2644a9de9248SMarcel Holtmann 		break;
2645a9de9248SMarcel Holtmann 
2646a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2647a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2648a9de9248SMarcel Holtmann 		break;
2649a9de9248SMarcel Holtmann 
2650a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2651a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2652a9de9248SMarcel Holtmann 		break;
2653a9de9248SMarcel Holtmann 
2654971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2655971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2656971e3a4bSAndre Guedes 		break;
2657971e3a4bSAndre Guedes 
2658a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2659a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2660a9de9248SMarcel Holtmann 		break;
2661a9de9248SMarcel Holtmann 
2662a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2663a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2664a9de9248SMarcel Holtmann 		break;
2665a9de9248SMarcel Holtmann 
2666f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2667f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
2668f332ec66SJohan Hedberg 		break;
2669f332ec66SJohan Hedberg 
26704a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
26714a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
26724a3ee763SJohan Hedberg 		break;
26734a3ee763SJohan Hedberg 
2674f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
2675f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
2676f332ec66SJohan Hedberg 		break;
2677f332ec66SJohan Hedberg 
26784a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
26794a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
26804a3ee763SJohan Hedberg 		break;
26814a3ee763SJohan Hedberg 
2682350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2683350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2684350ee4cfSAndrei Emeltchenko 		break;
2685350ee4cfSAndrei Emeltchenko 
26861e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
26871e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
26881e89cffbSAndrei Emeltchenko 		break;
26891e89cffbSAndrei Emeltchenko 
2690928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2691928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2692928abaa7SAndrei Emeltchenko 		break;
2693928abaa7SAndrei Emeltchenko 
269433f35721SJohan Hedberg 	case HCI_OP_READ_CLOCK:
269533f35721SJohan Hedberg 		hci_cc_read_clock(hdev, skb);
269633f35721SJohan Hedberg 		break;
269733f35721SJohan Hedberg 
2698903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2699903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2700903e4541SAndrei Emeltchenko 		break;
2701903e4541SAndrei Emeltchenko 
2702d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2703d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2704d5859e22SJohan Hedberg 		break;
2705d5859e22SJohan Hedberg 
2706980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2707980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2708980e1a53SJohan Hedberg 		break;
2709980e1a53SJohan Hedberg 
2710980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2711980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2712980e1a53SJohan Hedberg 		break;
2713980e1a53SJohan Hedberg 
2714c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
27154d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_data(hdev, skb);
27164d2d2796SMarcel Holtmann 		break;
27174d2d2796SMarcel Holtmann 
27184d2d2796SMarcel Holtmann 	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
27194d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_ext_data(hdev, skb);
2720c35938b2SSzymon Janc 		break;
2721c35938b2SSzymon Janc 
27226ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
27236ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
27246ed58ec5SVille Tervo 		break;
27256ed58ec5SVille Tervo 
272660e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
272760e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
272860e77321SJohan Hedberg 		break;
272960e77321SJohan Hedberg 
27308fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
27318fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
27328fa19098SJohan Hedberg 		break;
27338fa19098SJohan Hedberg 
2734a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2735a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2736a5c29683SJohan Hedberg 		break;
2737a5c29683SJohan Hedberg 
2738a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2739a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2740a5c29683SJohan Hedberg 		break;
2741a5c29683SJohan Hedberg 
27421143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
27431143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
27441143d458SBrian Gix 		break;
27451143d458SBrian Gix 
27461143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
27471143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
274816cde993SSzymon Janc 		break;
274907f7fa5dSAndre Guedes 
27507a4cd51dSMarcel Holtmann 	case HCI_OP_LE_SET_RANDOM_ADDR:
27517a4cd51dSMarcel Holtmann 		hci_cc_le_set_random_addr(hdev, skb);
27527a4cd51dSMarcel Holtmann 		break;
27537a4cd51dSMarcel Holtmann 
2754c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2755c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2756c1d5dc4aSJohan Hedberg 		break;
2757c1d5dc4aSJohan Hedberg 
2758533553f8SMarcel Holtmann 	case HCI_OP_LE_SET_SCAN_PARAM:
2759533553f8SMarcel Holtmann 		hci_cc_le_set_scan_param(hdev, skb);
2760533553f8SMarcel Holtmann 		break;
2761533553f8SMarcel Holtmann 
2762eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2763eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2764eb9d91f5SAndre Guedes 		break;
2765eb9d91f5SAndre Guedes 
2766cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2767cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2768cf1d081fSJohan Hedberg 		break;
2769cf1d081fSJohan Hedberg 
27700f36b589SMarcel Holtmann 	case HCI_OP_LE_CLEAR_WHITE_LIST:
27710f36b589SMarcel Holtmann 		hci_cc_le_clear_white_list(hdev, skb);
27720f36b589SMarcel Holtmann 		break;
27730f36b589SMarcel Holtmann 
27740f36b589SMarcel Holtmann 	case HCI_OP_LE_ADD_TO_WHITE_LIST:
27750f36b589SMarcel Holtmann 		hci_cc_le_add_to_white_list(hdev, skb);
27760f36b589SMarcel Holtmann 		break;
27770f36b589SMarcel Holtmann 
27780f36b589SMarcel Holtmann 	case HCI_OP_LE_DEL_FROM_WHITE_LIST:
27790f36b589SMarcel Holtmann 		hci_cc_le_del_from_white_list(hdev, skb);
27800f36b589SMarcel Holtmann 		break;
27810f36b589SMarcel Holtmann 
27829b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
27839b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
27849b008c04SJohan Hedberg 		break;
27859b008c04SJohan Hedberg 
2786f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2787f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2788f9b49306SAndre Guedes 		break;
2789f9b49306SAndre Guedes 
279056ed2cb8SJohan Hedberg 	case HCI_OP_LE_SET_ADV_PARAM:
279156ed2cb8SJohan Hedberg 		hci_cc_set_adv_param(hdev, skb);
279256ed2cb8SJohan Hedberg 		break;
279356ed2cb8SJohan Hedberg 
279493c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
279593c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
279693c284eeSAndrei Emeltchenko 		break;
279793c284eeSAndrei Emeltchenko 
27985ae76a94SAndrzej Kaczmarek 	case HCI_OP_READ_RSSI:
27995ae76a94SAndrzej Kaczmarek 		hci_cc_read_rssi(hdev, skb);
28005ae76a94SAndrzej Kaczmarek 		break;
28015ae76a94SAndrzej Kaczmarek 
28025a134faeSAndrzej Kaczmarek 	case HCI_OP_READ_TX_POWER:
28035a134faeSAndrzej Kaczmarek 		hci_cc_read_tx_power(hdev, skb);
28045a134faeSAndrzej Kaczmarek 		break;
28055a134faeSAndrzej Kaczmarek 
2806a9de9248SMarcel Holtmann 	default:
28079f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2808a9de9248SMarcel Holtmann 		break;
2809a9de9248SMarcel Holtmann 	}
2810a9de9248SMarcel Holtmann 
2811ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
281265cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
28136bd32326SVille Tervo 
2814ad82cdd1SJohan Hedberg 	hci_req_cmd_complete(hdev, opcode, status);
28159238f36aSJohan Hedberg 
2816dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2817a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2818a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2819c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2820a9de9248SMarcel Holtmann 	}
2821a9de9248SMarcel Holtmann }
2822a9de9248SMarcel Holtmann 
28236039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2824a9de9248SMarcel Holtmann {
2825a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2826a9de9248SMarcel Holtmann 	__u16 opcode;
2827a9de9248SMarcel Holtmann 
2828a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2829a9de9248SMarcel Holtmann 
2830a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2831a9de9248SMarcel Holtmann 
2832a9de9248SMarcel Holtmann 	switch (opcode) {
2833a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2834a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2835a9de9248SMarcel Holtmann 		break;
2836a9de9248SMarcel Holtmann 
2837a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2838a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2839a9de9248SMarcel Holtmann 		break;
2840a9de9248SMarcel Holtmann 
2841a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2842a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2843a9de9248SMarcel Holtmann 		break;
2844a9de9248SMarcel Holtmann 
2845f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2846f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2847f8558555SMarcel Holtmann 		break;
2848f8558555SMarcel Holtmann 
2849f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2850f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2851f8558555SMarcel Holtmann 		break;
2852f8558555SMarcel Holtmann 
2853a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2854a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2855a9de9248SMarcel Holtmann 		break;
2856a9de9248SMarcel Holtmann 
2857769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2858769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2859769be974SMarcel Holtmann 		break;
2860769be974SMarcel Holtmann 
2861769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2862769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2863769be974SMarcel Holtmann 		break;
2864769be974SMarcel Holtmann 
2865a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2866a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2867a9de9248SMarcel Holtmann 		break;
2868a9de9248SMarcel Holtmann 
2869a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2870a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2871a9de9248SMarcel Holtmann 		break;
2872a9de9248SMarcel Holtmann 
2873a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2874a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2875a9de9248SMarcel Holtmann 		break;
2876a9de9248SMarcel Holtmann 
28778962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
287888c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
28798962ee74SJohan Hedberg 		break;
28808962ee74SJohan Hedberg 
2881a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2882a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2883a02226d6SAndrei Emeltchenko 		break;
2884a02226d6SAndrei Emeltchenko 
28850b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
28860b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
28870b26ab9dSAndrei Emeltchenko 		break;
28880b26ab9dSAndrei Emeltchenko 
2889cb1d68f7SJohan Hedberg 	case HCI_OP_LE_CREATE_CONN:
2890cb1d68f7SJohan Hedberg 		hci_cs_le_create_conn(hdev, ev->status);
2891cb1d68f7SJohan Hedberg 		break;
2892cb1d68f7SJohan Hedberg 
289381d0c8adSJohan Hedberg 	case HCI_OP_LE_START_ENC:
289481d0c8adSJohan Hedberg 		hci_cs_le_start_enc(hdev, ev->status);
289581d0c8adSJohan Hedberg 		break;
289681d0c8adSJohan Hedberg 
2897a9de9248SMarcel Holtmann 	default:
28989f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2899a9de9248SMarcel Holtmann 		break;
2900a9de9248SMarcel Holtmann 	}
2901a9de9248SMarcel Holtmann 
2902ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
290365cc2b49SMarcel Holtmann 		cancel_delayed_work(&hdev->cmd_timer);
29046bd32326SVille Tervo 
290502350a72SJohan Hedberg 	if (ev->status ||
290602350a72SJohan Hedberg 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
290733720450SAndre Guedes 		hci_req_cmd_complete(hdev, opcode, ev->status);
29089238f36aSJohan Hedberg 
290910572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2910a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2911a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2912c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2913a9de9248SMarcel Holtmann 	}
2914a9de9248SMarcel Holtmann }
2915a9de9248SMarcel Holtmann 
29166039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2917a9de9248SMarcel Holtmann {
2918a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2919a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2920a9de9248SMarcel Holtmann 
29219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2922a9de9248SMarcel Holtmann 
2923a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2924a9de9248SMarcel Holtmann 
2925a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2926a9de9248SMarcel Holtmann 	if (conn) {
292740bef302SJohan Hedberg 		if (!ev->status)
292840bef302SJohan Hedberg 			conn->role = ev->role;
2929a9de9248SMarcel Holtmann 
293051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2931a9de9248SMarcel Holtmann 
2932a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2933a9de9248SMarcel Holtmann 	}
2934a9de9248SMarcel Holtmann 
2935a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2936a9de9248SMarcel Holtmann }
2937a9de9248SMarcel Holtmann 
29386039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
29391da177e4SLinus Torvalds {
2940a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
29411da177e4SLinus Torvalds 	int i;
29421da177e4SLinus Torvalds 
294332ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
294432ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
294532ac5b9bSAndrei Emeltchenko 		return;
294632ac5b9bSAndrei Emeltchenko 	}
294732ac5b9bSAndrei Emeltchenko 
2948c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2949c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
29501da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
29511da177e4SLinus Torvalds 		return;
29521da177e4SLinus Torvalds 	}
29531da177e4SLinus Torvalds 
2954c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2955c5993de8SAndrei Emeltchenko 
2956613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2957613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
29581da177e4SLinus Torvalds 		struct hci_conn *conn;
29591da177e4SLinus Torvalds 		__u16  handle, count;
29601da177e4SLinus Torvalds 
2961613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2962613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
29631da177e4SLinus Torvalds 
29641da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2965f4280918SAndrei Emeltchenko 		if (!conn)
2966f4280918SAndrei Emeltchenko 			continue;
2967f4280918SAndrei Emeltchenko 
29681da177e4SLinus Torvalds 		conn->sent -= count;
29691da177e4SLinus Torvalds 
2970f4280918SAndrei Emeltchenko 		switch (conn->type) {
2971f4280918SAndrei Emeltchenko 		case ACL_LINK:
297270f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
297370f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
29741da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2975f4280918SAndrei Emeltchenko 			break;
2976f4280918SAndrei Emeltchenko 
2977f4280918SAndrei Emeltchenko 		case LE_LINK:
29786ed58ec5SVille Tervo 			if (hdev->le_pkts) {
29796ed58ec5SVille Tervo 				hdev->le_cnt += count;
29806ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
29816ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
29826ed58ec5SVille Tervo 			} else {
29836ed58ec5SVille Tervo 				hdev->acl_cnt += count;
29846ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
29856ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
29866ed58ec5SVille Tervo 			}
2987f4280918SAndrei Emeltchenko 			break;
2988f4280918SAndrei Emeltchenko 
2989f4280918SAndrei Emeltchenko 		case SCO_LINK:
299070f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
299170f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
29925b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2993f4280918SAndrei Emeltchenko 			break;
2994f4280918SAndrei Emeltchenko 
2995f4280918SAndrei Emeltchenko 		default:
2996f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2997f4280918SAndrei Emeltchenko 			break;
29981da177e4SLinus Torvalds 		}
29991da177e4SLinus Torvalds 	}
3000a9de9248SMarcel Holtmann 
30013eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
30021da177e4SLinus Torvalds }
30031da177e4SLinus Torvalds 
300476ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
300576ef7cf7SAndrei Emeltchenko 						 __u16 handle)
300676ef7cf7SAndrei Emeltchenko {
300776ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
300876ef7cf7SAndrei Emeltchenko 
300976ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
301076ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
301176ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
301276ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
301376ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
301476ef7cf7SAndrei Emeltchenko 		if (chan)
301576ef7cf7SAndrei Emeltchenko 			return chan->conn;
301676ef7cf7SAndrei Emeltchenko 		break;
301776ef7cf7SAndrei Emeltchenko 	default:
301876ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
301976ef7cf7SAndrei Emeltchenko 		break;
302076ef7cf7SAndrei Emeltchenko 	}
302176ef7cf7SAndrei Emeltchenko 
302276ef7cf7SAndrei Emeltchenko 	return NULL;
302376ef7cf7SAndrei Emeltchenko }
302476ef7cf7SAndrei Emeltchenko 
30256039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
302625e89e99SAndrei Emeltchenko {
302725e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
302825e89e99SAndrei Emeltchenko 	int i;
302925e89e99SAndrei Emeltchenko 
303025e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
303125e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
303225e89e99SAndrei Emeltchenko 		return;
303325e89e99SAndrei Emeltchenko 	}
303425e89e99SAndrei Emeltchenko 
303525e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
303625e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
303725e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
303825e89e99SAndrei Emeltchenko 		return;
303925e89e99SAndrei Emeltchenko 	}
304025e89e99SAndrei Emeltchenko 
304125e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
304225e89e99SAndrei Emeltchenko 	       ev->num_hndl);
304325e89e99SAndrei Emeltchenko 
304425e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
304525e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
304676ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
304725e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
304825e89e99SAndrei Emeltchenko 
304925e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
305025e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
305125e89e99SAndrei Emeltchenko 
305276ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
305325e89e99SAndrei Emeltchenko 		if (!conn)
305425e89e99SAndrei Emeltchenko 			continue;
305525e89e99SAndrei Emeltchenko 
305625e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
305725e89e99SAndrei Emeltchenko 
305825e89e99SAndrei Emeltchenko 		switch (conn->type) {
305925e89e99SAndrei Emeltchenko 		case ACL_LINK:
3060bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
306125e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
306225e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
306325e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
306425e89e99SAndrei Emeltchenko 			break;
306525e89e99SAndrei Emeltchenko 
306625e89e99SAndrei Emeltchenko 		default:
306725e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
306825e89e99SAndrei Emeltchenko 			break;
306925e89e99SAndrei Emeltchenko 		}
307025e89e99SAndrei Emeltchenko 	}
307125e89e99SAndrei Emeltchenko 
307225e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
307325e89e99SAndrei Emeltchenko }
307425e89e99SAndrei Emeltchenko 
30756039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
30761da177e4SLinus Torvalds {
3077a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
307804837f64SMarcel Holtmann 	struct hci_conn *conn;
30791da177e4SLinus Torvalds 
30809f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
30811da177e4SLinus Torvalds 
30821da177e4SLinus Torvalds 	hci_dev_lock(hdev);
30831da177e4SLinus Torvalds 
308404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
308504837f64SMarcel Holtmann 	if (conn) {
308604837f64SMarcel Holtmann 		conn->mode = ev->mode;
308704837f64SMarcel Holtmann 
30888fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
30898fc9ced3SGustavo Padovan 					&conn->flags)) {
309004837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
309158a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
309204837f64SMarcel Holtmann 			else
309358a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
309404837f64SMarcel Holtmann 		}
3095e73439d8SMarcel Holtmann 
309651a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
3097e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
309804837f64SMarcel Holtmann 	}
309904837f64SMarcel Holtmann 
310004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
310104837f64SMarcel Holtmann }
310204837f64SMarcel Holtmann 
31036039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
31041da177e4SLinus Torvalds {
3105052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
3106052b30b0SMarcel Holtmann 	struct hci_conn *conn;
3107052b30b0SMarcel Holtmann 
3108a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3109052b30b0SMarcel Holtmann 
3110052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3111052b30b0SMarcel Holtmann 
3112052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3113b6f98044SWaldemar Rymarkiewicz 	if (!conn)
3114b6f98044SWaldemar Rymarkiewicz 		goto unlock;
3115b6f98044SWaldemar Rymarkiewicz 
3116b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
3117052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3118052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
311976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3120052b30b0SMarcel Holtmann 	}
3121052b30b0SMarcel Holtmann 
3122b6ae8457SJohan Hedberg 	if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) &&
31232f407f0aSJohan Hedberg 	    !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) {
312403b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
312503b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
31262f407f0aSJohan Hedberg 	} else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
3127a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
3128a770bb5aSWaldemar Rymarkiewicz 
3129a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
3130a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
3131a770bb5aSWaldemar Rymarkiewicz 		else
3132a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
3133a770bb5aSWaldemar Rymarkiewicz 
3134744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
3135a770bb5aSWaldemar Rymarkiewicz 	}
3136980e1a53SJohan Hedberg 
3137b6f98044SWaldemar Rymarkiewicz unlock:
3138052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
31391da177e4SLinus Torvalds }
31401da177e4SLinus Torvalds 
31416039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
31421da177e4SLinus Torvalds {
314355ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
314455ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
314555ed8ca1SJohan Hedberg 	struct hci_conn *conn;
314655ed8ca1SJohan Hedberg 	struct link_key *key;
314755ed8ca1SJohan Hedberg 
3148a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
314955ed8ca1SJohan Hedberg 
3150034cbea0SAndrei Emeltchenko 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
315155ed8ca1SJohan Hedberg 		return;
315255ed8ca1SJohan Hedberg 
315355ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
315455ed8ca1SJohan Hedberg 
315555ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
315655ed8ca1SJohan Hedberg 	if (!key) {
31576ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
31586ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
315955ed8ca1SJohan Hedberg 		goto not_found;
316055ed8ca1SJohan Hedberg 	}
316155ed8ca1SJohan Hedberg 
31626ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
31636ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
316455ed8ca1SJohan Hedberg 
316555ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
316660b83f57SWaldemar Rymarkiewicz 	if (conn) {
316766138ce8SMarcel Holtmann 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
316866138ce8SMarcel Holtmann 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
3169807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
317055ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
317155ed8ca1SJohan Hedberg 			goto not_found;
317255ed8ca1SJohan Hedberg 		}
317355ed8ca1SJohan Hedberg 
317460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
3175f3fb0b58SJohan Hedberg 		    (conn->pending_sec_level == BT_SECURITY_HIGH ||
3176f3fb0b58SJohan Hedberg 		     conn->pending_sec_level == BT_SECURITY_FIPS)) {
31778fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
31788fc9ced3SGustavo Padovan 			       hdev->name);
317960b83f57SWaldemar Rymarkiewicz 			goto not_found;
318060b83f57SWaldemar Rymarkiewicz 		}
318160b83f57SWaldemar Rymarkiewicz 
318260b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
318360b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
318460b83f57SWaldemar Rymarkiewicz 	}
318560b83f57SWaldemar Rymarkiewicz 
318655ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
31879b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
318855ed8ca1SJohan Hedberg 
318955ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
319055ed8ca1SJohan Hedberg 
319155ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
319255ed8ca1SJohan Hedberg 
319355ed8ca1SJohan Hedberg 	return;
319455ed8ca1SJohan Hedberg 
319555ed8ca1SJohan Hedberg not_found:
319655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
319755ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
31981da177e4SLinus Torvalds }
31991da177e4SLinus Torvalds 
32006039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
32011da177e4SLinus Torvalds {
3202052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
3203052b30b0SMarcel Holtmann 	struct hci_conn *conn;
32047652ff6aSJohan Hedberg 	struct link_key *key;
32057652ff6aSJohan Hedberg 	bool persistent;
320655ed8ca1SJohan Hedberg 	u8 pin_len = 0;
3207052b30b0SMarcel Holtmann 
3208a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3209052b30b0SMarcel Holtmann 
3210052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3211052b30b0SMarcel Holtmann 
3212052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3213052b30b0SMarcel Holtmann 	if (conn) {
3214052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3215052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3216980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
321713d39315SWaldemar Rymarkiewicz 
321813d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
321913d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
322013d39315SWaldemar Rymarkiewicz 
322176a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3222052b30b0SMarcel Holtmann 	}
3223052b30b0SMarcel Holtmann 
32247652ff6aSJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
32257652ff6aSJohan Hedberg 		goto unlock;
322655ed8ca1SJohan Hedberg 
32277652ff6aSJohan Hedberg 	key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key,
32287652ff6aSJohan Hedberg 			        ev->key_type, pin_len, &persistent);
32297652ff6aSJohan Hedberg 	if (!key)
32307652ff6aSJohan Hedberg 		goto unlock;
32317652ff6aSJohan Hedberg 
32327652ff6aSJohan Hedberg 	mgmt_new_link_key(hdev, key, persistent);
32337652ff6aSJohan Hedberg 
32346d5650c4SJohan Hedberg 	/* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
32356d5650c4SJohan Hedberg 	 * is set. If it's not set simply remove the key from the kernel
32366d5650c4SJohan Hedberg 	 * list (we've still notified user space about it but with
32376d5650c4SJohan Hedberg 	 * store_hint being 0).
32386d5650c4SJohan Hedberg 	 */
32396d5650c4SJohan Hedberg 	if (key->type == HCI_LK_DEBUG_COMBINATION &&
32406d5650c4SJohan Hedberg 	    !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) {
32416d5650c4SJohan Hedberg 		list_del(&key->list);
32426d5650c4SJohan Hedberg 		kfree(key);
32436d5650c4SJohan Hedberg 	} else if (conn) {
3244af6a9c32SJohan Hedberg 		if (persistent)
3245af6a9c32SJohan Hedberg 			clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
3246af6a9c32SJohan Hedberg 		else
3247af6a9c32SJohan Hedberg 			set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
32486d5650c4SJohan Hedberg 	}
32497652ff6aSJohan Hedberg 
32507652ff6aSJohan Hedberg unlock:
3251052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
32521da177e4SLinus Torvalds }
32531da177e4SLinus Torvalds 
32546039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
325504837f64SMarcel Holtmann {
3256a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
325704837f64SMarcel Holtmann 	struct hci_conn *conn;
325804837f64SMarcel Holtmann 
32599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
326004837f64SMarcel Holtmann 
326104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
326204837f64SMarcel Holtmann 
326304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
32641da177e4SLinus Torvalds 	if (conn && !ev->status) {
32651da177e4SLinus Torvalds 		struct inquiry_entry *ie;
32661da177e4SLinus Torvalds 
3267cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3268cc11b9c1SAndrei Emeltchenko 		if (ie) {
32691da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
32701da177e4SLinus Torvalds 			ie->timestamp = jiffies;
32711da177e4SLinus Torvalds 		}
32721da177e4SLinus Torvalds 	}
32731da177e4SLinus Torvalds 
32741da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
32751da177e4SLinus Torvalds }
32761da177e4SLinus Torvalds 
32776039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3278a8746417SMarcel Holtmann {
3279a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3280a8746417SMarcel Holtmann 	struct hci_conn *conn;
3281a8746417SMarcel Holtmann 
32829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3283a8746417SMarcel Holtmann 
3284a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
3285a8746417SMarcel Holtmann 
3286a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3287a8746417SMarcel Holtmann 	if (conn && !ev->status)
3288a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3289a8746417SMarcel Holtmann 
3290a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
3291a8746417SMarcel Holtmann }
3292a8746417SMarcel Holtmann 
32936039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
329485a1e930SMarcel Holtmann {
3295a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
329685a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
329785a1e930SMarcel Holtmann 
329885a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
329985a1e930SMarcel Holtmann 
330085a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
330185a1e930SMarcel Holtmann 
3302cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3303cc11b9c1SAndrei Emeltchenko 	if (ie) {
330485a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
330585a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
330685a1e930SMarcel Holtmann 	}
330785a1e930SMarcel Holtmann 
330885a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
330985a1e930SMarcel Holtmann }
331085a1e930SMarcel Holtmann 
33116039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3312807deac2SGustavo Padovan 					     struct sk_buff *skb)
3313a9de9248SMarcel Holtmann {
3314a9de9248SMarcel Holtmann 	struct inquiry_data data;
3315a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
3316a9de9248SMarcel Holtmann 
3317a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3318a9de9248SMarcel Holtmann 
3319a9de9248SMarcel Holtmann 	if (!num_rsp)
3320a9de9248SMarcel Holtmann 		return;
3321a9de9248SMarcel Holtmann 
33221519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
33231519cc17SAndre Guedes 		return;
33241519cc17SAndre Guedes 
3325a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3326a9de9248SMarcel Holtmann 
3327a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3328138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3329138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3330a9de9248SMarcel Holtmann 
3331e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3332af58925cSMarcel Holtmann 			u32 flags;
3333af58925cSMarcel Holtmann 
3334a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3335a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3336a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3337a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3338a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3339a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3340a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
334141a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
33423175405bSJohan Hedberg 
3343af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
3344af58925cSMarcel Holtmann 
334548264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3346e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3347af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
3348a9de9248SMarcel Holtmann 		}
3349a9de9248SMarcel Holtmann 	} else {
3350a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3351a9de9248SMarcel Holtmann 
3352e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3353af58925cSMarcel Holtmann 			u32 flags;
3354af58925cSMarcel Holtmann 
3355a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3356a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3357a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3358a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3359a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3360a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3361a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
336241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
3363af58925cSMarcel Holtmann 
3364af58925cSMarcel Holtmann 			flags = hci_inquiry_cache_update(hdev, &data, false);
3365af58925cSMarcel Holtmann 
336648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3367e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3368af58925cSMarcel Holtmann 					  flags, NULL, 0, NULL, 0);
3369a9de9248SMarcel Holtmann 		}
3370a9de9248SMarcel Holtmann 	}
3371a9de9248SMarcel Holtmann 
3372a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3373a9de9248SMarcel Holtmann }
3374a9de9248SMarcel Holtmann 
33756039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3376807deac2SGustavo Padovan 					struct sk_buff *skb)
3377a9de9248SMarcel Holtmann {
337841a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
337941a96212SMarcel Holtmann 	struct hci_conn *conn;
338041a96212SMarcel Holtmann 
3381a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
338241a96212SMarcel Holtmann 
338341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
338441a96212SMarcel Holtmann 
338541a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3386ccd556feSJohan Hedberg 	if (!conn)
3387ccd556feSJohan Hedberg 		goto unlock;
3388ccd556feSJohan Hedberg 
3389cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
3390cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
3391cad718edSJohan Hedberg 
3392769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
339341a96212SMarcel Holtmann 		struct inquiry_entry *ie;
339441a96212SMarcel Holtmann 
3395cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3396cc11b9c1SAndrei Emeltchenko 		if (ie)
339702b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
339841a96212SMarcel Holtmann 
3399bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
340058a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
3401bbb0eadaSJaganath Kanakkassery 		} else {
3402bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
3403bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
3404bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
3405bbb0eadaSJaganath Kanakkassery 			 * this.
3406bbb0eadaSJaganath Kanakkassery 			 *
3407bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
3408bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
3409bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
3410bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
3411bbb0eadaSJaganath Kanakkassery 		}
3412eb9a8f3fSMarcel Holtmann 
3413eb9a8f3fSMarcel Holtmann 		if (ev->features[0] & LMP_HOST_SC)
3414eb9a8f3fSMarcel Holtmann 			set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
341541a96212SMarcel Holtmann 	}
341641a96212SMarcel Holtmann 
3417ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3418ccd556feSJohan Hedberg 		goto unlock;
3419ccd556feSJohan Hedberg 
3420671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3421127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3422127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3423127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3424127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3425127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3426b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3427b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
342808c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
3429b644ba33SJohan Hedberg 				      conn->dev_class);
3430392599b9SJohan Hedberg 
3431127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3432769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3433769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
343476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3435769be974SMarcel Holtmann 	}
3436769be974SMarcel Holtmann 
3437ccd556feSJohan Hedberg unlock:
343841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3439a9de9248SMarcel Holtmann }
3440a9de9248SMarcel Holtmann 
34416039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3442807deac2SGustavo Padovan 				       struct sk_buff *skb)
3443a9de9248SMarcel Holtmann {
3444b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3445b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3446b6a0dc82SMarcel Holtmann 
34479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3448b6a0dc82SMarcel Holtmann 
3449b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3450b6a0dc82SMarcel Holtmann 
3451b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
34529dc0a3afSMarcel Holtmann 	if (!conn) {
34539dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
34549dc0a3afSMarcel Holtmann 			goto unlock;
34559dc0a3afSMarcel Holtmann 
34569dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3457b6a0dc82SMarcel Holtmann 		if (!conn)
3458b6a0dc82SMarcel Holtmann 			goto unlock;
3459b6a0dc82SMarcel Holtmann 
34609dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
34619dc0a3afSMarcel Holtmann 	}
34629dc0a3afSMarcel Holtmann 
3463732547f9SMarcel Holtmann 	switch (ev->status) {
3464732547f9SMarcel Holtmann 	case 0x00:
3465732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3466732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3467732547f9SMarcel Holtmann 
3468732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3469732547f9SMarcel Holtmann 		break;
3470732547f9SMarcel Holtmann 
347181218d20SNick Pelly 	case 0x10:	/* Connection Accept Timeout */
34721a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
3473705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3474732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
34751038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3476732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
347727539bc4SAndrew Earl 	case 0x20:	/* Unsupported LMP Parameter value */
34782dea632fSFrédéric Dalleau 		if (conn->out) {
3479efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3480efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
34812dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
3482efc7688bSMarcel Holtmann 				goto unlock;
3483efc7688bSMarcel Holtmann 		}
3484732547f9SMarcel Holtmann 		/* fall through */
3485efc7688bSMarcel Holtmann 
3486732547f9SMarcel Holtmann 	default:
3487b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3488732547f9SMarcel Holtmann 		break;
3489732547f9SMarcel Holtmann 	}
3490b6a0dc82SMarcel Holtmann 
3491b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3492b6a0dc82SMarcel Holtmann 	if (ev->status)
3493b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3494b6a0dc82SMarcel Holtmann 
3495b6a0dc82SMarcel Holtmann unlock:
3496b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3497a9de9248SMarcel Holtmann }
3498a9de9248SMarcel Holtmann 
3499efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len)
3500efdcf8e3SMarcel Holtmann {
3501efdcf8e3SMarcel Holtmann 	size_t parsed = 0;
3502efdcf8e3SMarcel Holtmann 
3503efdcf8e3SMarcel Holtmann 	while (parsed < eir_len) {
3504efdcf8e3SMarcel Holtmann 		u8 field_len = eir[0];
3505efdcf8e3SMarcel Holtmann 
3506efdcf8e3SMarcel Holtmann 		if (field_len == 0)
3507efdcf8e3SMarcel Holtmann 			return parsed;
3508efdcf8e3SMarcel Holtmann 
3509efdcf8e3SMarcel Holtmann 		parsed += field_len + 1;
3510efdcf8e3SMarcel Holtmann 		eir += field_len + 1;
3511efdcf8e3SMarcel Holtmann 	}
3512efdcf8e3SMarcel Holtmann 
3513efdcf8e3SMarcel Holtmann 	return eir_len;
3514efdcf8e3SMarcel Holtmann }
3515efdcf8e3SMarcel Holtmann 
35166039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3517807deac2SGustavo Padovan 					    struct sk_buff *skb)
3518a9de9248SMarcel Holtmann {
3519a9de9248SMarcel Holtmann 	struct inquiry_data data;
3520a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3521a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
35229d939d94SVishal Agarwal 	size_t eir_len;
3523a9de9248SMarcel Holtmann 
3524a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3525a9de9248SMarcel Holtmann 
3526a9de9248SMarcel Holtmann 	if (!num_rsp)
3527a9de9248SMarcel Holtmann 		return;
3528a9de9248SMarcel Holtmann 
35291519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
35301519cc17SAndre Guedes 		return;
35311519cc17SAndre Guedes 
3532a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3533a9de9248SMarcel Holtmann 
3534e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3535af58925cSMarcel Holtmann 		u32 flags;
3536af58925cSMarcel Holtmann 		bool name_known;
3537561aafbcSJohan Hedberg 
3538a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3539a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3540a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3541a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3542a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3543a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3544a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
354541a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3546561aafbcSJohan Hedberg 
3547a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
35484ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
35494ddb1930SJohan Hedberg 						       sizeof(info->data),
35504ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3551561aafbcSJohan Hedberg 		else
3552561aafbcSJohan Hedberg 			name_known = true;
3553561aafbcSJohan Hedberg 
3554af58925cSMarcel Holtmann 		flags = hci_inquiry_cache_update(hdev, &data, name_known);
3555af58925cSMarcel Holtmann 
35569d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
3557af58925cSMarcel Holtmann 
355848264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3559af58925cSMarcel Holtmann 				  info->dev_class, info->rssi,
3560af58925cSMarcel Holtmann 				  flags, info->data, eir_len, NULL, 0);
3561a9de9248SMarcel Holtmann 	}
3562a9de9248SMarcel Holtmann 
3563a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3564a9de9248SMarcel Holtmann }
3565a9de9248SMarcel Holtmann 
35661c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
35671c2e0041SJohan Hedberg 					 struct sk_buff *skb)
35681c2e0041SJohan Hedberg {
35691c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
35701c2e0041SJohan Hedberg 	struct hci_conn *conn;
35711c2e0041SJohan Hedberg 
35729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
35731c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
35741c2e0041SJohan Hedberg 
35751c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
35761c2e0041SJohan Hedberg 
35771c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
35781c2e0041SJohan Hedberg 	if (!conn)
35791c2e0041SJohan Hedberg 		goto unlock;
35801c2e0041SJohan Hedberg 
35819eb1fbfaSJohan Hedberg 	/* For BR/EDR the necessary steps are taken through the
35829eb1fbfaSJohan Hedberg 	 * auth_complete event.
35839eb1fbfaSJohan Hedberg 	 */
35849eb1fbfaSJohan Hedberg 	if (conn->type != LE_LINK)
35859eb1fbfaSJohan Hedberg 		goto unlock;
35869eb1fbfaSJohan Hedberg 
35871c2e0041SJohan Hedberg 	if (!ev->status)
35881c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
35891c2e0041SJohan Hedberg 
35901c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
35911c2e0041SJohan Hedberg 
35921c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3593bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
359476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
35951c2e0041SJohan Hedberg 		goto unlock;
35961c2e0041SJohan Hedberg 	}
35971c2e0041SJohan Hedberg 
35981c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
35991c2e0041SJohan Hedberg 		if (!ev->status)
36001c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
36011c2e0041SJohan Hedberg 
36021c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
360376a68ba0SDavid Herrmann 		hci_conn_drop(conn);
36041c2e0041SJohan Hedberg 	} else {
36051c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
36061c2e0041SJohan Hedberg 
36071c2e0041SJohan Hedberg 		hci_conn_hold(conn);
36081c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
360976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
36101c2e0041SJohan Hedberg 	}
36111c2e0041SJohan Hedberg 
36121c2e0041SJohan Hedberg unlock:
36131c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
36141c2e0041SJohan Hedberg }
36151c2e0041SJohan Hedberg 
36166039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
361717fa4b9dSJohan Hedberg {
361817fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
3619acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
3620acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
362158797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
362217fa4b9dSJohan Hedberg 
3623b7f94c88SMikel Astiz 	/* If both remote and local have enough IO capabilities, require
3624b7f94c88SMikel Astiz 	 * MITM protection
3625b7f94c88SMikel Astiz 	 */
3626b7f94c88SMikel Astiz 	if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT &&
3627b7f94c88SMikel Astiz 	    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT)
3628b7f94c88SMikel Astiz 		return conn->remote_auth | 0x01;
3629b7f94c88SMikel Astiz 
36307e74170aSTimo Mueller 	/* No MITM protection possible so ignore remote requirement */
36317e74170aSTimo Mueller 	return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01);
363217fa4b9dSJohan Hedberg }
363317fa4b9dSJohan Hedberg 
36346039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
36350493684eSMarcel Holtmann {
36360493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
36370493684eSMarcel Holtmann 	struct hci_conn *conn;
36380493684eSMarcel Holtmann 
36390493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
36400493684eSMarcel Holtmann 
36410493684eSMarcel Holtmann 	hci_dev_lock(hdev);
36420493684eSMarcel Holtmann 
36430493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
364403b555e1SJohan Hedberg 	if (!conn)
364503b555e1SJohan Hedberg 		goto unlock;
364603b555e1SJohan Hedberg 
36470493684eSMarcel Holtmann 	hci_conn_hold(conn);
36480493684eSMarcel Holtmann 
3649a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
365003b555e1SJohan Hedberg 		goto unlock;
365103b555e1SJohan Hedberg 
36522f407f0aSJohan Hedberg 	/* Allow pairing if we're pairable, the initiators of the
36532f407f0aSJohan Hedberg 	 * pairing or if the remote is not requesting bonding.
36542f407f0aSJohan Hedberg 	 */
3655b6ae8457SJohan Hedberg 	if (test_bit(HCI_BONDABLE, &hdev->dev_flags) ||
36562f407f0aSJohan Hedberg 	    test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) ||
365703b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
365817fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
365917fa4b9dSJohan Hedberg 
366017fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
36617a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
36627a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
36637a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
3664a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
3665b7f94c88SMikel Astiz 
3666b7f94c88SMikel Astiz 		/* If we are initiators, there is no remote information yet */
3667b7f94c88SMikel Astiz 		if (conn->remote_auth == 0xff) {
3668b16c6604SMikel Astiz 			/* Request MITM protection if our IO caps allow it
36694ad51a75SJohan Hedberg 			 * except for the no-bonding case.
3670b16c6604SMikel Astiz 			 */
36716fd6b915SMikel Astiz 			if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
36729f743d74SJohan Hedberg 			    conn->auth_type != HCI_AT_NO_BONDING)
36736c53823aSJohan Hedberg 				conn->auth_type |= 0x01;
36746c53823aSJohan Hedberg 
36756c53823aSJohan Hedberg 			cp.authentication = conn->auth_type;
3676b7f94c88SMikel Astiz 		} else {
36777cbc9bd9SJohan Hedberg 			conn->auth_type = hci_get_auth_req(conn);
36787cbc9bd9SJohan Hedberg 			cp.authentication = conn->auth_type;
3679b7f94c88SMikel Astiz 		}
368017fa4b9dSJohan Hedberg 
36818fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
36828fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3683ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3684ce85ee13SSzymon Janc 		else
3685ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3686ce85ee13SSzymon Janc 
368717fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
368817fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
368903b555e1SJohan Hedberg 	} else {
369003b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
369103b555e1SJohan Hedberg 
369203b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
36939f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
369403b555e1SJohan Hedberg 
369503b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
369603b555e1SJohan Hedberg 			     sizeof(cp), &cp);
369703b555e1SJohan Hedberg 	}
369803b555e1SJohan Hedberg 
369903b555e1SJohan Hedberg unlock:
370003b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
370103b555e1SJohan Hedberg }
370203b555e1SJohan Hedberg 
37036039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
370403b555e1SJohan Hedberg {
370503b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
370603b555e1SJohan Hedberg 	struct hci_conn *conn;
370703b555e1SJohan Hedberg 
370803b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
370903b555e1SJohan Hedberg 
371003b555e1SJohan Hedberg 	hci_dev_lock(hdev);
371103b555e1SJohan Hedberg 
371203b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
371303b555e1SJohan Hedberg 	if (!conn)
371403b555e1SJohan Hedberg 		goto unlock;
371503b555e1SJohan Hedberg 
371603b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
371703b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
371858a681efSJohan Hedberg 	if (ev->oob_data)
371958a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
372003b555e1SJohan Hedberg 
372103b555e1SJohan Hedberg unlock:
37220493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
37230493684eSMarcel Holtmann }
37240493684eSMarcel Holtmann 
37256039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3726a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3727a5c29683SJohan Hedberg {
3728a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
372955bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
37307a828908SJohan Hedberg 	struct hci_conn *conn;
3731a5c29683SJohan Hedberg 
3732a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3733a5c29683SJohan Hedberg 
3734a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3735a5c29683SJohan Hedberg 
3736a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
37377a828908SJohan Hedberg 		goto unlock;
37387a828908SJohan Hedberg 
37397a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
37407a828908SJohan Hedberg 	if (!conn)
37417a828908SJohan Hedberg 		goto unlock;
37427a828908SJohan Hedberg 
37437a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
37447a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
37457a828908SJohan Hedberg 
37467a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
37476c53823aSJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
37486c53823aSJohan Hedberg 	 * request. We check the security level here since it doesn't
37496c53823aSJohan Hedberg 	 * necessarily match conn->auth_type.
37506fd6b915SMikel Astiz 	 */
37516c53823aSJohan Hedberg 	if (conn->pending_sec_level > BT_SECURITY_MEDIUM &&
37526c53823aSJohan Hedberg 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
37537a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
37547a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
37557a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
37567a828908SJohan Hedberg 		goto unlock;
37577a828908SJohan Hedberg 	}
37587a828908SJohan Hedberg 
37597a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
3760a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
3761a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
376255bc1a37SJohan Hedberg 
376355bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
376455bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
3765ba15a58bSJohan Hedberg 		 * confirm_hint set to 1). The exception is if neither
376602f3e254SJohan Hedberg 		 * side had MITM or if the local IO capability is
376702f3e254SJohan Hedberg 		 * NoInputNoOutput, in which case we do auto-accept
3768ba15a58bSJohan Hedberg 		 */
3769ba15a58bSJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
377002f3e254SJohan Hedberg 		    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
3771ba15a58bSJohan Hedberg 		    (loc_mitm || rem_mitm)) {
377255bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
377355bc1a37SJohan Hedberg 			confirm_hint = 1;
377455bc1a37SJohan Hedberg 			goto confirm;
377555bc1a37SJohan Hedberg 		}
377655bc1a37SJohan Hedberg 
37779f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
37789f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
37799f61656aSJohan Hedberg 
37809f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
37819f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
37827bc18d9dSJohan Hedberg 			queue_delayed_work(conn->hdev->workqueue,
37837bc18d9dSJohan Hedberg 					   &conn->auto_accept_work, delay);
37849f61656aSJohan Hedberg 			goto unlock;
37859f61656aSJohan Hedberg 		}
37869f61656aSJohan Hedberg 
37877a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
37887a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
37897a828908SJohan Hedberg 		goto unlock;
37907a828908SJohan Hedberg 	}
37917a828908SJohan Hedberg 
379255bc1a37SJohan Hedberg confirm:
379339adbffeSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0,
379439adbffeSJohan Hedberg 				  le32_to_cpu(ev->passkey), confirm_hint);
3795a5c29683SJohan Hedberg 
37967a828908SJohan Hedberg unlock:
3797a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3798a5c29683SJohan Hedberg }
3799a5c29683SJohan Hedberg 
38006039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
38011143d458SBrian Gix 					 struct sk_buff *skb)
38021143d458SBrian Gix {
38031143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
38041143d458SBrian Gix 
38051143d458SBrian Gix 	BT_DBG("%s", hdev->name);
38061143d458SBrian Gix 
3807a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3808272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
38091143d458SBrian Gix }
38101143d458SBrian Gix 
381192a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
381292a25256SJohan Hedberg 					struct sk_buff *skb)
381392a25256SJohan Hedberg {
381492a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
381592a25256SJohan Hedberg 	struct hci_conn *conn;
381692a25256SJohan Hedberg 
381792a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
381892a25256SJohan Hedberg 
381992a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
382092a25256SJohan Hedberg 	if (!conn)
382192a25256SJohan Hedberg 		return;
382292a25256SJohan Hedberg 
382392a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
382492a25256SJohan Hedberg 	conn->passkey_entered = 0;
382592a25256SJohan Hedberg 
382692a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
382792a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
382892a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
382992a25256SJohan Hedberg 					 conn->passkey_entered);
383092a25256SJohan Hedberg }
383192a25256SJohan Hedberg 
383292a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
383392a25256SJohan Hedberg {
383492a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
383592a25256SJohan Hedberg 	struct hci_conn *conn;
383692a25256SJohan Hedberg 
383792a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
383892a25256SJohan Hedberg 
383992a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
384092a25256SJohan Hedberg 	if (!conn)
384192a25256SJohan Hedberg 		return;
384292a25256SJohan Hedberg 
384392a25256SJohan Hedberg 	switch (ev->type) {
384492a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
384592a25256SJohan Hedberg 		conn->passkey_entered = 0;
384692a25256SJohan Hedberg 		return;
384792a25256SJohan Hedberg 
384892a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
384992a25256SJohan Hedberg 		conn->passkey_entered++;
385092a25256SJohan Hedberg 		break;
385192a25256SJohan Hedberg 
385292a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
385392a25256SJohan Hedberg 		conn->passkey_entered--;
385492a25256SJohan Hedberg 		break;
385592a25256SJohan Hedberg 
385692a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
385792a25256SJohan Hedberg 		conn->passkey_entered = 0;
385892a25256SJohan Hedberg 		break;
385992a25256SJohan Hedberg 
386092a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
386192a25256SJohan Hedberg 		return;
386292a25256SJohan Hedberg 	}
386392a25256SJohan Hedberg 
386492a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
386592a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
386692a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
386792a25256SJohan Hedberg 					 conn->passkey_entered);
386892a25256SJohan Hedberg }
386992a25256SJohan Hedberg 
38706039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3871807deac2SGustavo Padovan 					 struct sk_buff *skb)
38720493684eSMarcel Holtmann {
38730493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
38740493684eSMarcel Holtmann 	struct hci_conn *conn;
38750493684eSMarcel Holtmann 
38760493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
38770493684eSMarcel Holtmann 
38780493684eSMarcel Holtmann 	hci_dev_lock(hdev);
38790493684eSMarcel Holtmann 
38800493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
38812a611692SJohan Hedberg 	if (!conn)
38822a611692SJohan Hedberg 		goto unlock;
38832a611692SJohan Hedberg 
3884c1d4fa7aSJohan Hedberg 	/* Reset the authentication requirement to unknown */
3885c1d4fa7aSJohan Hedberg 	conn->remote_auth = 0xff;
3886c1d4fa7aSJohan Hedberg 
38872a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
38882a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
38892a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
38902a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
38912a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3892fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3893bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3894bab73cb6SJohan Hedberg 				 ev->status);
38952a611692SJohan Hedberg 
389676a68ba0SDavid Herrmann 	hci_conn_drop(conn);
38970493684eSMarcel Holtmann 
38982a611692SJohan Hedberg unlock:
38990493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
39000493684eSMarcel Holtmann }
39010493684eSMarcel Holtmann 
39026039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3903807deac2SGustavo Padovan 					 struct sk_buff *skb)
390441a96212SMarcel Holtmann {
390541a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
390641a96212SMarcel Holtmann 	struct inquiry_entry *ie;
3907cad718edSJohan Hedberg 	struct hci_conn *conn;
390841a96212SMarcel Holtmann 
390941a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
391041a96212SMarcel Holtmann 
391141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
391241a96212SMarcel Holtmann 
3913cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3914cad718edSJohan Hedberg 	if (conn)
3915cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
3916cad718edSJohan Hedberg 
3917cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3918cc11b9c1SAndrei Emeltchenko 	if (ie)
391902b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
392041a96212SMarcel Holtmann 
392141a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
392241a96212SMarcel Holtmann }
392341a96212SMarcel Holtmann 
39246039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
39252763eda6SSzymon Janc 					    struct sk_buff *skb)
39262763eda6SSzymon Janc {
39272763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
39282763eda6SSzymon Janc 	struct oob_data *data;
39292763eda6SSzymon Janc 
39302763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
39312763eda6SSzymon Janc 
39322763eda6SSzymon Janc 	hci_dev_lock(hdev);
39332763eda6SSzymon Janc 
3934a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3935e1ba1f15SSzymon Janc 		goto unlock;
3936e1ba1f15SSzymon Janc 
39372763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
39382763eda6SSzymon Janc 	if (data) {
3939519ca9d0SMarcel Holtmann 		if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
3940519ca9d0SMarcel Holtmann 			struct hci_cp_remote_oob_ext_data_reply cp;
3941519ca9d0SMarcel Holtmann 
3942519ca9d0SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
3943519ca9d0SMarcel Holtmann 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
3944519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer192, data->randomizer192,
3945519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer192));
3946519ca9d0SMarcel Holtmann 			memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
3947519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer256, data->randomizer256,
3948519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer256));
3949519ca9d0SMarcel Holtmann 
3950519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
3951519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3952519ca9d0SMarcel Holtmann 		} else {
39532763eda6SSzymon Janc 			struct hci_cp_remote_oob_data_reply cp;
39542763eda6SSzymon Janc 
39552763eda6SSzymon Janc 			bacpy(&cp.bdaddr, &ev->bdaddr);
3956519ca9d0SMarcel Holtmann 			memcpy(cp.hash, data->hash192, sizeof(cp.hash));
3957519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer, data->randomizer192,
3958519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer));
39592763eda6SSzymon Janc 
3960519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
3961519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3962519ca9d0SMarcel Holtmann 		}
39632763eda6SSzymon Janc 	} else {
39642763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
39652763eda6SSzymon Janc 
39662763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
3967519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
3968519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
39692763eda6SSzymon Janc 	}
39702763eda6SSzymon Janc 
3971e1ba1f15SSzymon Janc unlock:
39722763eda6SSzymon Janc 	hci_dev_unlock(hdev);
39732763eda6SSzymon Janc }
39742763eda6SSzymon Janc 
3975d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3976d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3977d5e91192SAndrei Emeltchenko {
3978d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3979d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3980d5e91192SAndrei Emeltchenko 
3981d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3982d5e91192SAndrei Emeltchenko 	       ev->status);
3983d5e91192SAndrei Emeltchenko 
3984d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3985d5e91192SAndrei Emeltchenko 
3986d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3987d5e91192SAndrei Emeltchenko 	if (!hcon) {
3988d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3989d5e91192SAndrei Emeltchenko 		return;
3990d5e91192SAndrei Emeltchenko 	}
3991d5e91192SAndrei Emeltchenko 
3992d5e91192SAndrei Emeltchenko 	if (ev->status) {
3993d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3994d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3995d5e91192SAndrei Emeltchenko 		return;
3996d5e91192SAndrei Emeltchenko 	}
3997d5e91192SAndrei Emeltchenko 
3998d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3999d5e91192SAndrei Emeltchenko 
4000d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
4001d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
4002d5e91192SAndrei Emeltchenko 
4003d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
4004d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
400576a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
4006d5e91192SAndrei Emeltchenko 
4007d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
4008d5e91192SAndrei Emeltchenko 
4009cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
4010cf70ff22SAndrei Emeltchenko 
4011d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
4012d5e91192SAndrei Emeltchenko }
4013d5e91192SAndrei Emeltchenko 
401427695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
401527695fb4SAndrei Emeltchenko {
401627695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
401727695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
401827695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
401927695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
402027695fb4SAndrei Emeltchenko 
402127695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
402227695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
402327695fb4SAndrei Emeltchenko 	       ev->status);
402427695fb4SAndrei Emeltchenko 
402527695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
402627695fb4SAndrei Emeltchenko 	if (!hcon)
402727695fb4SAndrei Emeltchenko 		return;
402827695fb4SAndrei Emeltchenko 
402927695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
403027695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
403127695fb4SAndrei Emeltchenko 	if (!hchan)
403227695fb4SAndrei Emeltchenko 		return;
403327695fb4SAndrei Emeltchenko 
403427695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
403527695fb4SAndrei Emeltchenko 
403627695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
403727695fb4SAndrei Emeltchenko 
403827695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
403927695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
404027695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
404127695fb4SAndrei Emeltchenko 
404227695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
404327695fb4SAndrei Emeltchenko 
404427695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
404527695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
404627695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
404727695fb4SAndrei Emeltchenko 
404827695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
404927695fb4SAndrei Emeltchenko 	}
405027695fb4SAndrei Emeltchenko }
405127695fb4SAndrei Emeltchenko 
4052606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
4053606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
4054606e2a10SAndrei Emeltchenko {
4055606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
4056606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
4057606e2a10SAndrei Emeltchenko 
4058606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
4059606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
4060606e2a10SAndrei Emeltchenko 
4061606e2a10SAndrei Emeltchenko 	if (ev->status)
4062606e2a10SAndrei Emeltchenko 		return;
4063606e2a10SAndrei Emeltchenko 
4064606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
4065606e2a10SAndrei Emeltchenko 
4066606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
4067606e2a10SAndrei Emeltchenko 	if (!hchan)
4068606e2a10SAndrei Emeltchenko 		goto unlock;
4069606e2a10SAndrei Emeltchenko 
4070606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
4071606e2a10SAndrei Emeltchenko 
4072606e2a10SAndrei Emeltchenko unlock:
4073606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
4074606e2a10SAndrei Emeltchenko }
4075606e2a10SAndrei Emeltchenko 
40769eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
40779eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
40789eef6b3aSAndrei Emeltchenko {
40799eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
40809eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
40819eef6b3aSAndrei Emeltchenko 
40829eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
40839eef6b3aSAndrei Emeltchenko 
40849eef6b3aSAndrei Emeltchenko 	if (ev->status)
40859eef6b3aSAndrei Emeltchenko 		return;
40869eef6b3aSAndrei Emeltchenko 
40879eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
40889eef6b3aSAndrei Emeltchenko 
40899eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
40909eef6b3aSAndrei Emeltchenko 	if (hcon) {
40919eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
40929eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
40939eef6b3aSAndrei Emeltchenko 	}
40949eef6b3aSAndrei Emeltchenko 
40959eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
40969eef6b3aSAndrei Emeltchenko }
40979eef6b3aSAndrei Emeltchenko 
40986039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
4099fcd89c09SVille Tervo {
4100fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
4101912b42efSJohan Hedberg 	struct hci_conn_params *params;
4102fcd89c09SVille Tervo 	struct hci_conn *conn;
410368d6f6deSJohan Hedberg 	struct smp_irk *irk;
4104837d502eSJohan Hedberg 	u8 addr_type;
4105fcd89c09SVille Tervo 
41069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
4107fcd89c09SVille Tervo 
4108fcd89c09SVille Tervo 	hci_dev_lock(hdev);
4109fcd89c09SVille Tervo 
4110fbd96c15SJohan Hedberg 	/* All controllers implicitly stop advertising in the event of a
4111fbd96c15SJohan Hedberg 	 * connection, so ensure that the state bit is cleared.
4112fbd96c15SJohan Hedberg 	 */
4113fbd96c15SJohan Hedberg 	clear_bit(HCI_LE_ADV, &hdev->dev_flags);
4114fbd96c15SJohan Hedberg 
41154f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
4116b62f328bSVille Tervo 	if (!conn) {
4117a5c4e309SJohan Hedberg 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr, ev->role);
4118b62f328bSVille Tervo 		if (!conn) {
4119b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
4120230fd16aSAndre Guedes 			goto unlock;
4121b62f328bSVille Tervo 		}
412229b7988aSAndre Guedes 
412329b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
4124b9b343d2SAndre Guedes 
4125cb1d68f7SJohan Hedberg 		/* If we didn't have a hci_conn object previously
4126cb1d68f7SJohan Hedberg 		 * but we're in master role this must be something
4127cb1d68f7SJohan Hedberg 		 * initiated using a white list. Since white list based
4128cb1d68f7SJohan Hedberg 		 * connections are not "first class citizens" we don't
4129cb1d68f7SJohan Hedberg 		 * have full tracking of them. Therefore, we go ahead
4130cb1d68f7SJohan Hedberg 		 * with a "best effort" approach of determining the
4131cb1d68f7SJohan Hedberg 		 * initiator address based on the HCI_PRIVACY flag.
4132cb1d68f7SJohan Hedberg 		 */
4133cb1d68f7SJohan Hedberg 		if (conn->out) {
4134cb1d68f7SJohan Hedberg 			conn->resp_addr_type = ev->bdaddr_type;
4135cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &ev->bdaddr);
4136cb1d68f7SJohan Hedberg 			if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) {
4137cb1d68f7SJohan Hedberg 				conn->init_addr_type = ADDR_LE_DEV_RANDOM;
4138cb1d68f7SJohan Hedberg 				bacpy(&conn->init_addr, &hdev->rpa);
4139cb1d68f7SJohan Hedberg 			} else {
4140cb1d68f7SJohan Hedberg 				hci_copy_identity_address(hdev,
4141cb1d68f7SJohan Hedberg 							  &conn->init_addr,
4142cb1d68f7SJohan Hedberg 							  &conn->init_addr_type);
4143cb1d68f7SJohan Hedberg 			}
414480c24ab8SJohan Hedberg 		}
4145cb1d68f7SJohan Hedberg 	} else {
414680c24ab8SJohan Hedberg 		cancel_delayed_work(&conn->le_conn_timeout);
414780c24ab8SJohan Hedberg 	}
414880c24ab8SJohan Hedberg 
414980c24ab8SJohan Hedberg 	if (!conn->out) {
4150cb1d68f7SJohan Hedberg 		/* Set the responder (our side) address type based on
4151cb1d68f7SJohan Hedberg 		 * the advertising address type.
4152cb1d68f7SJohan Hedberg 		 */
4153cb1d68f7SJohan Hedberg 		conn->resp_addr_type = hdev->adv_addr_type;
4154cb1d68f7SJohan Hedberg 		if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM)
4155cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &hdev->random_addr);
4156cb1d68f7SJohan Hedberg 		else
4157cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &hdev->bdaddr);
4158cb1d68f7SJohan Hedberg 
4159cb1d68f7SJohan Hedberg 		conn->init_addr_type = ev->bdaddr_type;
4160cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &ev->bdaddr);
4161a720d735SMarcel Holtmann 
4162a720d735SMarcel Holtmann 		/* For incoming connections, set the default minimum
4163a720d735SMarcel Holtmann 		 * and maximum connection interval. They will be used
4164a720d735SMarcel Holtmann 		 * to check if the parameters are in range and if not
4165a720d735SMarcel Holtmann 		 * trigger the connection update procedure.
4166a720d735SMarcel Holtmann 		 */
4167a720d735SMarcel Holtmann 		conn->le_conn_min_interval = hdev->le_conn_min_interval;
4168a720d735SMarcel Holtmann 		conn->le_conn_max_interval = hdev->le_conn_max_interval;
4169cb1d68f7SJohan Hedberg 	}
41707be2edbbSJohan Hedberg 
4171edb4b466SMarcel Holtmann 	/* Lookup the identity address from the stored connection
4172edb4b466SMarcel Holtmann 	 * address and address type.
4173edb4b466SMarcel Holtmann 	 *
4174edb4b466SMarcel Holtmann 	 * When establishing connections to an identity address, the
4175edb4b466SMarcel Holtmann 	 * connection procedure will store the resolvable random
4176edb4b466SMarcel Holtmann 	 * address first. Now if it can be converted back into the
4177edb4b466SMarcel Holtmann 	 * identity address, start using the identity address from
4178edb4b466SMarcel Holtmann 	 * now on.
4179edb4b466SMarcel Holtmann 	 */
4180edb4b466SMarcel Holtmann 	irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
418168d6f6deSJohan Hedberg 	if (irk) {
418268d6f6deSJohan Hedberg 		bacpy(&conn->dst, &irk->bdaddr);
418368d6f6deSJohan Hedberg 		conn->dst_type = irk->addr_type;
418468d6f6deSJohan Hedberg 	}
418568d6f6deSJohan Hedberg 
4186837d502eSJohan Hedberg 	if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
4187837d502eSJohan Hedberg 		addr_type = BDADDR_LE_PUBLIC;
4188837d502eSJohan Hedberg 	else
4189837d502eSJohan Hedberg 		addr_type = BDADDR_LE_RANDOM;
4190837d502eSJohan Hedberg 
41912d3c2260SJohan Hedberg 	if (ev->status) {
41922d3c2260SJohan Hedberg 		hci_le_conn_failed(conn, ev->status);
4193837d502eSJohan Hedberg 		goto unlock;
4194837d502eSJohan Hedberg 	}
4195837d502eSJohan Hedberg 
41962d3c2260SJohan Hedberg 	/* Drop the connection if the device is blocked */
41972d3c2260SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) {
41982d3c2260SJohan Hedberg 		hci_conn_drop(conn);
4199cd17decbSAndre Guedes 		goto unlock;
4200cd17decbSAndre Guedes 	}
4201cd17decbSAndre Guedes 
4202b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
420301fdb0fcSMarcel Holtmann 		mgmt_device_connected(hdev, &conn->dst, conn->type,
420495b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
420583bc71b4SVinicius Costa Gomes 
42067b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
4207fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
4208fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
4209fcd89c09SVille Tervo 
4210e04fde60SMarcel Holtmann 	conn->le_conn_interval = le16_to_cpu(ev->interval);
4211e04fde60SMarcel Holtmann 	conn->le_conn_latency = le16_to_cpu(ev->latency);
4212e04fde60SMarcel Holtmann 	conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
4213e04fde60SMarcel Holtmann 
4214fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
4215fcd89c09SVille Tervo 
4216fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
4217fcd89c09SVille Tervo 
4218912b42efSJohan Hedberg 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
4219223683a5SJohan Hedberg 	if (params)
422095305baaSJohan Hedberg 		list_del_init(&params->action);
4221a4790dbdSAndre Guedes 
4222fcd89c09SVille Tervo unlock:
4223223683a5SJohan Hedberg 	hci_update_background_scan(hdev);
4224fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
4225fcd89c09SVille Tervo }
4226fcd89c09SVille Tervo 
42271855d92dSMarcel Holtmann static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
42281855d92dSMarcel Holtmann 					    struct sk_buff *skb)
42291855d92dSMarcel Holtmann {
42301855d92dSMarcel Holtmann 	struct hci_ev_le_conn_update_complete *ev = (void *) skb->data;
42311855d92dSMarcel Holtmann 	struct hci_conn *conn;
42321855d92dSMarcel Holtmann 
42331855d92dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
42341855d92dSMarcel Holtmann 
42351855d92dSMarcel Holtmann 	if (ev->status)
42361855d92dSMarcel Holtmann 		return;
42371855d92dSMarcel Holtmann 
42381855d92dSMarcel Holtmann 	hci_dev_lock(hdev);
42391855d92dSMarcel Holtmann 
42401855d92dSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
42411855d92dSMarcel Holtmann 	if (conn) {
42421855d92dSMarcel Holtmann 		conn->le_conn_interval = le16_to_cpu(ev->interval);
42431855d92dSMarcel Holtmann 		conn->le_conn_latency = le16_to_cpu(ev->latency);
42441855d92dSMarcel Holtmann 		conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
42451855d92dSMarcel Holtmann 	}
42461855d92dSMarcel Holtmann 
42471855d92dSMarcel Holtmann 	hci_dev_unlock(hdev);
42481855d92dSMarcel Holtmann }
42491855d92dSMarcel Holtmann 
4250a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */
42517e899c94SJohan Hedberg static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
42521c1abcabSJohan Hedberg 				  u8 addr_type, u8 adv_type)
4253a4790dbdSAndre Guedes {
4254a4790dbdSAndre Guedes 	struct hci_conn *conn;
42554b9e7e75SMarcel Holtmann 	struct hci_conn_params *params;
4256a4790dbdSAndre Guedes 
42571c1abcabSJohan Hedberg 	/* If the event is not connectable don't proceed further */
42581c1abcabSJohan Hedberg 	if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND)
42597e899c94SJohan Hedberg 		return;
42601c1abcabSJohan Hedberg 
42611c1abcabSJohan Hedberg 	/* Ignore if the device is blocked */
4262dcc36c16SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type))
42637e899c94SJohan Hedberg 		return;
42641c1abcabSJohan Hedberg 
4265f99353cfSJohan Hedberg 	/* Most controller will fail if we try to create new connections
4266f99353cfSJohan Hedberg 	 * while we have an existing one in slave role.
4267f99353cfSJohan Hedberg 	 */
4268f99353cfSJohan Hedberg 	if (hdev->conn_hash.le_num_slave > 0)
4269f99353cfSJohan Hedberg 		return;
4270f99353cfSJohan Hedberg 
42711c1abcabSJohan Hedberg 	/* If we're not connectable only connect devices that we have in
42721c1abcabSJohan Hedberg 	 * our pend_le_conns list.
42731c1abcabSJohan Hedberg 	 */
42744b9e7e75SMarcel Holtmann 	params = hci_pend_le_action_lookup(&hdev->pend_le_conns,
42754b9e7e75SMarcel Holtmann 					   addr, addr_type);
42764b9e7e75SMarcel Holtmann 	if (!params)
42777e899c94SJohan Hedberg 		return;
4278a4790dbdSAndre Guedes 
42794b9e7e75SMarcel Holtmann 	switch (params->auto_connect) {
42804b9e7e75SMarcel Holtmann 	case HCI_AUTO_CONN_DIRECT:
42814b9e7e75SMarcel Holtmann 		/* Only devices advertising with ADV_DIRECT_IND are
42824b9e7e75SMarcel Holtmann 		 * triggering a connection attempt. This is allowing
42834b9e7e75SMarcel Holtmann 		 * incoming connections from slave devices.
42844b9e7e75SMarcel Holtmann 		 */
42854b9e7e75SMarcel Holtmann 		if (adv_type != LE_ADV_DIRECT_IND)
42864b9e7e75SMarcel Holtmann 			return;
42874b9e7e75SMarcel Holtmann 		break;
42884b9e7e75SMarcel Holtmann 	case HCI_AUTO_CONN_ALWAYS:
42894b9e7e75SMarcel Holtmann 		/* Devices advertising with ADV_IND or ADV_DIRECT_IND
42904b9e7e75SMarcel Holtmann 		 * are triggering a connection attempt. This means
42914b9e7e75SMarcel Holtmann 		 * that incoming connectioms from slave device are
42924b9e7e75SMarcel Holtmann 		 * accepted and also outgoing connections to slave
42934b9e7e75SMarcel Holtmann 		 * devices are established when found.
42944b9e7e75SMarcel Holtmann 		 */
42954b9e7e75SMarcel Holtmann 		break;
42964b9e7e75SMarcel Holtmann 	default:
42974b9e7e75SMarcel Holtmann 		return;
42984b9e7e75SMarcel Holtmann 	}
42994b9e7e75SMarcel Holtmann 
4300a4790dbdSAndre Guedes 	conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
4301e804d25dSJohan Hedberg 			      HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
4302a4790dbdSAndre Guedes 	if (!IS_ERR(conn))
43037e899c94SJohan Hedberg 		return;
4304a4790dbdSAndre Guedes 
4305a4790dbdSAndre Guedes 	switch (PTR_ERR(conn)) {
4306a4790dbdSAndre Guedes 	case -EBUSY:
4307a4790dbdSAndre Guedes 		/* If hci_connect() returns -EBUSY it means there is already
4308a4790dbdSAndre Guedes 		 * an LE connection attempt going on. Since controllers don't
4309a4790dbdSAndre Guedes 		 * support more than one connection attempt at the time, we
4310a4790dbdSAndre Guedes 		 * don't consider this an error case.
4311a4790dbdSAndre Guedes 		 */
4312a4790dbdSAndre Guedes 		break;
4313a4790dbdSAndre Guedes 	default:
4314a4790dbdSAndre Guedes 		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
4315a4790dbdSAndre Guedes 	}
4316a4790dbdSAndre Guedes }
4317a4790dbdSAndre Guedes 
43184af605d8SJohan Hedberg static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
43194af605d8SJohan Hedberg 			       u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
43204af605d8SJohan Hedberg {
4321b9a6328fSJohan Hedberg 	struct discovery_state *d = &hdev->discovery;
43221c1abcabSJohan Hedberg 	struct smp_irk *irk;
4323474ee066SJohan Hedberg 	bool match;
4324c70a7e4cSMarcel Holtmann 	u32 flags;
4325b9a6328fSJohan Hedberg 
4326435a13d8SJohan Hedberg 	/* Check if we need to convert to identity address */
4327435a13d8SJohan Hedberg 	irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
4328435a13d8SJohan Hedberg 	if (irk) {
4329435a13d8SJohan Hedberg 		bdaddr = &irk->bdaddr;
4330435a13d8SJohan Hedberg 		bdaddr_type = irk->addr_type;
4331435a13d8SJohan Hedberg 	}
4332435a13d8SJohan Hedberg 
43331c1abcabSJohan Hedberg 	/* Check if we have been requested to connect to this device */
43341c1abcabSJohan Hedberg 	check_pending_le_conn(hdev, bdaddr, bdaddr_type, type);
433599a6768eSJohan Hedberg 
43361c1abcabSJohan Hedberg 	/* Passive scanning shouldn't trigger any device found events,
43371c1abcabSJohan Hedberg 	 * except for devices marked as CONN_REPORT for which we do send
43381c1abcabSJohan Hedberg 	 * device found events.
43391c1abcabSJohan Hedberg 	 */
43401c1abcabSJohan Hedberg 	if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
43410d2bf134SJohan Hedberg 		if (type == LE_ADV_DIRECT_IND)
43420d2bf134SJohan Hedberg 			return;
43430d2bf134SJohan Hedberg 
43443a19b6feSJohan Hedberg 		if (!hci_pend_le_action_lookup(&hdev->pend_le_reports,
43453a19b6feSJohan Hedberg 					       bdaddr, bdaddr_type))
43460d2bf134SJohan Hedberg 			return;
43470d2bf134SJohan Hedberg 
43480d2bf134SJohan Hedberg 		if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND)
43490d2bf134SJohan Hedberg 			flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
43500d2bf134SJohan Hedberg 		else
43510d2bf134SJohan Hedberg 			flags = 0;
43520d2bf134SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
43530d2bf134SJohan Hedberg 				  rssi, flags, data, len, NULL, 0);
435497bf2e99SJohan Hedberg 		return;
4355ca5c4be7SJohan Hedberg 	}
43564af605d8SJohan Hedberg 
4357c70a7e4cSMarcel Holtmann 	/* When receiving non-connectable or scannable undirected
4358c70a7e4cSMarcel Holtmann 	 * advertising reports, this means that the remote device is
4359c70a7e4cSMarcel Holtmann 	 * not connectable and then clearly indicate this in the
4360c70a7e4cSMarcel Holtmann 	 * device found event.
4361c70a7e4cSMarcel Holtmann 	 *
4362c70a7e4cSMarcel Holtmann 	 * When receiving a scan response, then there is no way to
4363c70a7e4cSMarcel Holtmann 	 * know if the remote device is connectable or not. However
4364c70a7e4cSMarcel Holtmann 	 * since scan responses are merged with a previously seen
4365c70a7e4cSMarcel Holtmann 	 * advertising report, the flags field from that report
4366c70a7e4cSMarcel Holtmann 	 * will be used.
4367c70a7e4cSMarcel Holtmann 	 *
4368c70a7e4cSMarcel Holtmann 	 * In the really unlikely case that a controller get confused
4369c70a7e4cSMarcel Holtmann 	 * and just sends a scan response event, then it is marked as
4370c70a7e4cSMarcel Holtmann 	 * not connectable as well.
4371c70a7e4cSMarcel Holtmann 	 */
4372c70a7e4cSMarcel Holtmann 	if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND ||
4373c70a7e4cSMarcel Holtmann 	    type == LE_ADV_SCAN_RSP)
4374c70a7e4cSMarcel Holtmann 		flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
4375c70a7e4cSMarcel Holtmann 	else
4376c70a7e4cSMarcel Holtmann 		flags = 0;
4377c70a7e4cSMarcel Holtmann 
4378b9a6328fSJohan Hedberg 	/* If there's nothing pending either store the data from this
4379b9a6328fSJohan Hedberg 	 * event or send an immediate device found event if the data
4380b9a6328fSJohan Hedberg 	 * should not be stored for later.
4381b9a6328fSJohan Hedberg 	 */
4382b9a6328fSJohan Hedberg 	if (!has_pending_adv_report(hdev)) {
4383b9a6328fSJohan Hedberg 		/* If the report will trigger a SCAN_REQ store it for
4384b9a6328fSJohan Hedberg 		 * later merging.
4385b9a6328fSJohan Hedberg 		 */
4386b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
4387b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
4388c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
4389b9a6328fSJohan Hedberg 			return;
4390b9a6328fSJohan Hedberg 		}
4391b9a6328fSJohan Hedberg 
4392b9a6328fSJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
4393c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
4394b9a6328fSJohan Hedberg 		return;
4395b9a6328fSJohan Hedberg 	}
4396b9a6328fSJohan Hedberg 
4397474ee066SJohan Hedberg 	/* Check if the pending report is for the same device as the new one */
4398474ee066SJohan Hedberg 	match = (!bacmp(bdaddr, &d->last_adv_addr) &&
4399474ee066SJohan Hedberg 		 bdaddr_type == d->last_adv_addr_type);
4400474ee066SJohan Hedberg 
4401b9a6328fSJohan Hedberg 	/* If the pending data doesn't match this report or this isn't a
4402b9a6328fSJohan Hedberg 	 * scan response (e.g. we got a duplicate ADV_IND) then force
4403b9a6328fSJohan Hedberg 	 * sending of the pending data.
4404b9a6328fSJohan Hedberg 	 */
4405474ee066SJohan Hedberg 	if (type != LE_ADV_SCAN_RSP || !match) {
4406474ee066SJohan Hedberg 		/* Send out whatever is in the cache, but skip duplicates */
4407474ee066SJohan Hedberg 		if (!match)
4408b9a6328fSJohan Hedberg 			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4409ff5cd29fSJohan Hedberg 					  d->last_adv_addr_type, NULL,
4410c70a7e4cSMarcel Holtmann 					  d->last_adv_rssi, d->last_adv_flags,
4411ff5cd29fSJohan Hedberg 					  d->last_adv_data,
4412474ee066SJohan Hedberg 					  d->last_adv_data_len, NULL, 0);
4413b9a6328fSJohan Hedberg 
4414b9a6328fSJohan Hedberg 		/* If the new report will trigger a SCAN_REQ store it for
4415b9a6328fSJohan Hedberg 		 * later merging.
4416b9a6328fSJohan Hedberg 		 */
4417b9a6328fSJohan Hedberg 		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
4418b9a6328fSJohan Hedberg 			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
4419c70a7e4cSMarcel Holtmann 						 rssi, flags, data, len);
4420b9a6328fSJohan Hedberg 			return;
4421b9a6328fSJohan Hedberg 		}
4422b9a6328fSJohan Hedberg 
4423b9a6328fSJohan Hedberg 		/* The advertising reports cannot be merged, so clear
4424b9a6328fSJohan Hedberg 		 * the pending report and send out a device found event.
4425b9a6328fSJohan Hedberg 		 */
4426b9a6328fSJohan Hedberg 		clear_pending_adv_report(hdev);
44275c5b93e4SJohan Hedberg 		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
4428c70a7e4cSMarcel Holtmann 				  rssi, flags, data, len, NULL, 0);
4429b9a6328fSJohan Hedberg 		return;
4430b9a6328fSJohan Hedberg 	}
4431b9a6328fSJohan Hedberg 
4432b9a6328fSJohan Hedberg 	/* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
4433b9a6328fSJohan Hedberg 	 * the new event is a SCAN_RSP. We can therefore proceed with
4434b9a6328fSJohan Hedberg 	 * sending a merged device found event.
4435b9a6328fSJohan Hedberg 	 */
4436b9a6328fSJohan Hedberg 	mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
4437c70a7e4cSMarcel Holtmann 			  d->last_adv_addr_type, NULL, rssi, d->last_adv_flags,
443842bd6a56SMarcel Holtmann 			  d->last_adv_data, d->last_adv_data_len, data, len);
4439b9a6328fSJohan Hedberg 	clear_pending_adv_report(hdev);
44404af605d8SJohan Hedberg }
44414af605d8SJohan Hedberg 
44426039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
44439aa04c91SAndre Guedes {
4444e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
4445e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
44469aa04c91SAndre Guedes 
4447a4790dbdSAndre Guedes 	hci_dev_lock(hdev);
4448a4790dbdSAndre Guedes 
4449e95beb41SAndre Guedes 	while (num_reports--) {
4450e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
44514af605d8SJohan Hedberg 		s8 rssi;
4452a4790dbdSAndre Guedes 
44533c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
44544af605d8SJohan Hedberg 		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
44554af605d8SJohan Hedberg 				   ev->bdaddr_type, rssi, ev->data, ev->length);
44563c9e9195SAndre Guedes 
4457e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
44589aa04c91SAndre Guedes 	}
4459a4790dbdSAndre Guedes 
4460a4790dbdSAndre Guedes 	hci_dev_unlock(hdev);
44619aa04c91SAndre Guedes }
44629aa04c91SAndre Guedes 
44636039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
4464a7a595f6SVinicius Costa Gomes {
4465a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
4466a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
4467bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
4468a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
4469c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
4470a7a595f6SVinicius Costa Gomes 
44719f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
4472a7a595f6SVinicius Costa Gomes 
4473a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
4474a7a595f6SVinicius Costa Gomes 
4475a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
4476bea710feSVinicius Costa Gomes 	if (conn == NULL)
4477bea710feSVinicius Costa Gomes 		goto not_found;
4478a7a595f6SVinicius Costa Gomes 
4479e804d25dSJohan Hedberg 	ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role);
4480bea710feSVinicius Costa Gomes 	if (ltk == NULL)
4481bea710feSVinicius Costa Gomes 		goto not_found;
4482bea710feSVinicius Costa Gomes 
4483bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
4484a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
4485c9839a11SVinicius Costa Gomes 
4486c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
4487f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_HIGH;
4488f8776218SAndre Guedes 	else
4489f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_MEDIUM;
4490a7a595f6SVinicius Costa Gomes 
449189cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
4492a7a595f6SVinicius Costa Gomes 
4493a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
4494a7a595f6SVinicius Costa Gomes 
44955981a882SClaudio Takahasi 	/* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a
44965981a882SClaudio Takahasi 	 * temporary key used to encrypt a connection following
44975981a882SClaudio Takahasi 	 * pairing. It is used during the Encrypted Session Setup to
44985981a882SClaudio Takahasi 	 * distribute the keys. Later, security can be re-established
44995981a882SClaudio Takahasi 	 * using a distributed LTK.
45005981a882SClaudio Takahasi 	 */
45012ceba539SJohan Hedberg 	if (ltk->type == SMP_STK) {
4502fe59a05fSJohan Hedberg 		set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
4503c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
4504c9839a11SVinicius Costa Gomes 		kfree(ltk);
4505fe59a05fSJohan Hedberg 	} else {
4506fe59a05fSJohan Hedberg 		clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
4507c9839a11SVinicius Costa Gomes 	}
4508c9839a11SVinicius Costa Gomes 
4509a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
4510bea710feSVinicius Costa Gomes 
4511bea710feSVinicius Costa Gomes 	return;
4512bea710feSVinicius Costa Gomes 
4513bea710feSVinicius Costa Gomes not_found:
4514bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
4515bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
4516bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
4517a7a595f6SVinicius Costa Gomes }
4518a7a595f6SVinicius Costa Gomes 
45198e75b46aSAndre Guedes static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
45208e75b46aSAndre Guedes 				      u8 reason)
45218e75b46aSAndre Guedes {
45228e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_neg_reply cp;
45238e75b46aSAndre Guedes 
45248e75b46aSAndre Guedes 	cp.handle = cpu_to_le16(handle);
45258e75b46aSAndre Guedes 	cp.reason = reason;
45268e75b46aSAndre Guedes 
45278e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp),
45288e75b46aSAndre Guedes 		     &cp);
45298e75b46aSAndre Guedes }
45308e75b46aSAndre Guedes 
45318e75b46aSAndre Guedes static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
45328e75b46aSAndre Guedes 					     struct sk_buff *skb)
45338e75b46aSAndre Guedes {
45348e75b46aSAndre Guedes 	struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data;
45358e75b46aSAndre Guedes 	struct hci_cp_le_conn_param_req_reply cp;
45368e75b46aSAndre Guedes 	struct hci_conn *hcon;
45378e75b46aSAndre Guedes 	u16 handle, min, max, latency, timeout;
45388e75b46aSAndre Guedes 
45398e75b46aSAndre Guedes 	handle = le16_to_cpu(ev->handle);
45408e75b46aSAndre Guedes 	min = le16_to_cpu(ev->interval_min);
45418e75b46aSAndre Guedes 	max = le16_to_cpu(ev->interval_max);
45428e75b46aSAndre Guedes 	latency = le16_to_cpu(ev->latency);
45438e75b46aSAndre Guedes 	timeout = le16_to_cpu(ev->timeout);
45448e75b46aSAndre Guedes 
45458e75b46aSAndre Guedes 	hcon = hci_conn_hash_lookup_handle(hdev, handle);
45468e75b46aSAndre Guedes 	if (!hcon || hcon->state != BT_CONNECTED)
45478e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
45488e75b46aSAndre Guedes 						 HCI_ERROR_UNKNOWN_CONN_ID);
45498e75b46aSAndre Guedes 
45508e75b46aSAndre Guedes 	if (hci_check_conn_params(min, max, latency, timeout))
45518e75b46aSAndre Guedes 		return send_conn_param_neg_reply(hdev, handle,
45528e75b46aSAndre Guedes 						 HCI_ERROR_INVALID_LL_PARAMS);
45538e75b46aSAndre Guedes 
455440bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_MASTER) {
4555348d50b8SJohan Hedberg 		struct hci_conn_params *params;
4556f4869e2aSJohan Hedberg 		u8 store_hint;
4557348d50b8SJohan Hedberg 
4558348d50b8SJohan Hedberg 		hci_dev_lock(hdev);
4559348d50b8SJohan Hedberg 
4560348d50b8SJohan Hedberg 		params = hci_conn_params_lookup(hdev, &hcon->dst,
4561348d50b8SJohan Hedberg 						hcon->dst_type);
4562348d50b8SJohan Hedberg 		if (params) {
4563348d50b8SJohan Hedberg 			params->conn_min_interval = min;
4564348d50b8SJohan Hedberg 			params->conn_max_interval = max;
4565348d50b8SJohan Hedberg 			params->conn_latency = latency;
4566348d50b8SJohan Hedberg 			params->supervision_timeout = timeout;
4567f4869e2aSJohan Hedberg 			store_hint = 0x01;
4568f4869e2aSJohan Hedberg 		} else{
4569f4869e2aSJohan Hedberg 			store_hint = 0x00;
4570348d50b8SJohan Hedberg 		}
4571348d50b8SJohan Hedberg 
4572348d50b8SJohan Hedberg 		hci_dev_unlock(hdev);
4573348d50b8SJohan Hedberg 
4574f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type,
4575f4869e2aSJohan Hedberg 				    store_hint, min, max, latency, timeout);
4576348d50b8SJohan Hedberg 	}
4577ffb5a827SAndre Guedes 
45788e75b46aSAndre Guedes 	cp.handle = ev->handle;
45798e75b46aSAndre Guedes 	cp.interval_min = ev->interval_min;
45808e75b46aSAndre Guedes 	cp.interval_max = ev->interval_max;
45818e75b46aSAndre Guedes 	cp.latency = ev->latency;
45828e75b46aSAndre Guedes 	cp.timeout = ev->timeout;
45838e75b46aSAndre Guedes 	cp.min_ce_len = 0;
45848e75b46aSAndre Guedes 	cp.max_ce_len = 0;
45858e75b46aSAndre Guedes 
45868e75b46aSAndre Guedes 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
45878e75b46aSAndre Guedes }
45888e75b46aSAndre Guedes 
45896039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
4590fcd89c09SVille Tervo {
4591fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
4592fcd89c09SVille Tervo 
4593fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
4594fcd89c09SVille Tervo 
4595fcd89c09SVille Tervo 	switch (le_ev->subevent) {
4596fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
4597fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
4598fcd89c09SVille Tervo 		break;
4599fcd89c09SVille Tervo 
46001855d92dSMarcel Holtmann 	case HCI_EV_LE_CONN_UPDATE_COMPLETE:
46011855d92dSMarcel Holtmann 		hci_le_conn_update_complete_evt(hdev, skb);
46021855d92dSMarcel Holtmann 		break;
46031855d92dSMarcel Holtmann 
46049aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
46059aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
46069aa04c91SAndre Guedes 		break;
46079aa04c91SAndre Guedes 
4608a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
4609a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
4610a7a595f6SVinicius Costa Gomes 		break;
4611a7a595f6SVinicius Costa Gomes 
46128e75b46aSAndre Guedes 	case HCI_EV_LE_REMOTE_CONN_PARAM_REQ:
46138e75b46aSAndre Guedes 		hci_le_remote_conn_param_req_evt(hdev, skb);
46148e75b46aSAndre Guedes 		break;
46158e75b46aSAndre Guedes 
4616fcd89c09SVille Tervo 	default:
4617fcd89c09SVille Tervo 		break;
4618fcd89c09SVille Tervo 	}
4619fcd89c09SVille Tervo }
4620fcd89c09SVille Tervo 
46219495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
46229495b2eeSAndrei Emeltchenko {
46239495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
46249495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
46259495b2eeSAndrei Emeltchenko 
46269495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
46279495b2eeSAndrei Emeltchenko 
46289495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
46299495b2eeSAndrei Emeltchenko 
46309495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
46319495b2eeSAndrei Emeltchenko 	if (!hcon)
46329495b2eeSAndrei Emeltchenko 		return;
46339495b2eeSAndrei Emeltchenko 
46349495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
46359495b2eeSAndrei Emeltchenko }
46369495b2eeSAndrei Emeltchenko 
46371da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
46381da177e4SLinus Torvalds {
4639a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
4640a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
46411da177e4SLinus Torvalds 
4642b6ddb638SJohan Hedberg 	hci_dev_lock(hdev);
4643b6ddb638SJohan Hedberg 
4644b6ddb638SJohan Hedberg 	/* Received events are (currently) only needed when a request is
4645b6ddb638SJohan Hedberg 	 * ongoing so avoid unnecessary memory allocation.
4646b6ddb638SJohan Hedberg 	 */
4647899de765SMarcel Holtmann 	if (hci_req_pending(hdev)) {
4648b6ddb638SJohan Hedberg 		kfree_skb(hdev->recv_evt);
4649b6ddb638SJohan Hedberg 		hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
4650b6ddb638SJohan Hedberg 	}
4651b6ddb638SJohan Hedberg 
4652b6ddb638SJohan Hedberg 	hci_dev_unlock(hdev);
4653b6ddb638SJohan Hedberg 
46541da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
46551da177e4SLinus Torvalds 
465602350a72SJohan Hedberg 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
4657c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
4658c1f23a2bSJohannes Berg 		u16 opcode = __le16_to_cpu(cmd_hdr->opcode);
465902350a72SJohan Hedberg 
466002350a72SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, 0);
466102350a72SJohan Hedberg 	}
466202350a72SJohan Hedberg 
4663a9de9248SMarcel Holtmann 	switch (event) {
46641da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
46651da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
46661da177e4SLinus Torvalds 		break;
46671da177e4SLinus Torvalds 
46681da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
46691da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
46701da177e4SLinus Torvalds 		break;
46711da177e4SLinus Torvalds 
4672a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
4673a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
467421d9e30eSMarcel Holtmann 		break;
467521d9e30eSMarcel Holtmann 
46761da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
46771da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
46781da177e4SLinus Torvalds 		break;
46791da177e4SLinus Torvalds 
46801da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
46811da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
46821da177e4SLinus Torvalds 		break;
46831da177e4SLinus Torvalds 
46841da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
46851da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
46861da177e4SLinus Torvalds 		break;
46871da177e4SLinus Torvalds 
4688a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
4689a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
4690a9de9248SMarcel Holtmann 		break;
4691a9de9248SMarcel Holtmann 
46921da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
46931da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
46941da177e4SLinus Torvalds 		break;
46951da177e4SLinus Torvalds 
4696a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
4697a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
4698a9de9248SMarcel Holtmann 		break;
4699a9de9248SMarcel Holtmann 
4700a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
4701a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
4702a9de9248SMarcel Holtmann 		break;
4703a9de9248SMarcel Holtmann 
4704a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
4705a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
4706a9de9248SMarcel Holtmann 		break;
4707a9de9248SMarcel Holtmann 
4708a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
4709a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
4710a9de9248SMarcel Holtmann 		break;
4711a9de9248SMarcel Holtmann 
4712a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
4713a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
4714a9de9248SMarcel Holtmann 		break;
4715a9de9248SMarcel Holtmann 
4716a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
4717a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
4718a9de9248SMarcel Holtmann 		break;
4719a9de9248SMarcel Holtmann 
4720a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
4721a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
47221da177e4SLinus Torvalds 		break;
47231da177e4SLinus Torvalds 
47241da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
47251da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
47261da177e4SLinus Torvalds 		break;
47271da177e4SLinus Torvalds 
47281da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
47291da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
47301da177e4SLinus Torvalds 		break;
47311da177e4SLinus Torvalds 
47321da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
47331da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
47341da177e4SLinus Torvalds 		break;
47351da177e4SLinus Torvalds 
47361da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
47371da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
47381da177e4SLinus Torvalds 		break;
47391da177e4SLinus Torvalds 
4740a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
4741a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
4742a8746417SMarcel Holtmann 		break;
4743a8746417SMarcel Holtmann 
474485a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
474585a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
474685a1e930SMarcel Holtmann 		break;
474785a1e930SMarcel Holtmann 
4748a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4749a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
4750a9de9248SMarcel Holtmann 		break;
4751a9de9248SMarcel Holtmann 
4752a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
4753a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
4754a9de9248SMarcel Holtmann 		break;
4755a9de9248SMarcel Holtmann 
4756a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
4757a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
4758a9de9248SMarcel Holtmann 		break;
4759a9de9248SMarcel Holtmann 
4760a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
4761a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
47621da177e4SLinus Torvalds 		break;
47631da177e4SLinus Torvalds 
47641c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
47651c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
47661c2e0041SJohan Hedberg 		break;
47671c2e0041SJohan Hedberg 
47680493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
47690493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
47700493684eSMarcel Holtmann 		break;
47710493684eSMarcel Holtmann 
477203b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
477303b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
477403b555e1SJohan Hedberg 		break;
477503b555e1SJohan Hedberg 
4776a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
4777a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
4778a5c29683SJohan Hedberg 		break;
4779a5c29683SJohan Hedberg 
47801143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
47811143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
47821143d458SBrian Gix 		break;
47831143d458SBrian Gix 
478492a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
478592a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
478692a25256SJohan Hedberg 		break;
478792a25256SJohan Hedberg 
478892a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
478992a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
479092a25256SJohan Hedberg 		break;
479192a25256SJohan Hedberg 
47920493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
47930493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
47940493684eSMarcel Holtmann 		break;
47950493684eSMarcel Holtmann 
479641a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
479741a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
479841a96212SMarcel Holtmann 		break;
479941a96212SMarcel Holtmann 
4800fcd89c09SVille Tervo 	case HCI_EV_LE_META:
4801fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
4802fcd89c09SVille Tervo 		break;
4803fcd89c09SVille Tervo 
48049495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
48059495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
48069495b2eeSAndrei Emeltchenko 		break;
48079495b2eeSAndrei Emeltchenko 
48082763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
48092763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
48102763eda6SSzymon Janc 		break;
48112763eda6SSzymon Janc 
4812d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
4813d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
4814d5e91192SAndrei Emeltchenko 		break;
4815d5e91192SAndrei Emeltchenko 
481627695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
481727695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
481827695fb4SAndrei Emeltchenko 		break;
481927695fb4SAndrei Emeltchenko 
4820606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4821606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
4822606e2a10SAndrei Emeltchenko 		break;
4823606e2a10SAndrei Emeltchenko 
48249eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
48259eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
48269eef6b3aSAndrei Emeltchenko 		break;
48279eef6b3aSAndrei Emeltchenko 
482825e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
482925e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
483025e89e99SAndrei Emeltchenko 		break;
483125e89e99SAndrei Emeltchenko 
48321da177e4SLinus Torvalds 	default:
48339f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
48341da177e4SLinus Torvalds 		break;
48351da177e4SLinus Torvalds 	}
48361da177e4SLinus Torvalds 
48371da177e4SLinus Torvalds 	kfree_skb(skb);
48381da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
48391da177e4SLinus Torvalds }
4840