xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 01fdb0fc)
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"
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds /* Handle HCI Event packets */
371da177e4SLinus Torvalds 
38a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
391da177e4SLinus Torvalds {
40a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
411da177e4SLinus Torvalds 
429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
431da177e4SLinus Torvalds 
4482f4785cSAndre Guedes 	if (status)
45a9de9248SMarcel Holtmann 		return;
461da177e4SLinus Torvalds 
4789352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
483e13fa1eSAndre Guedes 	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
493e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
5089352e7dSAndre Guedes 
51a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
521da177e4SLinus Torvalds }
536bd57416SMarcel Holtmann 
544d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
554d93483bSAndre Guedes {
564d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
574d93483bSAndre Guedes 
589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
59ae854a70SAndre Guedes 
60ae854a70SAndre Guedes 	if (status)
61ae854a70SAndre Guedes 		return;
62ae854a70SAndre Guedes 
63ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
644d93483bSAndre Guedes }
654d93483bSAndre Guedes 
66a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
671da177e4SLinus Torvalds {
68a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
69a9de9248SMarcel Holtmann 
709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
71a9de9248SMarcel Holtmann 
72a9de9248SMarcel Holtmann 	if (status)
73a9de9248SMarcel Holtmann 		return;
74a9de9248SMarcel Holtmann 
75ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
76ae854a70SAndre Guedes 
77a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
78a9de9248SMarcel Holtmann }
79a9de9248SMarcel Holtmann 
80807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
81807deac2SGustavo Padovan 					  struct sk_buff *skb)
82a9de9248SMarcel Holtmann {
83a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
84a9de9248SMarcel Holtmann }
85a9de9248SMarcel Holtmann 
86a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
87a9de9248SMarcel Holtmann {
88a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
891da177e4SLinus Torvalds 	struct hci_conn *conn;
901da177e4SLinus Torvalds 
919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
921da177e4SLinus Torvalds 
93a9de9248SMarcel Holtmann 	if (rp->status)
94a9de9248SMarcel Holtmann 		return;
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds 	hci_dev_lock(hdev);
971da177e4SLinus Torvalds 
98a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
991da177e4SLinus Torvalds 	if (conn) {
100a9de9248SMarcel Holtmann 		if (rp->role)
1011da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1021da177e4SLinus Torvalds 		else
1031da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1041da177e4SLinus Torvalds 	}
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
107a9de9248SMarcel Holtmann }
1081da177e4SLinus Torvalds 
109e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
110e4e8e37cSMarcel Holtmann {
111e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
112e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
113e4e8e37cSMarcel Holtmann 
1149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
115e4e8e37cSMarcel Holtmann 
116e4e8e37cSMarcel Holtmann 	if (rp->status)
117e4e8e37cSMarcel Holtmann 		return;
118e4e8e37cSMarcel Holtmann 
119e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
120e4e8e37cSMarcel Holtmann 
121e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
122e4e8e37cSMarcel Holtmann 	if (conn)
123e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
124e4e8e37cSMarcel Holtmann 
125e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
126e4e8e37cSMarcel Holtmann }
127e4e8e37cSMarcel Holtmann 
128a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
129a9de9248SMarcel Holtmann {
130a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
131a9de9248SMarcel Holtmann 	struct hci_conn *conn;
132a9de9248SMarcel Holtmann 	void *sent;
133a9de9248SMarcel Holtmann 
1349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
135a9de9248SMarcel Holtmann 
136a9de9248SMarcel Holtmann 	if (rp->status)
137a9de9248SMarcel Holtmann 		return;
138a9de9248SMarcel Holtmann 
139a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14004837f64SMarcel Holtmann 	if (!sent)
141a9de9248SMarcel Holtmann 		return;
14204837f64SMarcel Holtmann 
14304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14404837f64SMarcel Holtmann 
145a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
146e4e8e37cSMarcel Holtmann 	if (conn)
14783985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
14804837f64SMarcel Holtmann 
14904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1501da177e4SLinus Torvalds }
1511da177e4SLinus Torvalds 
152807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
153807deac2SGustavo Padovan 					struct sk_buff *skb)
154e4e8e37cSMarcel Holtmann {
155e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
156e4e8e37cSMarcel Holtmann 
1579f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
158e4e8e37cSMarcel Holtmann 
159e4e8e37cSMarcel Holtmann 	if (rp->status)
160e4e8e37cSMarcel Holtmann 		return;
161e4e8e37cSMarcel Holtmann 
162e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
163e4e8e37cSMarcel Holtmann }
164e4e8e37cSMarcel Holtmann 
165807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
166807deac2SGustavo Padovan 					 struct sk_buff *skb)
167e4e8e37cSMarcel Holtmann {
168e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
169e4e8e37cSMarcel Holtmann 	void *sent;
170e4e8e37cSMarcel Holtmann 
1719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
172e4e8e37cSMarcel Holtmann 
173e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
174e4e8e37cSMarcel Holtmann 	if (!sent)
175e4e8e37cSMarcel Holtmann 		return;
176e4e8e37cSMarcel Holtmann 
177e4e8e37cSMarcel Holtmann 	if (!status)
178e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
179e4e8e37cSMarcel Holtmann }
180e4e8e37cSMarcel Holtmann 
181a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1821da177e4SLinus Torvalds {
183a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
184a9de9248SMarcel Holtmann 
1859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
186a9de9248SMarcel Holtmann 
18710572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
18810572132SGustavo F. Padovan 
189a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
1902cc6fb00SJohan Hedberg 	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
19169775ff6SAndre Guedes 
19269775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
193bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
194bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
1953f0f524bSJohan Hedberg 
1963f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
1973f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
198f8e808bdSMarcel Holtmann 
199f8e808bdSMarcel Holtmann 	memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data));
200f8e808bdSMarcel Holtmann 	hdev->scan_rsp_data_len = 0;
20106f5b778SMarcel Holtmann 
20206f5b778SMarcel Holtmann 	hdev->ssp_debug_mode = 0;
203a9de9248SMarcel Holtmann }
204a9de9248SMarcel Holtmann 
205a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
206a9de9248SMarcel Holtmann {
207a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2081da177e4SLinus Torvalds 	void *sent;
2091da177e4SLinus Torvalds 
2109f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2111da177e4SLinus Torvalds 
212a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2131da177e4SLinus Torvalds 	if (!sent)
214a9de9248SMarcel Holtmann 		return;
2151da177e4SLinus Torvalds 
21656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21756e5cb86SJohan Hedberg 
218f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
219f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
22028cc7bdeSJohan Hedberg 	else if (!status)
22128cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
222f51d5b24SJohan Hedberg 
22356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
224a9de9248SMarcel Holtmann }
225a9de9248SMarcel Holtmann 
226a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
227a9de9248SMarcel Holtmann {
228a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
229a9de9248SMarcel Holtmann 
2309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
231a9de9248SMarcel Holtmann 
232a9de9248SMarcel Holtmann 	if (rp->status)
233a9de9248SMarcel Holtmann 		return;
234a9de9248SMarcel Holtmann 
235db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2361f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
237a9de9248SMarcel Holtmann }
238a9de9248SMarcel Holtmann 
239a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
240a9de9248SMarcel Holtmann {
241a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
242a9de9248SMarcel Holtmann 	void *sent;
243a9de9248SMarcel Holtmann 
2449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
245a9de9248SMarcel Holtmann 
246a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
247a9de9248SMarcel Holtmann 	if (!sent)
248a9de9248SMarcel Holtmann 		return;
2491da177e4SLinus Torvalds 
2501da177e4SLinus Torvalds 	if (!status) {
251a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
252a9de9248SMarcel Holtmann 
2531da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2541da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2551da177e4SLinus Torvalds 		else
2561da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2571da177e4SLinus Torvalds 	}
258a9de9248SMarcel Holtmann 
25933ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
26033ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
261a9de9248SMarcel Holtmann }
2621da177e4SLinus Torvalds 
263a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
264a9de9248SMarcel Holtmann {
265a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
266a9de9248SMarcel Holtmann 	void *sent;
267a9de9248SMarcel Holtmann 
2689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
269a9de9248SMarcel Holtmann 
270a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2711da177e4SLinus Torvalds 	if (!sent)
272a9de9248SMarcel Holtmann 		return;
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 	if (!status) {
275a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
276a9de9248SMarcel Holtmann 
2771da177e4SLinus Torvalds 		if (param)
2781da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2791da177e4SLinus Torvalds 		else
2801da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2811da177e4SLinus Torvalds 	}
2821da177e4SLinus Torvalds }
2831da177e4SLinus Torvalds 
284a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
285a9de9248SMarcel Holtmann {
28636f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28736f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
288a9de9248SMarcel Holtmann 	void *sent;
2891da177e4SLinus Torvalds 
2909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
291a9de9248SMarcel Holtmann 
292a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2931da177e4SLinus Torvalds 	if (!sent)
294a9de9248SMarcel Holtmann 		return;
2951da177e4SLinus Torvalds 
29636f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
297a9de9248SMarcel Holtmann 
29856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29956e5cb86SJohan Hedberg 
300fa1bd918SMikel Astiz 	if (status) {
301744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3022d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3032d7cee58SJohan Hedberg 		goto done;
3042d7cee58SJohan Hedberg 	}
3052d7cee58SJohan Hedberg 
3060663ca2aSJohan Hedberg 	/* We need to ensure that we set this back on if someone changed
3070663ca2aSJohan Hedberg 	 * the scan mode through a raw HCI socket.
3080663ca2aSJohan Hedberg 	 */
3090663ca2aSJohan Hedberg 	set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
3100663ca2aSJohan Hedberg 
3119fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3129fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
313a9de9248SMarcel Holtmann 
31473f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3151da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3169fbcbb45SJohan Hedberg 		if (!old_iscan)
317744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
3189fbcbb45SJohan Hedberg 	} else if (old_iscan)
319744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3201da177e4SLinus Torvalds 
3219fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3221da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3239fbcbb45SJohan Hedberg 		if (!old_pscan)
324744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3259fbcbb45SJohan Hedberg 	} else if (old_pscan)
326744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
327a9de9248SMarcel Holtmann 
32836f7fc7eSJohan Hedberg done:
32956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
332a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
333a9de9248SMarcel Holtmann {
334a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
335a9de9248SMarcel Holtmann 
3369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
337a9de9248SMarcel Holtmann 
338a9de9248SMarcel Holtmann 	if (rp->status)
339a9de9248SMarcel Holtmann 		return;
340a9de9248SMarcel Holtmann 
341a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
344a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
345a9de9248SMarcel Holtmann }
346a9de9248SMarcel Holtmann 
347a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
348a9de9248SMarcel Holtmann {
349a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
350a9de9248SMarcel Holtmann 	void *sent;
351a9de9248SMarcel Holtmann 
3529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
353a9de9248SMarcel Holtmann 
354a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
355a9de9248SMarcel Holtmann 	if (!sent)
356a9de9248SMarcel Holtmann 		return;
357a9de9248SMarcel Holtmann 
3587f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3597f9a903cSMarcel Holtmann 
3607f9a903cSMarcel Holtmann 	if (status == 0)
361a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3627f9a903cSMarcel Holtmann 
3637f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3647f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3657f9a903cSMarcel Holtmann 
3667f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
367a9de9248SMarcel Holtmann }
368a9de9248SMarcel Holtmann 
369a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
370a9de9248SMarcel Holtmann {
371a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
372a9de9248SMarcel Holtmann 	__u16 setting;
373a9de9248SMarcel Holtmann 
3749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
375a9de9248SMarcel Holtmann 
376a9de9248SMarcel Holtmann 	if (rp->status)
377a9de9248SMarcel Holtmann 		return;
378a9de9248SMarcel Holtmann 
379a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
380a9de9248SMarcel Holtmann 
381a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
382a9de9248SMarcel Holtmann 		return;
383a9de9248SMarcel Holtmann 
384a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
385a9de9248SMarcel Holtmann 
3869f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
387a9de9248SMarcel Holtmann 
3883c54711cSGustavo F. Padovan 	if (hdev->notify)
389a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
390a9de9248SMarcel Holtmann }
391a9de9248SMarcel Holtmann 
3928fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
3938fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
394a9de9248SMarcel Holtmann {
395a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
396f383f275SMarcel Holtmann 	__u16 setting;
397a9de9248SMarcel Holtmann 	void *sent;
398a9de9248SMarcel Holtmann 
3999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
400a9de9248SMarcel Holtmann 
401f383f275SMarcel Holtmann 	if (status)
402f383f275SMarcel Holtmann 		return;
403f383f275SMarcel Holtmann 
404a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
405a9de9248SMarcel Holtmann 	if (!sent)
406a9de9248SMarcel Holtmann 		return;
407a9de9248SMarcel Holtmann 
408f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4091da177e4SLinus Torvalds 
410f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
411f383f275SMarcel Holtmann 		return;
412f383f275SMarcel Holtmann 
4131da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4141da177e4SLinus Torvalds 
4159f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4161da177e4SLinus Torvalds 
4173c54711cSGustavo F. Padovan 	if (hdev->notify)
4181da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4191da177e4SLinus Torvalds }
4201da177e4SLinus Torvalds 
421b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev,
422b4cb9fb2SMarcel Holtmann 					  struct sk_buff *skb)
423b4cb9fb2SMarcel Holtmann {
424b4cb9fb2SMarcel Holtmann 	struct hci_rp_read_num_supported_iac *rp = (void *) skb->data;
425b4cb9fb2SMarcel Holtmann 
426b4cb9fb2SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
427b4cb9fb2SMarcel Holtmann 
428b4cb9fb2SMarcel Holtmann 	if (rp->status)
429b4cb9fb2SMarcel Holtmann 		return;
430b4cb9fb2SMarcel Holtmann 
431b4cb9fb2SMarcel Holtmann 	hdev->num_iac = rp->num_iac;
432b4cb9fb2SMarcel Holtmann 
433b4cb9fb2SMarcel Holtmann 	BT_DBG("%s num iac %d", hdev->name, hdev->num_iac);
434b4cb9fb2SMarcel Holtmann }
435b4cb9fb2SMarcel Holtmann 
436333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
437333140b5SMarcel Holtmann {
438333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4395ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
440333140b5SMarcel Holtmann 
4419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
442333140b5SMarcel Holtmann 
443333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
444333140b5SMarcel Holtmann 	if (!sent)
445333140b5SMarcel Holtmann 		return;
446333140b5SMarcel Holtmann 
4475ed8eb2fSJohan Hedberg 	if (!status) {
4485ed8eb2fSJohan Hedberg 		if (sent->mode)
449cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_SSP;
4505ed8eb2fSJohan Hedberg 		else
451cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_SSP;
4525ed8eb2fSJohan Hedberg 	}
4535ed8eb2fSJohan Hedberg 
454c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4555ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
456c0ecddc2SJohan Hedberg 	else if (!status) {
4575ed8eb2fSJohan Hedberg 		if (sent->mode)
45884bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
45984bde9d6SJohan Hedberg 		else
46084bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
461c0ecddc2SJohan Hedberg 	}
462333140b5SMarcel Holtmann }
463333140b5SMarcel Holtmann 
464eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
465eac83dc6SMarcel Holtmann {
466eac83dc6SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
467eac83dc6SMarcel Holtmann 	struct hci_cp_write_sc_support *sent;
468eac83dc6SMarcel Holtmann 
469eac83dc6SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
470eac83dc6SMarcel Holtmann 
471eac83dc6SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
472eac83dc6SMarcel Holtmann 	if (!sent)
473eac83dc6SMarcel Holtmann 		return;
474eac83dc6SMarcel Holtmann 
475eac83dc6SMarcel Holtmann 	if (!status) {
476eac83dc6SMarcel Holtmann 		if (sent->support)
477eac83dc6SMarcel Holtmann 			hdev->features[1][0] |= LMP_HOST_SC;
478eac83dc6SMarcel Holtmann 		else
479eac83dc6SMarcel Holtmann 			hdev->features[1][0] &= ~LMP_HOST_SC;
480eac83dc6SMarcel Holtmann 	}
481eac83dc6SMarcel Holtmann 
482eac83dc6SMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
483eac83dc6SMarcel Holtmann 		mgmt_sc_enable_complete(hdev, sent->support, status);
484eac83dc6SMarcel Holtmann 	else if (!status) {
485eac83dc6SMarcel Holtmann 		if (sent->support)
486eac83dc6SMarcel Holtmann 			set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
487eac83dc6SMarcel Holtmann 		else
488eac83dc6SMarcel Holtmann 			clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
489eac83dc6SMarcel Holtmann 	}
490eac83dc6SMarcel Holtmann }
491eac83dc6SMarcel Holtmann 
492a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
493a9de9248SMarcel Holtmann {
494a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
4951143e5a6SMarcel Holtmann 
4969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
4971143e5a6SMarcel Holtmann 
498a9de9248SMarcel Holtmann 	if (rp->status)
49942c6b129SJohan Hedberg 		return;
5001143e5a6SMarcel Holtmann 
5010d5551f5SMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
502a9de9248SMarcel Holtmann 		hdev->hci_ver = rp->hci_ver;
503e4e8e37cSMarcel Holtmann 		hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
504d5859e22SJohan Hedberg 		hdev->lmp_ver = rp->lmp_ver;
505e4e8e37cSMarcel Holtmann 		hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
506d5859e22SJohan Hedberg 		hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5070d5551f5SMarcel Holtmann 	}
508d5859e22SJohan Hedberg }
509d5859e22SJohan Hedberg 
5108fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
5118fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
512a9de9248SMarcel Holtmann {
513a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
514a9de9248SMarcel Holtmann 
5159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
516a9de9248SMarcel Holtmann 
5176a070e6eSMarcel Holtmann 	if (rp->status)
5186a070e6eSMarcel Holtmann 		return;
5196a070e6eSMarcel Holtmann 
5206a070e6eSMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
521a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
522a9de9248SMarcel Holtmann }
523a9de9248SMarcel Holtmann 
5248fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
5258fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
526a9de9248SMarcel Holtmann {
527a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
528a9de9248SMarcel Holtmann 
5299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
530a9de9248SMarcel Holtmann 
531a9de9248SMarcel Holtmann 	if (rp->status)
532a9de9248SMarcel Holtmann 		return;
533a9de9248SMarcel Holtmann 
534a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
5351da177e4SLinus Torvalds 
5361da177e4SLinus Torvalds 	/* Adjust default settings according to features
5371da177e4SLinus Torvalds 	 * supported by device. */
538a9de9248SMarcel Holtmann 
539cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_3SLOT)
5401da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
5411da177e4SLinus Torvalds 
542cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_5SLOT)
5431da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
5441da177e4SLinus Torvalds 
545cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV2) {
5461da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
5475b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
5485b7f9909SMarcel Holtmann 	}
5491da177e4SLinus Torvalds 
550cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV3) {
5511da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
5525b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
5535b7f9909SMarcel Holtmann 	}
5545b7f9909SMarcel Holtmann 
55545db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
5565b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
5575b7f9909SMarcel Holtmann 
558cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV4)
5595b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
5605b7f9909SMarcel Holtmann 
561cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV5)
5625b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
5631da177e4SLinus Torvalds 
564cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
565efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
566efc7688bSMarcel Holtmann 
567cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
568efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
569efc7688bSMarcel Holtmann 
570cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
571efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
5721da177e4SLinus Torvalds }
5731da177e4SLinus Torvalds 
574971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
575971e3a4bSAndre Guedes 					   struct sk_buff *skb)
576971e3a4bSAndre Guedes {
577971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
578971e3a4bSAndre Guedes 
5799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
580971e3a4bSAndre Guedes 
581971e3a4bSAndre Guedes 	if (rp->status)
58242c6b129SJohan Hedberg 		return;
583971e3a4bSAndre Guedes 
58457af75a8SMarcel Holtmann 	if (hdev->max_page < rp->max_page)
585d2c5d77fSJohan Hedberg 		hdev->max_page = rp->max_page;
586d2c5d77fSJohan Hedberg 
587cad718edSJohan Hedberg 	if (rp->page < HCI_MAX_PAGES)
588cad718edSJohan Hedberg 		memcpy(hdev->features[rp->page], rp->features, 8);
589971e3a4bSAndre Guedes }
590971e3a4bSAndre Guedes 
5911e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
5921e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
5931e89cffbSAndrei Emeltchenko {
5941e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
5951e89cffbSAndrei Emeltchenko 
5969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5971e89cffbSAndrei Emeltchenko 
59842c6b129SJohan Hedberg 	if (!rp->status)
5991e89cffbSAndrei Emeltchenko 		hdev->flow_ctl_mode = rp->mode;
6001e89cffbSAndrei Emeltchenko }
6011e89cffbSAndrei Emeltchenko 
602a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
603a9de9248SMarcel Holtmann {
604a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
605a9de9248SMarcel Holtmann 
6069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
607a9de9248SMarcel Holtmann 
608a9de9248SMarcel Holtmann 	if (rp->status)
609a9de9248SMarcel Holtmann 		return;
610a9de9248SMarcel Holtmann 
611a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
612a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
613a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
614a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
615da1f5198SMarcel Holtmann 
616da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
617da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
618da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
619da1f5198SMarcel Holtmann 	}
620da1f5198SMarcel Holtmann 
621da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
622da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
6231da177e4SLinus Torvalds 
624807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
625807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
6261da177e4SLinus Torvalds }
6271da177e4SLinus Torvalds 
628a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
629a9de9248SMarcel Holtmann {
630a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6311da177e4SLinus Torvalds 
6329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
633a9de9248SMarcel Holtmann 
634a9de9248SMarcel Holtmann 	if (!rp->status)
635a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
63623bb5763SJohan Hedberg }
63723bb5763SJohan Hedberg 
638f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
639f332ec66SJohan Hedberg 					   struct sk_buff *skb)
640f332ec66SJohan Hedberg {
641f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
642f332ec66SJohan Hedberg 
643f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
644f332ec66SJohan Hedberg 
645f332ec66SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) {
646f332ec66SJohan Hedberg 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
647f332ec66SJohan Hedberg 		hdev->page_scan_window = __le16_to_cpu(rp->window);
648f332ec66SJohan Hedberg 	}
649f332ec66SJohan Hedberg }
650f332ec66SJohan Hedberg 
6514a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
6524a3ee763SJohan Hedberg 					    struct sk_buff *skb)
6534a3ee763SJohan Hedberg {
6544a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6554a3ee763SJohan Hedberg 	struct hci_cp_write_page_scan_activity *sent;
6564a3ee763SJohan Hedberg 
6574a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6584a3ee763SJohan Hedberg 
6594a3ee763SJohan Hedberg 	if (status)
6604a3ee763SJohan Hedberg 		return;
6614a3ee763SJohan Hedberg 
6624a3ee763SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
6634a3ee763SJohan Hedberg 	if (!sent)
6644a3ee763SJohan Hedberg 		return;
6654a3ee763SJohan Hedberg 
6664a3ee763SJohan Hedberg 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
6674a3ee763SJohan Hedberg 	hdev->page_scan_window = __le16_to_cpu(sent->window);
6684a3ee763SJohan Hedberg }
6694a3ee763SJohan Hedberg 
670f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
671f332ec66SJohan Hedberg 					   struct sk_buff *skb)
672f332ec66SJohan Hedberg {
673f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
674f332ec66SJohan Hedberg 
675f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
676f332ec66SJohan Hedberg 
677f332ec66SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status)
678f332ec66SJohan Hedberg 		hdev->page_scan_type = rp->type;
679f332ec66SJohan Hedberg }
680f332ec66SJohan Hedberg 
6814a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
6824a3ee763SJohan Hedberg 					struct sk_buff *skb)
6834a3ee763SJohan Hedberg {
6844a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6854a3ee763SJohan Hedberg 	u8 *type;
6864a3ee763SJohan Hedberg 
6874a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6884a3ee763SJohan Hedberg 
6894a3ee763SJohan Hedberg 	if (status)
6904a3ee763SJohan Hedberg 		return;
6914a3ee763SJohan Hedberg 
6924a3ee763SJohan Hedberg 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
6934a3ee763SJohan Hedberg 	if (type)
6944a3ee763SJohan Hedberg 		hdev->page_scan_type = *type;
6954a3ee763SJohan Hedberg }
6964a3ee763SJohan Hedberg 
697350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
698350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
699350ee4cfSAndrei Emeltchenko {
700350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
701350ee4cfSAndrei Emeltchenko 
7029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
703350ee4cfSAndrei Emeltchenko 
704350ee4cfSAndrei Emeltchenko 	if (rp->status)
705350ee4cfSAndrei Emeltchenko 		return;
706350ee4cfSAndrei Emeltchenko 
707350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
708350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
709350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
710350ee4cfSAndrei Emeltchenko 
711350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
712350ee4cfSAndrei Emeltchenko 
713350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
714350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
715350ee4cfSAndrei Emeltchenko }
716350ee4cfSAndrei Emeltchenko 
717928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
718928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
719928abaa7SAndrei Emeltchenko {
720928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
721928abaa7SAndrei Emeltchenko 
7229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
723928abaa7SAndrei Emeltchenko 
724928abaa7SAndrei Emeltchenko 	if (rp->status)
7258e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
726928abaa7SAndrei Emeltchenko 
727928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
728928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
729928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
730928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
731928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
732928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
733928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
734928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
735928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
736928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
737928abaa7SAndrei Emeltchenko 
7388e2a0d92SAndrei Emeltchenko a2mp_rsp:
7398e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
740928abaa7SAndrei Emeltchenko }
741928abaa7SAndrei Emeltchenko 
742903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
743903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
744903e4541SAndrei Emeltchenko {
745903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
746903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
747903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
748903e4541SAndrei Emeltchenko 
749903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
750903e4541SAndrei Emeltchenko 
751903e4541SAndrei Emeltchenko 	if (rp->status)
752903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
753903e4541SAndrei Emeltchenko 
754903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
755903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
756903e4541SAndrei Emeltchenko 
757903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
7582e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
759903e4541SAndrei Emeltchenko 
760903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
761903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
762903e4541SAndrei Emeltchenko 
763903e4541SAndrei Emeltchenko 		/* Read other fragments */
764903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
765903e4541SAndrei Emeltchenko 
766903e4541SAndrei Emeltchenko 		return;
767903e4541SAndrei Emeltchenko 	}
768903e4541SAndrei Emeltchenko 
769903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
770903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
771903e4541SAndrei Emeltchenko 	assoc->offset = 0;
772903e4541SAndrei Emeltchenko 
773903e4541SAndrei Emeltchenko a2mp_rsp:
774903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
775903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
7769495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
777903e4541SAndrei Emeltchenko }
778903e4541SAndrei Emeltchenko 
779d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
780d5859e22SJohan Hedberg 					 struct sk_buff *skb)
781d5859e22SJohan Hedberg {
78291c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
783d5859e22SJohan Hedberg 
7849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
785d5859e22SJohan Hedberg 
78691c4e9b1SMarcel Holtmann 	if (!rp->status)
78791c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
788d5859e22SJohan Hedberg }
789d5859e22SJohan Hedberg 
790980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
791980e1a53SJohan Hedberg {
792980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
793980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
794980e1a53SJohan Hedberg 	struct hci_conn *conn;
795980e1a53SJohan Hedberg 
7969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
797980e1a53SJohan Hedberg 
79856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
79956e5cb86SJohan Hedberg 
800a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
801744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
802980e1a53SJohan Hedberg 
803fa1bd918SMikel Astiz 	if (rp->status)
80456e5cb86SJohan Hedberg 		goto unlock;
805980e1a53SJohan Hedberg 
806980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
807980e1a53SJohan Hedberg 	if (!cp)
80856e5cb86SJohan Hedberg 		goto unlock;
809980e1a53SJohan Hedberg 
810980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
811980e1a53SJohan Hedberg 	if (conn)
812980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
81356e5cb86SJohan Hedberg 
81456e5cb86SJohan Hedberg unlock:
81556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
816980e1a53SJohan Hedberg }
817980e1a53SJohan Hedberg 
818980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
819980e1a53SJohan Hedberg {
820980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
821980e1a53SJohan Hedberg 
8229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
823980e1a53SJohan Hedberg 
82456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
82556e5cb86SJohan Hedberg 
826a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
827744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
828980e1a53SJohan Hedberg 						 rp->status);
82956e5cb86SJohan Hedberg 
83056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
831980e1a53SJohan Hedberg }
83256e5cb86SJohan Hedberg 
8336ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8346ed58ec5SVille Tervo 				       struct sk_buff *skb)
8356ed58ec5SVille Tervo {
8366ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
8376ed58ec5SVille Tervo 
8389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8396ed58ec5SVille Tervo 
8406ed58ec5SVille Tervo 	if (rp->status)
8416ed58ec5SVille Tervo 		return;
8426ed58ec5SVille Tervo 
8436ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
8446ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8456ed58ec5SVille Tervo 
8466ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8476ed58ec5SVille Tervo 
8486ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8496ed58ec5SVille Tervo }
850980e1a53SJohan Hedberg 
85160e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
85260e77321SJohan Hedberg 					  struct sk_buff *skb)
85360e77321SJohan Hedberg {
85460e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
85560e77321SJohan Hedberg 
85660e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
85760e77321SJohan Hedberg 
85860e77321SJohan Hedberg 	if (!rp->status)
85960e77321SJohan Hedberg 		memcpy(hdev->le_features, rp->features, 8);
86060e77321SJohan Hedberg }
86160e77321SJohan Hedberg 
8628fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
8638fa19098SJohan Hedberg 					struct sk_buff *skb)
8648fa19098SJohan Hedberg {
8658fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
8668fa19098SJohan Hedberg 
8678fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8688fa19098SJohan Hedberg 
86904b4edcbSJohan Hedberg 	if (!rp->status)
8708fa19098SJohan Hedberg 		hdev->adv_tx_power = rp->tx_power;
8718fa19098SJohan Hedberg }
8728fa19098SJohan Hedberg 
873a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
874a5c29683SJohan Hedberg {
875a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
876a5c29683SJohan Hedberg 
8779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
878a5c29683SJohan Hedberg 
87956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
88056e5cb86SJohan Hedberg 
881a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
88204124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
88304124681SGustavo F. Padovan 						 rp->status);
88456e5cb86SJohan Hedberg 
88556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
886a5c29683SJohan Hedberg }
887a5c29683SJohan Hedberg 
888a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
889a5c29683SJohan Hedberg 					  struct sk_buff *skb)
890a5c29683SJohan Hedberg {
891a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
892a5c29683SJohan Hedberg 
8939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
894a5c29683SJohan Hedberg 
89556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
89656e5cb86SJohan Hedberg 
897a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
898744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
89904124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
90056e5cb86SJohan Hedberg 
90156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
902a5c29683SJohan Hedberg }
903a5c29683SJohan Hedberg 
9041143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9051143d458SBrian Gix {
9061143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9071143d458SBrian Gix 
9089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9091143d458SBrian Gix 
9101143d458SBrian Gix 	hci_dev_lock(hdev);
9111143d458SBrian Gix 
912a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
913272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
914272d90dfSJohan Hedberg 						 0, rp->status);
9151143d458SBrian Gix 
9161143d458SBrian Gix 	hci_dev_unlock(hdev);
9171143d458SBrian Gix }
9181143d458SBrian Gix 
9191143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9201143d458SBrian Gix 					  struct sk_buff *skb)
9211143d458SBrian Gix {
9221143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9231143d458SBrian Gix 
9249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9251143d458SBrian Gix 
9261143d458SBrian Gix 	hci_dev_lock(hdev);
9271143d458SBrian Gix 
928a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9291143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
93004124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
9311143d458SBrian Gix 
9321143d458SBrian Gix 	hci_dev_unlock(hdev);
9331143d458SBrian Gix }
9341143d458SBrian Gix 
9354d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
936c35938b2SSzymon Janc 				       struct sk_buff *skb)
937c35938b2SSzymon Janc {
938c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
939c35938b2SSzymon Janc 
9409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
941c35938b2SSzymon Janc 
94256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
9434d2d2796SMarcel Holtmann 	mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer,
9444d2d2796SMarcel Holtmann 					  NULL, NULL, rp->status);
9454d2d2796SMarcel Holtmann 	hci_dev_unlock(hdev);
9464d2d2796SMarcel Holtmann }
9474d2d2796SMarcel Holtmann 
9484d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
9494d2d2796SMarcel Holtmann 					   struct sk_buff *skb)
9504d2d2796SMarcel Holtmann {
9514d2d2796SMarcel Holtmann 	struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
9524d2d2796SMarcel Holtmann 
9534d2d2796SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9544d2d2796SMarcel Holtmann 
9554d2d2796SMarcel Holtmann 	hci_dev_lock(hdev);
9564d2d2796SMarcel Holtmann 	mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192,
9574d2d2796SMarcel Holtmann 					  rp->hash256, rp->randomizer256,
9584d2d2796SMarcel Holtmann 					  rp->status);
95956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
960c35938b2SSzymon Janc }
961c35938b2SSzymon Janc 
962c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
963c1d5dc4aSJohan Hedberg {
964c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
965c1d5dc4aSJohan Hedberg 
966c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
967c1d5dc4aSJohan Hedberg 
968c1d5dc4aSJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
969c1d5dc4aSJohan Hedberg 	if (!sent)
970c1d5dc4aSJohan Hedberg 		return;
971c1d5dc4aSJohan Hedberg 
972c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
973c1d5dc4aSJohan Hedberg 
974c1d5dc4aSJohan Hedberg 	if (!status) {
975c1d5dc4aSJohan Hedberg 		if (*sent)
976f3d3444aSJohan Hedberg 			set_bit(HCI_ADVERTISING, &hdev->dev_flags);
977c1d5dc4aSJohan Hedberg 		else
978f3d3444aSJohan Hedberg 			clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
979c1d5dc4aSJohan Hedberg 	}
980c1d5dc4aSJohan Hedberg 
98104b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
982c1d5dc4aSJohan Hedberg }
983c1d5dc4aSJohan Hedberg 
984eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
985eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
986eb9d91f5SAndre Guedes {
987eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
988eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
989eb9d91f5SAndre Guedes 
9909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
991eb9d91f5SAndre Guedes 
992eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
993eb9d91f5SAndre Guedes 	if (!cp)
994eb9d91f5SAndre Guedes 		return;
995eb9d91f5SAndre Guedes 
996fef5234aSAndre Guedes 	if (status)
9977ba8b4beSAndre Guedes 		return;
9987ba8b4beSAndre Guedes 
9993fd319b8SAndre Guedes 	switch (cp->enable) {
10003fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
1001d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
100268a8aea4SAndrei Emeltchenko 		break;
100368a8aea4SAndrei Emeltchenko 
100476a388beSAndre Guedes 	case LE_SCAN_DISABLE:
1005d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
100668a8aea4SAndrei Emeltchenko 		break;
100768a8aea4SAndrei Emeltchenko 
100868a8aea4SAndrei Emeltchenko 	default:
100968a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
101068a8aea4SAndrei Emeltchenko 		break;
101135815085SAndre Guedes 	}
1012eb9d91f5SAndre Guedes }
1013eb9d91f5SAndre Guedes 
1014cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1015cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
1016cf1d081fSJohan Hedberg {
1017cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1018cf1d081fSJohan Hedberg 
1019cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1020cf1d081fSJohan Hedberg 
1021cf1d081fSJohan Hedberg 	if (!rp->status)
1022cf1d081fSJohan Hedberg 		hdev->le_white_list_size = rp->size;
1023cf1d081fSJohan Hedberg }
1024cf1d081fSJohan Hedberg 
10259b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
10269b008c04SJohan Hedberg 					    struct sk_buff *skb)
10279b008c04SJohan Hedberg {
10289b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
10299b008c04SJohan Hedberg 
10309b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10319b008c04SJohan Hedberg 
10329b008c04SJohan Hedberg 	if (!rp->status)
10339b008c04SJohan Hedberg 		memcpy(hdev->le_states, rp->le_states, 8);
10349b008c04SJohan Hedberg }
10359b008c04SJohan Hedberg 
10366039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1037f9b49306SAndre Guedes 					   struct sk_buff *skb)
1038f9b49306SAndre Guedes {
103906199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1040f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1041f9b49306SAndre Guedes 
10429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1043f9b49306SAndre Guedes 
104406199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
10458f984dfaSJohan Hedberg 	if (!sent)
1046f9b49306SAndre Guedes 		return;
1047f9b49306SAndre Guedes 
10488f984dfaSJohan Hedberg 	if (!status) {
1049416a4ae5SJohan Hedberg 		if (sent->le) {
1050cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE;
1051416a4ae5SJohan Hedberg 			set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1052416a4ae5SJohan Hedberg 		} else {
1053cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE;
1054416a4ae5SJohan Hedberg 			clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1055f3d3444aSJohan Hedberg 			clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1056416a4ae5SJohan Hedberg 		}
105753b2caabSJohan Hedberg 
105853b2caabSJohan Hedberg 		if (sent->simul)
1059cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE_BREDR;
106053b2caabSJohan Hedberg 		else
1061cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
10628f984dfaSJohan Hedberg 	}
1063f9b49306SAndre Guedes }
1064f9b49306SAndre Guedes 
106593c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
106693c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
106793c284eeSAndrei Emeltchenko {
106893c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
106993c284eeSAndrei Emeltchenko 
107093c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
107193c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
107293c284eeSAndrei Emeltchenko 
107393c284eeSAndrei Emeltchenko 	if (rp->status)
107493c284eeSAndrei Emeltchenko 		return;
107593c284eeSAndrei Emeltchenko 
107693c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
107793c284eeSAndrei Emeltchenko }
107893c284eeSAndrei Emeltchenko 
10796039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1080a9de9248SMarcel Holtmann {
10819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1082a9de9248SMarcel Holtmann 
1083a9de9248SMarcel Holtmann 	if (status) {
1084a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1085314b2381SJohan Hedberg 		return;
1086314b2381SJohan Hedberg 	}
1087314b2381SJohan Hedberg 
108889352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1089a9de9248SMarcel Holtmann }
1090a9de9248SMarcel Holtmann 
10916039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
10921da177e4SLinus Torvalds {
1093a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
10941da177e4SLinus Torvalds 	struct hci_conn *conn;
10951da177e4SLinus Torvalds 
10969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1097a9de9248SMarcel Holtmann 
1098a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
10991da177e4SLinus Torvalds 	if (!cp)
11001da177e4SLinus Torvalds 		return;
11011da177e4SLinus Torvalds 
11021da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11031da177e4SLinus Torvalds 
11041da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11051da177e4SLinus Torvalds 
11066ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
11071da177e4SLinus Torvalds 
11081da177e4SLinus Torvalds 	if (status) {
11091da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11104c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11111da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11121da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11131da177e4SLinus Torvalds 				hci_conn_del(conn);
11144c67bc74SMarcel Holtmann 			} else
11154c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11161da177e4SLinus Torvalds 		}
11171da177e4SLinus Torvalds 	} else {
11181da177e4SLinus Torvalds 		if (!conn) {
11191da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11201da177e4SLinus Torvalds 			if (conn) {
1121a0c808b3SJohan Hedberg 				conn->out = true;
11221da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11231da177e4SLinus Torvalds 			} else
1124893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11251da177e4SLinus Torvalds 		}
11261da177e4SLinus Torvalds 	}
11271da177e4SLinus Torvalds 
11281da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11291da177e4SLinus Torvalds }
11301da177e4SLinus Torvalds 
1131a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11321da177e4SLinus Torvalds {
1133a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11341da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11351da177e4SLinus Torvalds 	__u16 handle;
11361da177e4SLinus Torvalds 
11379f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1138b6a0dc82SMarcel Holtmann 
1139a9de9248SMarcel Holtmann 	if (!status)
1140a9de9248SMarcel Holtmann 		return;
1141a9de9248SMarcel Holtmann 
1142a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11431da177e4SLinus Torvalds 	if (!cp)
1144a9de9248SMarcel Holtmann 		return;
11451da177e4SLinus Torvalds 
11461da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11471da177e4SLinus Torvalds 
11489f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
11491da177e4SLinus Torvalds 
11501da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11511da177e4SLinus Torvalds 
11521da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11535a08ecceSAndrei Emeltchenko 	if (acl) {
11545a08ecceSAndrei Emeltchenko 		sco = acl->link;
11555a08ecceSAndrei Emeltchenko 		if (sco) {
11561da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11571da177e4SLinus Torvalds 
11581da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11591da177e4SLinus Torvalds 			hci_conn_del(sco);
11601da177e4SLinus Torvalds 		}
11615a08ecceSAndrei Emeltchenko 	}
11621da177e4SLinus Torvalds 
11631da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11641da177e4SLinus Torvalds }
11651da177e4SLinus Torvalds 
1166f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1167f8558555SMarcel Holtmann {
1168f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1169f8558555SMarcel Holtmann 	struct hci_conn *conn;
1170f8558555SMarcel Holtmann 
11719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1172f8558555SMarcel Holtmann 
1173f8558555SMarcel Holtmann 	if (!status)
1174f8558555SMarcel Holtmann 		return;
1175f8558555SMarcel Holtmann 
1176f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1177f8558555SMarcel Holtmann 	if (!cp)
1178f8558555SMarcel Holtmann 		return;
1179f8558555SMarcel Holtmann 
1180f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1181f8558555SMarcel Holtmann 
1182f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1183f8558555SMarcel Holtmann 	if (conn) {
1184f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1185f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
118676a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1187f8558555SMarcel Holtmann 		}
1188f8558555SMarcel Holtmann 	}
1189f8558555SMarcel Holtmann 
1190f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1191f8558555SMarcel Holtmann }
1192f8558555SMarcel Holtmann 
1193f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1194f8558555SMarcel Holtmann {
1195f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1196f8558555SMarcel Holtmann 	struct hci_conn *conn;
1197f8558555SMarcel Holtmann 
11989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1199f8558555SMarcel Holtmann 
1200f8558555SMarcel Holtmann 	if (!status)
1201f8558555SMarcel Holtmann 		return;
1202f8558555SMarcel Holtmann 
1203f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1204f8558555SMarcel Holtmann 	if (!cp)
1205f8558555SMarcel Holtmann 		return;
1206f8558555SMarcel Holtmann 
1207f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1208f8558555SMarcel Holtmann 
1209f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1210f8558555SMarcel Holtmann 	if (conn) {
1211f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1212f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
121376a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1214f8558555SMarcel Holtmann 		}
1215f8558555SMarcel Holtmann 	}
1216f8558555SMarcel Holtmann 
1217f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1218f8558555SMarcel Holtmann }
1219f8558555SMarcel Holtmann 
1220127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1221392599b9SJohan Hedberg 				    struct hci_conn *conn)
1222392599b9SJohan Hedberg {
1223392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1224392599b9SJohan Hedberg 		return 0;
1225392599b9SJohan Hedberg 
1226765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1227392599b9SJohan Hedberg 		return 0;
1228392599b9SJohan Hedberg 
1229392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1230264b8b4eSJohan Hedberg 	 * devices with sec_level MEDIUM or HIGH or if MITM protection
1231264b8b4eSJohan Hedberg 	 * is requested.
1232264b8b4eSJohan Hedberg 	 */
1233807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1234264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
1235264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
1236392599b9SJohan Hedberg 		return 0;
1237392599b9SJohan Hedberg 
1238392599b9SJohan Hedberg 	return 1;
1239392599b9SJohan Hedberg }
1240392599b9SJohan Hedberg 
12416039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
124200abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
124330dc78e1SJohan Hedberg {
124430dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
124530dc78e1SJohan Hedberg 
124630dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
124730dc78e1SJohan Hedberg 
124830dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
124930dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
125030dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
125130dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
125230dc78e1SJohan Hedberg 
125330dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
125430dc78e1SJohan Hedberg }
125530dc78e1SJohan Hedberg 
1256b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
125730dc78e1SJohan Hedberg {
125830dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
125930dc78e1SJohan Hedberg 	struct inquiry_entry *e;
126030dc78e1SJohan Hedberg 
1261b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1262b644ba33SJohan Hedberg 		return false;
1263b644ba33SJohan Hedberg 
1264b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1265c810089cSRam Malovany 	if (!e)
1266c810089cSRam Malovany 		return false;
1267c810089cSRam Malovany 
1268b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1269b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1270b644ba33SJohan Hedberg 		return true;
1271b644ba33SJohan Hedberg 	}
1272b644ba33SJohan Hedberg 
1273b644ba33SJohan Hedberg 	return false;
1274b644ba33SJohan Hedberg }
1275b644ba33SJohan Hedberg 
1276b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1277b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1278b644ba33SJohan Hedberg {
1279b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1280b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1281b644ba33SJohan Hedberg 
1282b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
128304124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
128404124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1285b644ba33SJohan Hedberg 
1286b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1287b644ba33SJohan Hedberg 		return;
1288b644ba33SJohan Hedberg 
128930dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
129030dc78e1SJohan Hedberg 		goto discov_complete;
129130dc78e1SJohan Hedberg 
129230dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
129330dc78e1SJohan Hedberg 		return;
129430dc78e1SJohan Hedberg 
129530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
12967cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
12977cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
12987cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
12997cc8380eSRam Malovany 	 * Event */
13007cc8380eSRam Malovany 	if (!e)
13017cc8380eSRam Malovany 		return;
13027cc8380eSRam Malovany 
130330dc78e1SJohan Hedberg 	list_del(&e->list);
13047cc8380eSRam Malovany 	if (name) {
13057cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1306b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1307b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1308c3e7c0d9SRam Malovany 	} else {
1309c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
131030dc78e1SJohan Hedberg 	}
131130dc78e1SJohan Hedberg 
1312b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
131330dc78e1SJohan Hedberg 		return;
131430dc78e1SJohan Hedberg 
131530dc78e1SJohan Hedberg discov_complete:
131630dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
131730dc78e1SJohan Hedberg }
131830dc78e1SJohan Hedberg 
1319a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13201da177e4SLinus Torvalds {
1321127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1322127178d2SJohan Hedberg 	struct hci_conn *conn;
1323127178d2SJohan Hedberg 
13249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1325127178d2SJohan Hedberg 
1326127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1327127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1328127178d2SJohan Hedberg 	if (!status)
1329127178d2SJohan Hedberg 		return;
1330127178d2SJohan Hedberg 
1331127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1332127178d2SJohan Hedberg 	if (!cp)
1333127178d2SJohan Hedberg 		return;
1334127178d2SJohan Hedberg 
1335127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1336127178d2SJohan Hedberg 
1337127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1338b644ba33SJohan Hedberg 
1339b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1340b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1341b644ba33SJohan Hedberg 
134279c6c70cSJohan Hedberg 	if (!conn)
134379c6c70cSJohan Hedberg 		goto unlock;
134479c6c70cSJohan Hedberg 
134579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
134679c6c70cSJohan Hedberg 		goto unlock;
134779c6c70cSJohan Hedberg 
134851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1349c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
1350c1f23a2bSJohannes Berg 
1351c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
1352c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1353c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
1354127178d2SJohan Hedberg 	}
1355127178d2SJohan Hedberg 
135679c6c70cSJohan Hedberg unlock:
1357127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1358a9de9248SMarcel Holtmann }
13591da177e4SLinus Torvalds 
1360769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1361769be974SMarcel Holtmann {
1362769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1363769be974SMarcel Holtmann 	struct hci_conn *conn;
1364769be974SMarcel Holtmann 
13659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1366769be974SMarcel Holtmann 
1367769be974SMarcel Holtmann 	if (!status)
1368769be974SMarcel Holtmann 		return;
1369769be974SMarcel Holtmann 
1370769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1371769be974SMarcel Holtmann 	if (!cp)
1372769be974SMarcel Holtmann 		return;
1373769be974SMarcel Holtmann 
1374769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1375769be974SMarcel Holtmann 
1376769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1377769be974SMarcel Holtmann 	if (conn) {
1378769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1379769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
138076a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1381769be974SMarcel Holtmann 		}
1382769be974SMarcel Holtmann 	}
1383769be974SMarcel Holtmann 
1384769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1385769be974SMarcel Holtmann }
1386769be974SMarcel Holtmann 
1387769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1388769be974SMarcel Holtmann {
1389769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1390769be974SMarcel Holtmann 	struct hci_conn *conn;
1391769be974SMarcel Holtmann 
13929f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1393769be974SMarcel Holtmann 
1394769be974SMarcel Holtmann 	if (!status)
1395769be974SMarcel Holtmann 		return;
1396769be974SMarcel Holtmann 
1397769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1398769be974SMarcel Holtmann 	if (!cp)
1399769be974SMarcel Holtmann 		return;
1400769be974SMarcel Holtmann 
1401769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1402769be974SMarcel Holtmann 
1403769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1404769be974SMarcel Holtmann 	if (conn) {
1405769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1406769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
140776a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1408769be974SMarcel Holtmann 		}
1409769be974SMarcel Holtmann 	}
1410769be974SMarcel Holtmann 
1411769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1412769be974SMarcel Holtmann }
1413769be974SMarcel Holtmann 
1414a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1415a9de9248SMarcel Holtmann {
1416b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1417b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1418b6a0dc82SMarcel Holtmann 	__u16 handle;
1419b6a0dc82SMarcel Holtmann 
14209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1421b6a0dc82SMarcel Holtmann 
1422b6a0dc82SMarcel Holtmann 	if (!status)
1423b6a0dc82SMarcel Holtmann 		return;
1424b6a0dc82SMarcel Holtmann 
1425b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1426b6a0dc82SMarcel Holtmann 	if (!cp)
1427b6a0dc82SMarcel Holtmann 		return;
1428b6a0dc82SMarcel Holtmann 
1429b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1430b6a0dc82SMarcel Holtmann 
14319f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1432b6a0dc82SMarcel Holtmann 
1433b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1434b6a0dc82SMarcel Holtmann 
1435b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14365a08ecceSAndrei Emeltchenko 	if (acl) {
14375a08ecceSAndrei Emeltchenko 		sco = acl->link;
14385a08ecceSAndrei Emeltchenko 		if (sco) {
1439b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1440b6a0dc82SMarcel Holtmann 
1441b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1442b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1443b6a0dc82SMarcel Holtmann 		}
14445a08ecceSAndrei Emeltchenko 	}
1445b6a0dc82SMarcel Holtmann 
1446b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1447a9de9248SMarcel Holtmann }
1448a9de9248SMarcel Holtmann 
1449a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1450a9de9248SMarcel Holtmann {
1451a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
145204837f64SMarcel Holtmann 	struct hci_conn *conn;
145304837f64SMarcel Holtmann 
14549f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1455a9de9248SMarcel Holtmann 
1456a9de9248SMarcel Holtmann 	if (!status)
1457a9de9248SMarcel Holtmann 		return;
1458a9de9248SMarcel Holtmann 
1459a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
146004837f64SMarcel Holtmann 	if (!cp)
1461a9de9248SMarcel Holtmann 		return;
146204837f64SMarcel Holtmann 
146304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
146404837f64SMarcel Holtmann 
146504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1466e73439d8SMarcel Holtmann 	if (conn) {
146751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
146804837f64SMarcel Holtmann 
146951a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1470e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1471e73439d8SMarcel Holtmann 	}
1472e73439d8SMarcel Holtmann 
147304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
147404837f64SMarcel Holtmann }
147504837f64SMarcel Holtmann 
1476a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1477a9de9248SMarcel Holtmann {
1478a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
147904837f64SMarcel Holtmann 	struct hci_conn *conn;
148004837f64SMarcel Holtmann 
14819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1482a9de9248SMarcel Holtmann 
1483a9de9248SMarcel Holtmann 	if (!status)
1484a9de9248SMarcel Holtmann 		return;
1485a9de9248SMarcel Holtmann 
1486a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
148704837f64SMarcel Holtmann 	if (!cp)
1488a9de9248SMarcel Holtmann 		return;
148904837f64SMarcel Holtmann 
149004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
149104837f64SMarcel Holtmann 
149204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1493e73439d8SMarcel Holtmann 	if (conn) {
149451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
149504837f64SMarcel Holtmann 
149651a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1497e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1498e73439d8SMarcel Holtmann 	}
1499e73439d8SMarcel Holtmann 
150004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
150104837f64SMarcel Holtmann }
150204837f64SMarcel Holtmann 
150388c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
150488c3df13SJohan Hedberg {
150588c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
150688c3df13SJohan Hedberg 	struct hci_conn *conn;
150788c3df13SJohan Hedberg 
150888c3df13SJohan Hedberg 	if (!status)
150988c3df13SJohan Hedberg 		return;
151088c3df13SJohan Hedberg 
151188c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
151288c3df13SJohan Hedberg 	if (!cp)
151388c3df13SJohan Hedberg 		return;
151488c3df13SJohan Hedberg 
151588c3df13SJohan Hedberg 	hci_dev_lock(hdev);
151688c3df13SJohan Hedberg 
151788c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
151888c3df13SJohan Hedberg 	if (conn)
151988c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
152088c3df13SJohan Hedberg 				       conn->dst_type, status);
152188c3df13SJohan Hedberg 
152288c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
152388c3df13SJohan Hedberg }
152488c3df13SJohan Hedberg 
1525a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1526a02226d6SAndrei Emeltchenko {
152793c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
152893c284eeSAndrei Emeltchenko 
1529a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
153093c284eeSAndrei Emeltchenko 
153193c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
153293c284eeSAndrei Emeltchenko 	if (!cp)
153393c284eeSAndrei Emeltchenko 		return;
153493c284eeSAndrei Emeltchenko 
1535e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1536e58917b9SAndrei Emeltchenko 
1537e58917b9SAndrei Emeltchenko 	if (status) {
1538e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1539e58917b9SAndrei Emeltchenko 
1540e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1541e58917b9SAndrei Emeltchenko 		if (hcon)
1542e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1543e58917b9SAndrei Emeltchenko 	} else {
154493c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1545a02226d6SAndrei Emeltchenko 	}
1546a02226d6SAndrei Emeltchenko 
1547e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1548e58917b9SAndrei Emeltchenko }
1549e58917b9SAndrei Emeltchenko 
15500b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
15510b26ab9dSAndrei Emeltchenko {
15520b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
15530b26ab9dSAndrei Emeltchenko 
15540b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15550b26ab9dSAndrei Emeltchenko 
15560b26ab9dSAndrei Emeltchenko 	if (status)
15570b26ab9dSAndrei Emeltchenko 		return;
15580b26ab9dSAndrei Emeltchenko 
15590b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
15600b26ab9dSAndrei Emeltchenko 	if (!cp)
15610b26ab9dSAndrei Emeltchenko 		return;
15620b26ab9dSAndrei Emeltchenko 
15630b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
15640b26ab9dSAndrei Emeltchenko }
15650b26ab9dSAndrei Emeltchenko 
15666039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15671da177e4SLinus Torvalds {
15681da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
156930dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
157030dc78e1SJohan Hedberg 	struct inquiry_entry *e;
15711da177e4SLinus Torvalds 
15729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15731da177e4SLinus Torvalds 
1574a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
157589352e7dSAndre Guedes 
157689352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
157789352e7dSAndre Guedes 		return;
157889352e7dSAndre Guedes 
15793e13fa1eSAndre Guedes 	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
15803e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
15813e13fa1eSAndre Guedes 
1582a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
158330dc78e1SJohan Hedberg 		return;
158430dc78e1SJohan Hedberg 
158556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
158630dc78e1SJohan Hedberg 
1587343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
158830dc78e1SJohan Hedberg 		goto unlock;
158930dc78e1SJohan Hedberg 
159030dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1591ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
159230dc78e1SJohan Hedberg 		goto unlock;
159330dc78e1SJohan Hedberg 	}
159430dc78e1SJohan Hedberg 
159530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
159630dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
159730dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
159830dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
159930dc78e1SJohan Hedberg 	} else {
160030dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
160130dc78e1SJohan Hedberg 	}
160230dc78e1SJohan Hedberg 
160330dc78e1SJohan Hedberg unlock:
160456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16051da177e4SLinus Torvalds }
16061da177e4SLinus Torvalds 
16076039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16081da177e4SLinus Torvalds {
160945bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1610a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16111da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16121da177e4SLinus Torvalds 
16131da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16141da177e4SLinus Torvalds 
161545bb4bf0SMarcel Holtmann 	if (!num_rsp)
161645bb4bf0SMarcel Holtmann 		return;
161745bb4bf0SMarcel Holtmann 
16181519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
16191519cc17SAndre Guedes 		return;
16201519cc17SAndre Guedes 
16211da177e4SLinus Torvalds 	hci_dev_lock(hdev);
162245bb4bf0SMarcel Holtmann 
1623e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1624388fc8faSJohan Hedberg 		bool name_known, ssp;
16253175405bSJohan Hedberg 
16261da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16271da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16281da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16291da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16301da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16311da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16321da177e4SLinus Torvalds 		data.rssi		= 0x00;
163341a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16343175405bSJohan Hedberg 
1635388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
163648264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
163704124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
163804124681SGustavo F. Padovan 				  0);
16391da177e4SLinus Torvalds 	}
164045bb4bf0SMarcel Holtmann 
16411da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16421da177e4SLinus Torvalds }
16431da177e4SLinus Torvalds 
16446039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16451da177e4SLinus Torvalds {
1646a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1647a9de9248SMarcel Holtmann 	struct hci_conn *conn;
16481da177e4SLinus Torvalds 
1649a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
165045bb4bf0SMarcel Holtmann 
16511da177e4SLinus Torvalds 	hci_dev_lock(hdev);
165245bb4bf0SMarcel Holtmann 
1653a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16549499237aSMarcel Holtmann 	if (!conn) {
16559499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16569499237aSMarcel Holtmann 			goto unlock;
16579499237aSMarcel Holtmann 
16589499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1659a9de9248SMarcel Holtmann 		if (!conn)
1660a9de9248SMarcel Holtmann 			goto unlock;
166145bb4bf0SMarcel Holtmann 
16629499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16639499237aSMarcel Holtmann 	}
16649499237aSMarcel Holtmann 
1665a9de9248SMarcel Holtmann 	if (!ev->status) {
1666a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1667769be974SMarcel Holtmann 
1668769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1669769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1670769be974SMarcel Holtmann 			hci_conn_hold(conn);
1671a9ea3ed9SSzymon Janc 
1672a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1673a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1674a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1675a9ea3ed9SSzymon Janc 			else
1676052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1677769be974SMarcel Holtmann 		} else
1678a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1679a9de9248SMarcel Holtmann 
16807d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
16817d0db0a3SMarcel Holtmann 
1682a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1683a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1684a9de9248SMarcel Holtmann 
1685a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1686a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1687a9de9248SMarcel Holtmann 
1688a9de9248SMarcel Holtmann 		/* Get remote features */
1689a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1690a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1691a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1692769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1693769be974SMarcel Holtmann 				     sizeof(cp), &cp);
169445bb4bf0SMarcel Holtmann 		}
1695a9de9248SMarcel Holtmann 
1696a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1697d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1698a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1699a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1700a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
170104124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
170204124681SGustavo F. Padovan 				     &cp);
1703a9de9248SMarcel Holtmann 		}
170417d5c04cSJohan Hedberg 	} else {
1705a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
170617d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1707744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
170848264f06SJohan Hedberg 					    conn->dst_type, ev->status);
170917d5c04cSJohan Hedberg 	}
171045bb4bf0SMarcel Holtmann 
1711e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1712e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
171345bb4bf0SMarcel Holtmann 
1714769be974SMarcel Holtmann 	if (ev->status) {
1715a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1716a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1717c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1718c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1719a9de9248SMarcel Holtmann 
1720a9de9248SMarcel Holtmann unlock:
17211da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1722a9de9248SMarcel Holtmann 
1723a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
17241da177e4SLinus Torvalds }
17251da177e4SLinus Torvalds 
17266039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17271da177e4SLinus Torvalds {
1728a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17291da177e4SLinus Torvalds 	int mask = hdev->link_mode;
173020714bfeSFrédéric Dalleau 	__u8 flags = 0;
17311da177e4SLinus Torvalds 
17326ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
1733807deac2SGustavo Padovan 	       ev->link_type);
17341da177e4SLinus Torvalds 
173520714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
173620714bfeSFrédéric Dalleau 				      &flags);
17371da177e4SLinus Torvalds 
1738138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1739b9ee0a78SMarcel Holtmann 	    !hci_blacklist_lookup(hdev, &ev->bdaddr, BDADDR_BREDR)) {
17401da177e4SLinus Torvalds 		/* Connection accepted */
1741c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17421da177e4SLinus Torvalds 		struct hci_conn *conn;
17431da177e4SLinus Torvalds 
17441da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1745b6a0dc82SMarcel Holtmann 
1746cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1747cc11b9c1SAndrei Emeltchenko 		if (ie)
1748c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1749c7bdd502SMarcel Holtmann 
17508fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
17518fc9ced3SGustavo Padovan 					       &ev->bdaddr);
17521da177e4SLinus Torvalds 		if (!conn) {
1753cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1754cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1755893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17561da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17571da177e4SLinus Torvalds 				return;
17581da177e4SLinus Torvalds 			}
17591da177e4SLinus Torvalds 		}
1760b6a0dc82SMarcel Holtmann 
17611da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
1762b6a0dc82SMarcel Holtmann 
17631da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17641da177e4SLinus Torvalds 
176520714bfeSFrédéric Dalleau 		if (ev->link_type == ACL_LINK ||
176620714bfeSFrédéric Dalleau 		    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
1767b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
176820714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1769b6a0dc82SMarcel Holtmann 
17701da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17711da177e4SLinus Torvalds 
17721da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17731da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17741da177e4SLinus Torvalds 			else
17751da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17761da177e4SLinus Torvalds 
177704124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
177804124681SGustavo F. Padovan 				     &cp);
177920714bfeSFrédéric Dalleau 		} else if (!(flags & HCI_PROTO_DEFER)) {
1780b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
178120714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1782b6a0dc82SMarcel Holtmann 
1783b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1784a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1785b6a0dc82SMarcel Holtmann 
178682781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
178782781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
178882781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1789b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1790b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1791b6a0dc82SMarcel Holtmann 
1792b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1793b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
179420714bfeSFrédéric Dalleau 		} else {
179520714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT2;
179620714bfeSFrédéric Dalleau 			hci_proto_connect_cfm(conn, 0);
1797b6a0dc82SMarcel Holtmann 		}
17981da177e4SLinus Torvalds 	} else {
17991da177e4SLinus Torvalds 		/* Connection rejected */
18001da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18011da177e4SLinus Torvalds 
18021da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18039f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1804a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18051da177e4SLinus Torvalds 	}
18061da177e4SLinus Torvalds }
18071da177e4SLinus Torvalds 
1808f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
1809f0d6a0eaSMikel Astiz {
1810f0d6a0eaSMikel Astiz 	switch (err) {
1811f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
1812f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
1813f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
1814f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
1815f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
1816f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
1817f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
1818f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
1819f0d6a0eaSMikel Astiz 	default:
1820f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
1821f0d6a0eaSMikel Astiz 	}
1822f0d6a0eaSMikel Astiz }
1823f0d6a0eaSMikel Astiz 
18246039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18251da177e4SLinus Torvalds {
1826a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
1827abf54a50SAndre Guedes 	u8 reason = hci_to_mgmt_reason(ev->reason);
182804837f64SMarcel Holtmann 	struct hci_conn *conn;
18293846220bSAndre Guedes 	u8 type;
18301da177e4SLinus Torvalds 
18319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
18321da177e4SLinus Torvalds 
18331da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18341da177e4SLinus Torvalds 
183504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1836f7520543SJohan Hedberg 	if (!conn)
1837f7520543SJohan Hedberg 		goto unlock;
1838f7520543SJohan Hedberg 
1839f0d6a0eaSMikel Astiz 	if (ev->status) {
184088c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
184188c3df13SJohan Hedberg 				       conn->dst_type, ev->status);
1842abf54a50SAndre Guedes 		goto unlock;
1843abf54a50SAndre Guedes 	}
1844f0d6a0eaSMikel Astiz 
18453846220bSAndre Guedes 	conn->state = BT_CLOSED;
18463846220bSAndre Guedes 
1847abf54a50SAndre Guedes 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
1848afc747a6SJohan Hedberg 		mgmt_device_disconnected(hdev, &conn->dst, conn->type,
1849f0d6a0eaSMikel Astiz 					 conn->dst_type, reason);
1850f7520543SJohan Hedberg 
18513846220bSAndre Guedes 	if (conn->type == ACL_LINK && conn->flush_key)
18526ec5bcadSVishal Agarwal 		hci_remove_link_key(hdev, &conn->dst);
18533846220bSAndre Guedes 
18543846220bSAndre Guedes 	type = conn->type;
18553846220bSAndre Guedes 
18562950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
18571da177e4SLinus Torvalds 	hci_conn_del(conn);
18582210246cSJohan Hedberg 
18592210246cSJohan Hedberg 	/* Re-enable advertising if necessary, since it might
18602210246cSJohan Hedberg 	 * have been disabled by the connection. From the
18612210246cSJohan Hedberg 	 * HCI_LE_Set_Advertise_Enable command description in
18622210246cSJohan Hedberg 	 * the core specification (v4.0):
18632210246cSJohan Hedberg 	 * "The Controller shall continue advertising until the Host
18642210246cSJohan Hedberg 	 * issues an LE_Set_Advertise_Enable command with
18652210246cSJohan Hedberg 	 * Advertising_Enable set to 0x00 (Advertising is disabled)
18662210246cSJohan Hedberg 	 * or until a connection is created or until the Advertising
18672210246cSJohan Hedberg 	 * is timed out due to Directed Advertising."
18682210246cSJohan Hedberg 	 */
18692210246cSJohan Hedberg 	if (type == LE_LINK)
18705976e608SMarcel Holtmann 		mgmt_reenable_advertising(hdev);
18711da177e4SLinus Torvalds 
1872f7520543SJohan Hedberg unlock:
18731da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18741da177e4SLinus Torvalds }
18751da177e4SLinus Torvalds 
18766039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1877a9de9248SMarcel Holtmann {
1878a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1879a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1880a9de9248SMarcel Holtmann 
18819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1882a9de9248SMarcel Holtmann 
1883a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1884a9de9248SMarcel Holtmann 
1885a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1886d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1887d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1888d7556e20SWaldemar Rymarkiewicz 
1889765c2a96SJohan Hedberg 	if (!ev->status) {
1890aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
189151a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1892d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
189319f8def0SWaldemar Rymarkiewicz 		} else {
1894a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1895765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
189619f8def0SWaldemar Rymarkiewicz 		}
18972a611692SJohan Hedberg 	} else {
1898bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1899bab73cb6SJohan Hedberg 				 ev->status);
19002a611692SJohan Hedberg 	}
1901a9de9248SMarcel Holtmann 
190251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
190351a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1904a9de9248SMarcel Holtmann 
1905f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1906aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1907f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1908f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1909f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1910d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1911d7556e20SWaldemar Rymarkiewicz 				     &cp);
1912f8558555SMarcel Holtmann 		} else {
1913f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1914f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
191576a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1916f8558555SMarcel Holtmann 		}
1917052b30b0SMarcel Holtmann 	} else {
1918a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1919a9de9248SMarcel Holtmann 
1920052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1921052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
192276a68ba0SDavid Herrmann 		hci_conn_drop(conn);
1923052b30b0SMarcel Holtmann 	}
1924052b30b0SMarcel Holtmann 
192551a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1926a9de9248SMarcel Holtmann 		if (!ev->status) {
1927a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1928f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1929f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1930d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1931d7556e20SWaldemar Rymarkiewicz 				     &cp);
1932a9de9248SMarcel Holtmann 		} else {
193351a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1934a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1935a9de9248SMarcel Holtmann 		}
1936a9de9248SMarcel Holtmann 	}
1937a9de9248SMarcel Holtmann 
1938d7556e20SWaldemar Rymarkiewicz unlock:
1939a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1940a9de9248SMarcel Holtmann }
1941a9de9248SMarcel Holtmann 
19426039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1943a9de9248SMarcel Holtmann {
1944127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1945127178d2SJohan Hedberg 	struct hci_conn *conn;
1946127178d2SJohan Hedberg 
1947a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1948a9de9248SMarcel Holtmann 
1949a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1950127178d2SJohan Hedberg 
1951127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1952127178d2SJohan Hedberg 
1953127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1954b644ba33SJohan Hedberg 
1955b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1956b644ba33SJohan Hedberg 		goto check_auth;
1957b644ba33SJohan Hedberg 
1958b644ba33SJohan Hedberg 	if (ev->status == 0)
1959b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1960b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1961b644ba33SJohan Hedberg 	else
1962b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1963b644ba33SJohan Hedberg 
1964b644ba33SJohan Hedberg check_auth:
196579c6c70cSJohan Hedberg 	if (!conn)
196679c6c70cSJohan Hedberg 		goto unlock;
196779c6c70cSJohan Hedberg 
196879c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
196979c6c70cSJohan Hedberg 		goto unlock;
197079c6c70cSJohan Hedberg 
197151a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1972127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1973127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1974127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1975127178d2SJohan Hedberg 	}
1976127178d2SJohan Hedberg 
197779c6c70cSJohan Hedberg unlock:
1978127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1979a9de9248SMarcel Holtmann }
1980a9de9248SMarcel Holtmann 
19816039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1982a9de9248SMarcel Holtmann {
1983a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1984a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1985a9de9248SMarcel Holtmann 
19869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1987a9de9248SMarcel Holtmann 
1988a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1989a9de9248SMarcel Holtmann 
1990a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1991dc8357ccSMarcel Holtmann 	if (!conn)
1992dc8357ccSMarcel Holtmann 		goto unlock;
1993dc8357ccSMarcel Holtmann 
1994a9de9248SMarcel Holtmann 	if (!ev->status) {
1995ae293196SMarcel Holtmann 		if (ev->encrypt) {
1996ae293196SMarcel Holtmann 			/* Encryption implies authentication */
1997ae293196SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1998a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1999da85e5e5SVinicius Costa Gomes 			conn->sec_level = conn->pending_sec_level;
2000abf76badSMarcel Holtmann 
2001914a6ffeSMarcel Holtmann 			/* P-256 authentication key implies FIPS */
2002914a6ffeSMarcel Holtmann 			if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
2003914a6ffeSMarcel Holtmann 				conn->link_mode |= HCI_LM_FIPS;
2004914a6ffeSMarcel Holtmann 
2005abf76badSMarcel Holtmann 			if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
2006abf76badSMarcel Holtmann 			    conn->type == LE_LINK)
2007abf76badSMarcel Holtmann 				set_bit(HCI_CONN_AES_CCM, &conn->flags);
2008abf76badSMarcel Holtmann 		} else {
2009a9de9248SMarcel Holtmann 			conn->link_mode &= ~HCI_LM_ENCRYPT;
2010abf76badSMarcel Holtmann 			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
2011abf76badSMarcel Holtmann 		}
2012a9de9248SMarcel Holtmann 	}
2013a9de9248SMarcel Holtmann 
201451a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2015a9de9248SMarcel Holtmann 
2016a7d7723aSGustavo Padovan 	if (ev->status && conn->state == BT_CONNECTED) {
2017bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
201876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2019a7d7723aSGustavo Padovan 		goto unlock;
2020a7d7723aSGustavo Padovan 	}
2021a7d7723aSGustavo Padovan 
2022f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2023f8558555SMarcel Holtmann 		if (!ev->status)
2024f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2025f8558555SMarcel Holtmann 
2026f8558555SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
202776a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2028f8558555SMarcel Holtmann 	} else
2029a9de9248SMarcel Holtmann 		hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2030a9de9248SMarcel Holtmann 
2031a7d7723aSGustavo Padovan unlock:
2032a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2033a9de9248SMarcel Holtmann }
2034a9de9248SMarcel Holtmann 
20356039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2036807deac2SGustavo Padovan 					     struct sk_buff *skb)
2037a9de9248SMarcel Holtmann {
2038a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2039a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2040a9de9248SMarcel Holtmann 
20419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2042a9de9248SMarcel Holtmann 
2043a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2044a9de9248SMarcel Holtmann 
2045a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2046a9de9248SMarcel Holtmann 	if (conn) {
2047a9de9248SMarcel Holtmann 		if (!ev->status)
2048a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2049a9de9248SMarcel Holtmann 
205051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2051a9de9248SMarcel Holtmann 
2052a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2053a9de9248SMarcel Holtmann 	}
2054a9de9248SMarcel Holtmann 
2055a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2056a9de9248SMarcel Holtmann }
2057a9de9248SMarcel Holtmann 
20586039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2059807deac2SGustavo Padovan 				    struct sk_buff *skb)
2060a9de9248SMarcel Holtmann {
2061a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2062a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2063a9de9248SMarcel Holtmann 
20649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2065a9de9248SMarcel Holtmann 
2066a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2067a9de9248SMarcel Holtmann 
2068a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2069ccd556feSJohan Hedberg 	if (!conn)
2070ccd556feSJohan Hedberg 		goto unlock;
2071ccd556feSJohan Hedberg 
2072769be974SMarcel Holtmann 	if (!ev->status)
2073cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
2074a9de9248SMarcel Holtmann 
2075ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2076ccd556feSJohan Hedberg 		goto unlock;
2077ccd556feSJohan Hedberg 
2078ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2079769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2080769be974SMarcel Holtmann 		cp.handle = ev->handle;
2081769be974SMarcel Holtmann 		cp.page = 0x01;
2082ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2083769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2084392599b9SJohan Hedberg 		goto unlock;
2085392599b9SJohan Hedberg 	}
2086392599b9SJohan Hedberg 
2087671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2088127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2089127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2090127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2091127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2092127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2093b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2094b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
209508c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2096b644ba33SJohan Hedberg 				      conn->dev_class);
2097392599b9SJohan Hedberg 
2098127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2099769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2100769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
210176a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2102769be974SMarcel Holtmann 	}
2103769be974SMarcel Holtmann 
2104ccd556feSJohan Hedberg unlock:
2105a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2106a9de9248SMarcel Holtmann }
2107a9de9248SMarcel Holtmann 
21086039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2109a9de9248SMarcel Holtmann {
2110a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
21119238f36aSJohan Hedberg 	u8 status = skb->data[sizeof(*ev)];
2112a9de9248SMarcel Holtmann 	__u16 opcode;
2113a9de9248SMarcel Holtmann 
2114a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2115a9de9248SMarcel Holtmann 
2116a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2117a9de9248SMarcel Holtmann 
2118a9de9248SMarcel Holtmann 	switch (opcode) {
2119a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2120a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2121a9de9248SMarcel Holtmann 		break;
2122a9de9248SMarcel Holtmann 
21234d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
21244d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
21254d93483bSAndre Guedes 		break;
21264d93483bSAndre Guedes 
2127a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2128a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2129a9de9248SMarcel Holtmann 		break;
2130a9de9248SMarcel Holtmann 
2131a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2132a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2133a9de9248SMarcel Holtmann 		break;
2134a9de9248SMarcel Holtmann 
2135a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2136a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2137a9de9248SMarcel Holtmann 		break;
2138a9de9248SMarcel Holtmann 
2139e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2140e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2141e4e8e37cSMarcel Holtmann 		break;
2142e4e8e37cSMarcel Holtmann 
2143a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2144a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2145a9de9248SMarcel Holtmann 		break;
2146a9de9248SMarcel Holtmann 
2147e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2148e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2149e4e8e37cSMarcel Holtmann 		break;
2150e4e8e37cSMarcel Holtmann 
2151e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2152e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2153e4e8e37cSMarcel Holtmann 		break;
2154e4e8e37cSMarcel Holtmann 
2155a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2156a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2157a9de9248SMarcel Holtmann 		break;
2158a9de9248SMarcel Holtmann 
2159a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2160a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2161a9de9248SMarcel Holtmann 		break;
2162a9de9248SMarcel Holtmann 
2163a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2164a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2165a9de9248SMarcel Holtmann 		break;
2166a9de9248SMarcel Holtmann 
2167a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2168a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2169a9de9248SMarcel Holtmann 		break;
2170a9de9248SMarcel Holtmann 
2171a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2172a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2173a9de9248SMarcel Holtmann 		break;
2174a9de9248SMarcel Holtmann 
2175a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2176a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2177a9de9248SMarcel Holtmann 		break;
2178a9de9248SMarcel Holtmann 
2179a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2180a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2181a9de9248SMarcel Holtmann 		break;
2182a9de9248SMarcel Holtmann 
2183a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2184a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2185a9de9248SMarcel Holtmann 		break;
2186a9de9248SMarcel Holtmann 
2187a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2188a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2189a9de9248SMarcel Holtmann 		break;
2190a9de9248SMarcel Holtmann 
2191a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2192a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2193a9de9248SMarcel Holtmann 		break;
2194a9de9248SMarcel Holtmann 
2195b4cb9fb2SMarcel Holtmann 	case HCI_OP_READ_NUM_SUPPORTED_IAC:
2196b4cb9fb2SMarcel Holtmann 		hci_cc_read_num_supported_iac(hdev, skb);
2197b4cb9fb2SMarcel Holtmann 		break;
2198b4cb9fb2SMarcel Holtmann 
2199333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2200333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2201333140b5SMarcel Holtmann 		break;
2202333140b5SMarcel Holtmann 
2203eac83dc6SMarcel Holtmann 	case HCI_OP_WRITE_SC_SUPPORT:
2204eac83dc6SMarcel Holtmann 		hci_cc_write_sc_support(hdev, skb);
2205eac83dc6SMarcel Holtmann 		break;
2206eac83dc6SMarcel Holtmann 
2207a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2208a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2209a9de9248SMarcel Holtmann 		break;
2210a9de9248SMarcel Holtmann 
2211a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2212a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2213a9de9248SMarcel Holtmann 		break;
2214a9de9248SMarcel Holtmann 
2215a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2216a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2217a9de9248SMarcel Holtmann 		break;
2218a9de9248SMarcel Holtmann 
2219971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2220971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2221971e3a4bSAndre Guedes 		break;
2222971e3a4bSAndre Guedes 
2223a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2224a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2225a9de9248SMarcel Holtmann 		break;
2226a9de9248SMarcel Holtmann 
2227a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2228a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2229a9de9248SMarcel Holtmann 		break;
2230a9de9248SMarcel Holtmann 
2231f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2232f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
2233f332ec66SJohan Hedberg 		break;
2234f332ec66SJohan Hedberg 
22354a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
22364a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
22374a3ee763SJohan Hedberg 		break;
22384a3ee763SJohan Hedberg 
2239f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
2240f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
2241f332ec66SJohan Hedberg 		break;
2242f332ec66SJohan Hedberg 
22434a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
22444a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
22454a3ee763SJohan Hedberg 		break;
22464a3ee763SJohan Hedberg 
2247350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2248350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2249350ee4cfSAndrei Emeltchenko 		break;
2250350ee4cfSAndrei Emeltchenko 
22511e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22521e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22531e89cffbSAndrei Emeltchenko 		break;
22541e89cffbSAndrei Emeltchenko 
2255928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2256928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2257928abaa7SAndrei Emeltchenko 		break;
2258928abaa7SAndrei Emeltchenko 
2259903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2260903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2261903e4541SAndrei Emeltchenko 		break;
2262903e4541SAndrei Emeltchenko 
2263d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2264d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2265d5859e22SJohan Hedberg 		break;
2266d5859e22SJohan Hedberg 
2267980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2268980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2269980e1a53SJohan Hedberg 		break;
2270980e1a53SJohan Hedberg 
2271980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2272980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2273980e1a53SJohan Hedberg 		break;
2274980e1a53SJohan Hedberg 
2275c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
22764d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_data(hdev, skb);
22774d2d2796SMarcel Holtmann 		break;
22784d2d2796SMarcel Holtmann 
22794d2d2796SMarcel Holtmann 	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
22804d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_ext_data(hdev, skb);
2281c35938b2SSzymon Janc 		break;
2282c35938b2SSzymon Janc 
22836ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22846ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22856ed58ec5SVille Tervo 		break;
22866ed58ec5SVille Tervo 
228760e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
228860e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
228960e77321SJohan Hedberg 		break;
229060e77321SJohan Hedberg 
22918fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
22928fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
22938fa19098SJohan Hedberg 		break;
22948fa19098SJohan Hedberg 
2295a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2296a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2297a5c29683SJohan Hedberg 		break;
2298a5c29683SJohan Hedberg 
2299a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2300a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2301a5c29683SJohan Hedberg 		break;
2302a5c29683SJohan Hedberg 
23031143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
23041143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
23051143d458SBrian Gix 		break;
23061143d458SBrian Gix 
23071143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23081143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
230916cde993SSzymon Janc 		break;
231007f7fa5dSAndre Guedes 
2311c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2312c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2313c1d5dc4aSJohan Hedberg 		break;
2314c1d5dc4aSJohan Hedberg 
2315eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2316eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2317eb9d91f5SAndre Guedes 		break;
2318eb9d91f5SAndre Guedes 
2319cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2320cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2321cf1d081fSJohan Hedberg 		break;
2322cf1d081fSJohan Hedberg 
23239b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
23249b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
23259b008c04SJohan Hedberg 		break;
23269b008c04SJohan Hedberg 
2327f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2328f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2329f9b49306SAndre Guedes 		break;
2330f9b49306SAndre Guedes 
233193c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
233293c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
233393c284eeSAndrei Emeltchenko 		break;
233493c284eeSAndrei Emeltchenko 
2335a9de9248SMarcel Holtmann 	default:
23369f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2337a9de9248SMarcel Holtmann 		break;
2338a9de9248SMarcel Holtmann 	}
2339a9de9248SMarcel Holtmann 
2340ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
23416bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23426bd32326SVille Tervo 
2343ad82cdd1SJohan Hedberg 	hci_req_cmd_complete(hdev, opcode, status);
23449238f36aSJohan Hedberg 
2345dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2346a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2347a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2348c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2349a9de9248SMarcel Holtmann 	}
2350a9de9248SMarcel Holtmann }
2351a9de9248SMarcel Holtmann 
23526039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2353a9de9248SMarcel Holtmann {
2354a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2355a9de9248SMarcel Holtmann 	__u16 opcode;
2356a9de9248SMarcel Holtmann 
2357a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2358a9de9248SMarcel Holtmann 
2359a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2360a9de9248SMarcel Holtmann 
2361a9de9248SMarcel Holtmann 	switch (opcode) {
2362a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2363a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2364a9de9248SMarcel Holtmann 		break;
2365a9de9248SMarcel Holtmann 
2366a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2367a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2368a9de9248SMarcel Holtmann 		break;
2369a9de9248SMarcel Holtmann 
2370a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2371a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2372a9de9248SMarcel Holtmann 		break;
2373a9de9248SMarcel Holtmann 
2374f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2375f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2376f8558555SMarcel Holtmann 		break;
2377f8558555SMarcel Holtmann 
2378f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2379f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2380f8558555SMarcel Holtmann 		break;
2381f8558555SMarcel Holtmann 
2382a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2383a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2384a9de9248SMarcel Holtmann 		break;
2385a9de9248SMarcel Holtmann 
2386769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2387769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2388769be974SMarcel Holtmann 		break;
2389769be974SMarcel Holtmann 
2390769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2391769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2392769be974SMarcel Holtmann 		break;
2393769be974SMarcel Holtmann 
2394a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2395a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2396a9de9248SMarcel Holtmann 		break;
2397a9de9248SMarcel Holtmann 
2398a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2399a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2400a9de9248SMarcel Holtmann 		break;
2401a9de9248SMarcel Holtmann 
2402a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2403a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2404a9de9248SMarcel Holtmann 		break;
2405a9de9248SMarcel Holtmann 
24068962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
240788c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
24088962ee74SJohan Hedberg 		break;
24098962ee74SJohan Hedberg 
2410a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2411a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2412a02226d6SAndrei Emeltchenko 		break;
2413a02226d6SAndrei Emeltchenko 
24140b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
24150b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
24160b26ab9dSAndrei Emeltchenko 		break;
24170b26ab9dSAndrei Emeltchenko 
2418a9de9248SMarcel Holtmann 	default:
24199f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2420a9de9248SMarcel Holtmann 		break;
2421a9de9248SMarcel Holtmann 	}
2422a9de9248SMarcel Holtmann 
2423ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
24246bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24256bd32326SVille Tervo 
242602350a72SJohan Hedberg 	if (ev->status ||
242702350a72SJohan Hedberg 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
242833720450SAndre Guedes 		hci_req_cmd_complete(hdev, opcode, ev->status);
24299238f36aSJohan Hedberg 
243010572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2431a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2432a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2433c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2434a9de9248SMarcel Holtmann 	}
2435a9de9248SMarcel Holtmann }
2436a9de9248SMarcel Holtmann 
24376039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2438a9de9248SMarcel Holtmann {
2439a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2440a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2441a9de9248SMarcel Holtmann 
24429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2443a9de9248SMarcel Holtmann 
2444a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2445a9de9248SMarcel Holtmann 
2446a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2447a9de9248SMarcel Holtmann 	if (conn) {
2448a9de9248SMarcel Holtmann 		if (!ev->status) {
2449a9de9248SMarcel Holtmann 			if (ev->role)
2450a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2451a9de9248SMarcel Holtmann 			else
2452a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2453a9de9248SMarcel Holtmann 		}
2454a9de9248SMarcel Holtmann 
245551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2456a9de9248SMarcel Holtmann 
2457a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2458a9de9248SMarcel Holtmann 	}
2459a9de9248SMarcel Holtmann 
2460a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2461a9de9248SMarcel Holtmann }
2462a9de9248SMarcel Holtmann 
24636039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24641da177e4SLinus Torvalds {
2465a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24661da177e4SLinus Torvalds 	int i;
24671da177e4SLinus Torvalds 
246832ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
246932ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
247032ac5b9bSAndrei Emeltchenko 		return;
247132ac5b9bSAndrei Emeltchenko 	}
247232ac5b9bSAndrei Emeltchenko 
2473c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2474c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24751da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24761da177e4SLinus Torvalds 		return;
24771da177e4SLinus Torvalds 	}
24781da177e4SLinus Torvalds 
2479c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2480c5993de8SAndrei Emeltchenko 
2481613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2482613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24831da177e4SLinus Torvalds 		struct hci_conn *conn;
24841da177e4SLinus Torvalds 		__u16  handle, count;
24851da177e4SLinus Torvalds 
2486613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2487613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24881da177e4SLinus Torvalds 
24891da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2490f4280918SAndrei Emeltchenko 		if (!conn)
2491f4280918SAndrei Emeltchenko 			continue;
2492f4280918SAndrei Emeltchenko 
24931da177e4SLinus Torvalds 		conn->sent -= count;
24941da177e4SLinus Torvalds 
2495f4280918SAndrei Emeltchenko 		switch (conn->type) {
2496f4280918SAndrei Emeltchenko 		case ACL_LINK:
249770f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
249870f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24991da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2500f4280918SAndrei Emeltchenko 			break;
2501f4280918SAndrei Emeltchenko 
2502f4280918SAndrei Emeltchenko 		case LE_LINK:
25036ed58ec5SVille Tervo 			if (hdev->le_pkts) {
25046ed58ec5SVille Tervo 				hdev->le_cnt += count;
25056ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
25066ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
25076ed58ec5SVille Tervo 			} else {
25086ed58ec5SVille Tervo 				hdev->acl_cnt += count;
25096ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
25106ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
25116ed58ec5SVille Tervo 			}
2512f4280918SAndrei Emeltchenko 			break;
2513f4280918SAndrei Emeltchenko 
2514f4280918SAndrei Emeltchenko 		case SCO_LINK:
251570f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
251670f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
25175b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2518f4280918SAndrei Emeltchenko 			break;
2519f4280918SAndrei Emeltchenko 
2520f4280918SAndrei Emeltchenko 		default:
2521f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2522f4280918SAndrei Emeltchenko 			break;
25231da177e4SLinus Torvalds 		}
25241da177e4SLinus Torvalds 	}
2525a9de9248SMarcel Holtmann 
25263eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25271da177e4SLinus Torvalds }
25281da177e4SLinus Torvalds 
252976ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
253076ef7cf7SAndrei Emeltchenko 						 __u16 handle)
253176ef7cf7SAndrei Emeltchenko {
253276ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
253376ef7cf7SAndrei Emeltchenko 
253476ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
253576ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
253676ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
253776ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
253876ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
253976ef7cf7SAndrei Emeltchenko 		if (chan)
254076ef7cf7SAndrei Emeltchenko 			return chan->conn;
254176ef7cf7SAndrei Emeltchenko 		break;
254276ef7cf7SAndrei Emeltchenko 	default:
254376ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
254476ef7cf7SAndrei Emeltchenko 		break;
254576ef7cf7SAndrei Emeltchenko 	}
254676ef7cf7SAndrei Emeltchenko 
254776ef7cf7SAndrei Emeltchenko 	return NULL;
254876ef7cf7SAndrei Emeltchenko }
254976ef7cf7SAndrei Emeltchenko 
25506039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
255125e89e99SAndrei Emeltchenko {
255225e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
255325e89e99SAndrei Emeltchenko 	int i;
255425e89e99SAndrei Emeltchenko 
255525e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
255625e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
255725e89e99SAndrei Emeltchenko 		return;
255825e89e99SAndrei Emeltchenko 	}
255925e89e99SAndrei Emeltchenko 
256025e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
256125e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
256225e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
256325e89e99SAndrei Emeltchenko 		return;
256425e89e99SAndrei Emeltchenko 	}
256525e89e99SAndrei Emeltchenko 
256625e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
256725e89e99SAndrei Emeltchenko 	       ev->num_hndl);
256825e89e99SAndrei Emeltchenko 
256925e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
257025e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
257176ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
257225e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
257325e89e99SAndrei Emeltchenko 
257425e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
257525e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
257625e89e99SAndrei Emeltchenko 
257776ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
257825e89e99SAndrei Emeltchenko 		if (!conn)
257925e89e99SAndrei Emeltchenko 			continue;
258025e89e99SAndrei Emeltchenko 
258125e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
258225e89e99SAndrei Emeltchenko 
258325e89e99SAndrei Emeltchenko 		switch (conn->type) {
258425e89e99SAndrei Emeltchenko 		case ACL_LINK:
2585bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
258625e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
258725e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
258825e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
258925e89e99SAndrei Emeltchenko 			break;
259025e89e99SAndrei Emeltchenko 
259125e89e99SAndrei Emeltchenko 		default:
259225e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
259325e89e99SAndrei Emeltchenko 			break;
259425e89e99SAndrei Emeltchenko 		}
259525e89e99SAndrei Emeltchenko 	}
259625e89e99SAndrei Emeltchenko 
259725e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
259825e89e99SAndrei Emeltchenko }
259925e89e99SAndrei Emeltchenko 
26006039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
26011da177e4SLinus Torvalds {
2602a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
260304837f64SMarcel Holtmann 	struct hci_conn *conn;
26041da177e4SLinus Torvalds 
26059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
26061da177e4SLinus Torvalds 
26071da177e4SLinus Torvalds 	hci_dev_lock(hdev);
26081da177e4SLinus Torvalds 
260904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
261004837f64SMarcel Holtmann 	if (conn) {
261104837f64SMarcel Holtmann 		conn->mode = ev->mode;
261204837f64SMarcel Holtmann 
26138fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
26148fc9ced3SGustavo Padovan 					&conn->flags)) {
261504837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
261658a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
261704837f64SMarcel Holtmann 			else
261858a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
261904837f64SMarcel Holtmann 		}
2620e73439d8SMarcel Holtmann 
262151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2622e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
262304837f64SMarcel Holtmann 	}
262404837f64SMarcel Holtmann 
262504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
262604837f64SMarcel Holtmann }
262704837f64SMarcel Holtmann 
26286039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26291da177e4SLinus Torvalds {
2630052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2631052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2632052b30b0SMarcel Holtmann 
2633a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2634052b30b0SMarcel Holtmann 
2635052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2636052b30b0SMarcel Holtmann 
2637052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2638b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2639b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2640b6f98044SWaldemar Rymarkiewicz 
2641b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2642052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2643052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
264476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2645052b30b0SMarcel Holtmann 	}
2646052b30b0SMarcel Holtmann 
2647a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
264803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
264903b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2650a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2651a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2652a770bb5aSWaldemar Rymarkiewicz 
2653a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2654a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2655a770bb5aSWaldemar Rymarkiewicz 		else
2656a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2657a770bb5aSWaldemar Rymarkiewicz 
2658744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2659a770bb5aSWaldemar Rymarkiewicz 	}
2660980e1a53SJohan Hedberg 
2661b6f98044SWaldemar Rymarkiewicz unlock:
2662052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26631da177e4SLinus Torvalds }
26641da177e4SLinus Torvalds 
26656039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26661da177e4SLinus Torvalds {
266755ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
266855ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
266955ed8ca1SJohan Hedberg 	struct hci_conn *conn;
267055ed8ca1SJohan Hedberg 	struct link_key *key;
267155ed8ca1SJohan Hedberg 
2672a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
267355ed8ca1SJohan Hedberg 
2674034cbea0SAndrei Emeltchenko 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
267555ed8ca1SJohan Hedberg 		return;
267655ed8ca1SJohan Hedberg 
267755ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
267855ed8ca1SJohan Hedberg 
267955ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
268055ed8ca1SJohan Hedberg 	if (!key) {
26816ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
26826ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
268355ed8ca1SJohan Hedberg 		goto not_found;
268455ed8ca1SJohan Hedberg 	}
268555ed8ca1SJohan Hedberg 
26866ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
26876ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
268855ed8ca1SJohan Hedberg 
2689a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2690b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
269155ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
269255ed8ca1SJohan Hedberg 		goto not_found;
269355ed8ca1SJohan Hedberg 	}
269455ed8ca1SJohan Hedberg 
269555ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
269660b83f57SWaldemar Rymarkiewicz 	if (conn) {
269766138ce8SMarcel Holtmann 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
269866138ce8SMarcel Holtmann 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
2699807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
270055ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
270155ed8ca1SJohan Hedberg 			goto not_found;
270255ed8ca1SJohan Hedberg 		}
270355ed8ca1SJohan Hedberg 
270460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
270560b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
27068fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
27078fc9ced3SGustavo Padovan 			       hdev->name);
270860b83f57SWaldemar Rymarkiewicz 			goto not_found;
270960b83f57SWaldemar Rymarkiewicz 		}
271060b83f57SWaldemar Rymarkiewicz 
271160b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
271260b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
271360b83f57SWaldemar Rymarkiewicz 	}
271460b83f57SWaldemar Rymarkiewicz 
271555ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
27169b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
271755ed8ca1SJohan Hedberg 
271855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
271955ed8ca1SJohan Hedberg 
272055ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
272155ed8ca1SJohan Hedberg 
272255ed8ca1SJohan Hedberg 	return;
272355ed8ca1SJohan Hedberg 
272455ed8ca1SJohan Hedberg not_found:
272555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
272655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
27271da177e4SLinus Torvalds }
27281da177e4SLinus Torvalds 
27296039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
27301da177e4SLinus Torvalds {
2731052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2732052b30b0SMarcel Holtmann 	struct hci_conn *conn;
273355ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2734052b30b0SMarcel Holtmann 
2735a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2736052b30b0SMarcel Holtmann 
2737052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2738052b30b0SMarcel Holtmann 
2739052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2740052b30b0SMarcel Holtmann 	if (conn) {
2741052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2742052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2743980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
274413d39315SWaldemar Rymarkiewicz 
274513d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
274613d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
274713d39315SWaldemar Rymarkiewicz 
274876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2749052b30b0SMarcel Holtmann 	}
2750052b30b0SMarcel Holtmann 
2751034cbea0SAndrei Emeltchenko 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
2752d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
275355ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
275455ed8ca1SJohan Hedberg 
2755052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27561da177e4SLinus Torvalds }
27571da177e4SLinus Torvalds 
27586039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
275904837f64SMarcel Holtmann {
2760a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
276104837f64SMarcel Holtmann 	struct hci_conn *conn;
276204837f64SMarcel Holtmann 
27639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
276404837f64SMarcel Holtmann 
276504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
276604837f64SMarcel Holtmann 
276704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27681da177e4SLinus Torvalds 	if (conn && !ev->status) {
27691da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27701da177e4SLinus Torvalds 
2771cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2772cc11b9c1SAndrei Emeltchenko 		if (ie) {
27731da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27741da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27751da177e4SLinus Torvalds 		}
27761da177e4SLinus Torvalds 	}
27771da177e4SLinus Torvalds 
27781da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27791da177e4SLinus Torvalds }
27801da177e4SLinus Torvalds 
27816039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2782a8746417SMarcel Holtmann {
2783a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2784a8746417SMarcel Holtmann 	struct hci_conn *conn;
2785a8746417SMarcel Holtmann 
27869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2787a8746417SMarcel Holtmann 
2788a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2789a8746417SMarcel Holtmann 
2790a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2791a8746417SMarcel Holtmann 	if (conn && !ev->status)
2792a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2793a8746417SMarcel Holtmann 
2794a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2795a8746417SMarcel Holtmann }
2796a8746417SMarcel Holtmann 
27976039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
279885a1e930SMarcel Holtmann {
2799a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
280085a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
280185a1e930SMarcel Holtmann 
280285a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
280385a1e930SMarcel Holtmann 
280485a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
280585a1e930SMarcel Holtmann 
2806cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2807cc11b9c1SAndrei Emeltchenko 	if (ie) {
280885a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
280985a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
281085a1e930SMarcel Holtmann 	}
281185a1e930SMarcel Holtmann 
281285a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
281385a1e930SMarcel Holtmann }
281485a1e930SMarcel Holtmann 
28156039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2816807deac2SGustavo Padovan 					     struct sk_buff *skb)
2817a9de9248SMarcel Holtmann {
2818a9de9248SMarcel Holtmann 	struct inquiry_data data;
2819a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2820388fc8faSJohan Hedberg 	bool name_known, ssp;
2821a9de9248SMarcel Holtmann 
2822a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2823a9de9248SMarcel Holtmann 
2824a9de9248SMarcel Holtmann 	if (!num_rsp)
2825a9de9248SMarcel Holtmann 		return;
2826a9de9248SMarcel Holtmann 
28271519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
28281519cc17SAndre Guedes 		return;
28291519cc17SAndre Guedes 
2830a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2831a9de9248SMarcel Holtmann 
2832a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2833138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2834138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2835a9de9248SMarcel Holtmann 
2836e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2837a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2838a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2839a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2840a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2841a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2842a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2843a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
284441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28453175405bSJohan Hedberg 
28463175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2847388fc8faSJohan Hedberg 							      false, &ssp);
284848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2849e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2850388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2851a9de9248SMarcel Holtmann 		}
2852a9de9248SMarcel Holtmann 	} else {
2853a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2854a9de9248SMarcel Holtmann 
2855e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2856a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2857a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2858a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2859a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2860a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2861a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2862a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
286341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28643175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2865388fc8faSJohan Hedberg 							      false, &ssp);
286648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2867e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2868388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2869a9de9248SMarcel Holtmann 		}
2870a9de9248SMarcel Holtmann 	}
2871a9de9248SMarcel Holtmann 
2872a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2873a9de9248SMarcel Holtmann }
2874a9de9248SMarcel Holtmann 
28756039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2876807deac2SGustavo Padovan 					struct sk_buff *skb)
2877a9de9248SMarcel Holtmann {
287841a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
287941a96212SMarcel Holtmann 	struct hci_conn *conn;
288041a96212SMarcel Holtmann 
2881a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
288241a96212SMarcel Holtmann 
288341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
288441a96212SMarcel Holtmann 
288541a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2886ccd556feSJohan Hedberg 	if (!conn)
2887ccd556feSJohan Hedberg 		goto unlock;
2888ccd556feSJohan Hedberg 
2889cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
2890cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
2891cad718edSJohan Hedberg 
2892769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
289341a96212SMarcel Holtmann 		struct inquiry_entry *ie;
289441a96212SMarcel Holtmann 
2895cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2896cc11b9c1SAndrei Emeltchenko 		if (ie)
289702b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
289841a96212SMarcel Holtmann 
2899bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
290058a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
2901bbb0eadaSJaganath Kanakkassery 		} else {
2902bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
2903bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
2904bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
2905bbb0eadaSJaganath Kanakkassery 			 * this.
2906bbb0eadaSJaganath Kanakkassery 			 *
2907bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
2908bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
2909bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
2910bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
2911bbb0eadaSJaganath Kanakkassery 		}
2912eb9a8f3fSMarcel Holtmann 
2913eb9a8f3fSMarcel Holtmann 		if (ev->features[0] & LMP_HOST_SC)
2914eb9a8f3fSMarcel Holtmann 			set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
291541a96212SMarcel Holtmann 	}
291641a96212SMarcel Holtmann 
2917ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2918ccd556feSJohan Hedberg 		goto unlock;
2919ccd556feSJohan Hedberg 
2920671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2921127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2922127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2923127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2924127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2925127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2926b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2927b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
292808c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2929b644ba33SJohan Hedberg 				      conn->dev_class);
2930392599b9SJohan Hedberg 
2931127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2932769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2933769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
293476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2935769be974SMarcel Holtmann 	}
2936769be974SMarcel Holtmann 
2937ccd556feSJohan Hedberg unlock:
293841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2939a9de9248SMarcel Holtmann }
2940a9de9248SMarcel Holtmann 
29416039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2942807deac2SGustavo Padovan 				       struct sk_buff *skb)
2943a9de9248SMarcel Holtmann {
2944b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2945b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2946b6a0dc82SMarcel Holtmann 
29479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2948b6a0dc82SMarcel Holtmann 
2949b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2950b6a0dc82SMarcel Holtmann 
2951b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
29529dc0a3afSMarcel Holtmann 	if (!conn) {
29539dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
29549dc0a3afSMarcel Holtmann 			goto unlock;
29559dc0a3afSMarcel Holtmann 
29569dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2957b6a0dc82SMarcel Holtmann 		if (!conn)
2958b6a0dc82SMarcel Holtmann 			goto unlock;
2959b6a0dc82SMarcel Holtmann 
29609dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
29619dc0a3afSMarcel Holtmann 	}
29629dc0a3afSMarcel Holtmann 
2963732547f9SMarcel Holtmann 	switch (ev->status) {
2964732547f9SMarcel Holtmann 	case 0x00:
2965732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2966732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2967732547f9SMarcel Holtmann 
2968732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2969732547f9SMarcel Holtmann 		break;
2970732547f9SMarcel Holtmann 
29711a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
2972705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2973732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29741038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2975732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
29762dea632fSFrédéric Dalleau 		if (conn->out) {
2977efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2978efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
29792dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
2980efc7688bSMarcel Holtmann 				goto unlock;
2981efc7688bSMarcel Holtmann 		}
2982732547f9SMarcel Holtmann 		/* fall through */
2983efc7688bSMarcel Holtmann 
2984732547f9SMarcel Holtmann 	default:
2985b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2986732547f9SMarcel Holtmann 		break;
2987732547f9SMarcel Holtmann 	}
2988b6a0dc82SMarcel Holtmann 
2989b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2990b6a0dc82SMarcel Holtmann 	if (ev->status)
2991b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2992b6a0dc82SMarcel Holtmann 
2993b6a0dc82SMarcel Holtmann unlock:
2994b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2995a9de9248SMarcel Holtmann }
2996a9de9248SMarcel Holtmann 
2997efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len)
2998efdcf8e3SMarcel Holtmann {
2999efdcf8e3SMarcel Holtmann 	size_t parsed = 0;
3000efdcf8e3SMarcel Holtmann 
3001efdcf8e3SMarcel Holtmann 	while (parsed < eir_len) {
3002efdcf8e3SMarcel Holtmann 		u8 field_len = eir[0];
3003efdcf8e3SMarcel Holtmann 
3004efdcf8e3SMarcel Holtmann 		if (field_len == 0)
3005efdcf8e3SMarcel Holtmann 			return parsed;
3006efdcf8e3SMarcel Holtmann 
3007efdcf8e3SMarcel Holtmann 		parsed += field_len + 1;
3008efdcf8e3SMarcel Holtmann 		eir += field_len + 1;
3009efdcf8e3SMarcel Holtmann 	}
3010efdcf8e3SMarcel Holtmann 
3011efdcf8e3SMarcel Holtmann 	return eir_len;
3012efdcf8e3SMarcel Holtmann }
3013efdcf8e3SMarcel Holtmann 
30146039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3015807deac2SGustavo Padovan 					    struct sk_buff *skb)
3016a9de9248SMarcel Holtmann {
3017a9de9248SMarcel Holtmann 	struct inquiry_data data;
3018a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3019a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
30209d939d94SVishal Agarwal 	size_t eir_len;
3021a9de9248SMarcel Holtmann 
3022a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3023a9de9248SMarcel Holtmann 
3024a9de9248SMarcel Holtmann 	if (!num_rsp)
3025a9de9248SMarcel Holtmann 		return;
3026a9de9248SMarcel Holtmann 
30271519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30281519cc17SAndre Guedes 		return;
30291519cc17SAndre Guedes 
3030a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3031a9de9248SMarcel Holtmann 
3032e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3033388fc8faSJohan Hedberg 		bool name_known, ssp;
3034561aafbcSJohan Hedberg 
3035a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3036a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3037a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3038a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3039a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3040a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3041a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
304241a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3043561aafbcSJohan Hedberg 
3044a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
30454ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
30464ddb1930SJohan Hedberg 						       sizeof(info->data),
30474ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3048561aafbcSJohan Hedberg 		else
3049561aafbcSJohan Hedberg 			name_known = true;
3050561aafbcSJohan Hedberg 
3051388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3052388fc8faSJohan Hedberg 						      &ssp);
30539d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
305448264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
305504124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
30569d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3057a9de9248SMarcel Holtmann 	}
3058a9de9248SMarcel Holtmann 
3059a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3060a9de9248SMarcel Holtmann }
3061a9de9248SMarcel Holtmann 
30621c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
30631c2e0041SJohan Hedberg 					 struct sk_buff *skb)
30641c2e0041SJohan Hedberg {
30651c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
30661c2e0041SJohan Hedberg 	struct hci_conn *conn;
30671c2e0041SJohan Hedberg 
30689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
30691c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
30701c2e0041SJohan Hedberg 
30711c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
30721c2e0041SJohan Hedberg 
30731c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30741c2e0041SJohan Hedberg 	if (!conn)
30751c2e0041SJohan Hedberg 		goto unlock;
30761c2e0041SJohan Hedberg 
30771c2e0041SJohan Hedberg 	if (!ev->status)
30781c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
30791c2e0041SJohan Hedberg 
30801c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
30811c2e0041SJohan Hedberg 
30821c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3083bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
308476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
30851c2e0041SJohan Hedberg 		goto unlock;
30861c2e0041SJohan Hedberg 	}
30871c2e0041SJohan Hedberg 
30881c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
30891c2e0041SJohan Hedberg 		if (!ev->status)
30901c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
30911c2e0041SJohan Hedberg 
30921c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
309376a68ba0SDavid Herrmann 		hci_conn_drop(conn);
30941c2e0041SJohan Hedberg 	} else {
30951c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
30961c2e0041SJohan Hedberg 
30971c2e0041SJohan Hedberg 		hci_conn_hold(conn);
30981c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
309976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
31001c2e0041SJohan Hedberg 	}
31011c2e0041SJohan Hedberg 
31021c2e0041SJohan Hedberg unlock:
31031c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
31041c2e0041SJohan Hedberg }
31051c2e0041SJohan Hedberg 
31066039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
310717fa4b9dSJohan Hedberg {
310817fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
3109acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_DEDICATED_BONDING ||
3110acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_DEDICATED_BONDING_MITM) {
311117fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
311217fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
3113acabae96SMikel Astiz 		if (conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT ||
3114acabae96SMikel Astiz 		    conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)
3115acabae96SMikel Astiz 			return HCI_AT_DEDICATED_BONDING;
311617fa4b9dSJohan Hedberg 		else
3117acabae96SMikel Astiz 			return HCI_AT_DEDICATED_BONDING_MITM;
311817fa4b9dSJohan Hedberg 	}
311917fa4b9dSJohan Hedberg 
312017fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
3121acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
3122acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
312358797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
312417fa4b9dSJohan Hedberg 
312517fa4b9dSJohan Hedberg 	return conn->auth_type;
312617fa4b9dSJohan Hedberg }
312717fa4b9dSJohan Hedberg 
31286039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
31290493684eSMarcel Holtmann {
31300493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
31310493684eSMarcel Holtmann 	struct hci_conn *conn;
31320493684eSMarcel Holtmann 
31330493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31340493684eSMarcel Holtmann 
31350493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31360493684eSMarcel Holtmann 
31370493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
313803b555e1SJohan Hedberg 	if (!conn)
313903b555e1SJohan Hedberg 		goto unlock;
314003b555e1SJohan Hedberg 
31410493684eSMarcel Holtmann 	hci_conn_hold(conn);
31420493684eSMarcel Holtmann 
3143a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
314403b555e1SJohan Hedberg 		goto unlock;
314503b555e1SJohan Hedberg 
3146a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
314703b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
314817fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
314917fa4b9dSJohan Hedberg 
315017fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31517a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
31527a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
31537a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
3154a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
31557cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
31567cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
315717fa4b9dSJohan Hedberg 
31588fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
31598fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3160ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3161ce85ee13SSzymon Janc 		else
3162ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3163ce85ee13SSzymon Janc 
316417fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
316517fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
316603b555e1SJohan Hedberg 	} else {
316703b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
316803b555e1SJohan Hedberg 
316903b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31709f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
317103b555e1SJohan Hedberg 
317203b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
317303b555e1SJohan Hedberg 			     sizeof(cp), &cp);
317403b555e1SJohan Hedberg 	}
317503b555e1SJohan Hedberg 
317603b555e1SJohan Hedberg unlock:
317703b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
317803b555e1SJohan Hedberg }
317903b555e1SJohan Hedberg 
31806039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
318103b555e1SJohan Hedberg {
318203b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
318303b555e1SJohan Hedberg 	struct hci_conn *conn;
318403b555e1SJohan Hedberg 
318503b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
318603b555e1SJohan Hedberg 
318703b555e1SJohan Hedberg 	hci_dev_lock(hdev);
318803b555e1SJohan Hedberg 
318903b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
319003b555e1SJohan Hedberg 	if (!conn)
319103b555e1SJohan Hedberg 		goto unlock;
319203b555e1SJohan Hedberg 
319303b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
319403b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
319558a681efSJohan Hedberg 	if (ev->oob_data)
319658a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
319703b555e1SJohan Hedberg 
319803b555e1SJohan Hedberg unlock:
31990493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32000493684eSMarcel Holtmann }
32010493684eSMarcel Holtmann 
32026039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3203a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3204a5c29683SJohan Hedberg {
3205a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
320655bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
32077a828908SJohan Hedberg 	struct hci_conn *conn;
3208a5c29683SJohan Hedberg 
3209a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3210a5c29683SJohan Hedberg 
3211a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3212a5c29683SJohan Hedberg 
3213a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
32147a828908SJohan Hedberg 		goto unlock;
32157a828908SJohan Hedberg 
32167a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32177a828908SJohan Hedberg 	if (!conn)
32187a828908SJohan Hedberg 		goto unlock;
32197a828908SJohan Hedberg 
32207a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
32217a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
32227a828908SJohan Hedberg 
32237a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
32247a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
32257a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
32267a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
32277a828908SJohan Hedberg 	 * bit set. */
3228a767631aSMikel Astiz 	if (!conn->connect_cfm_cb && loc_mitm &&
3229a767631aSMikel Astiz 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
32307a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
32317a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
32327a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
32337a828908SJohan Hedberg 		goto unlock;
32347a828908SJohan Hedberg 	}
32357a828908SJohan Hedberg 
32367a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
3237a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
3238a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
323955bc1a37SJohan Hedberg 
324055bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
324155bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
324255bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
324351a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
324455bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
324555bc1a37SJohan Hedberg 			confirm_hint = 1;
324655bc1a37SJohan Hedberg 			goto confirm;
324755bc1a37SJohan Hedberg 		}
324855bc1a37SJohan Hedberg 
32499f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
32509f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
32519f61656aSJohan Hedberg 
32529f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
32539f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
32547bc18d9dSJohan Hedberg 			queue_delayed_work(conn->hdev->workqueue,
32557bc18d9dSJohan Hedberg 					   &conn->auto_accept_work, delay);
32569f61656aSJohan Hedberg 			goto unlock;
32579f61656aSJohan Hedberg 		}
32589f61656aSJohan Hedberg 
32597a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
32607a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
32617a828908SJohan Hedberg 		goto unlock;
32627a828908SJohan Hedberg 	}
32637a828908SJohan Hedberg 
326455bc1a37SJohan Hedberg confirm:
3265272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
326655bc1a37SJohan Hedberg 				  confirm_hint);
3267a5c29683SJohan Hedberg 
32687a828908SJohan Hedberg unlock:
3269a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3270a5c29683SJohan Hedberg }
3271a5c29683SJohan Hedberg 
32726039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
32731143d458SBrian Gix 					 struct sk_buff *skb)
32741143d458SBrian Gix {
32751143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
32761143d458SBrian Gix 
32771143d458SBrian Gix 	BT_DBG("%s", hdev->name);
32781143d458SBrian Gix 
3279a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3280272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
32811143d458SBrian Gix }
32821143d458SBrian Gix 
328392a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
328492a25256SJohan Hedberg 					struct sk_buff *skb)
328592a25256SJohan Hedberg {
328692a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
328792a25256SJohan Hedberg 	struct hci_conn *conn;
328892a25256SJohan Hedberg 
328992a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
329092a25256SJohan Hedberg 
329192a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
329292a25256SJohan Hedberg 	if (!conn)
329392a25256SJohan Hedberg 		return;
329492a25256SJohan Hedberg 
329592a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
329692a25256SJohan Hedberg 	conn->passkey_entered = 0;
329792a25256SJohan Hedberg 
329892a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
329992a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
330092a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
330192a25256SJohan Hedberg 					 conn->passkey_entered);
330292a25256SJohan Hedberg }
330392a25256SJohan Hedberg 
330492a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
330592a25256SJohan Hedberg {
330692a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
330792a25256SJohan Hedberg 	struct hci_conn *conn;
330892a25256SJohan Hedberg 
330992a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
331092a25256SJohan Hedberg 
331192a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
331292a25256SJohan Hedberg 	if (!conn)
331392a25256SJohan Hedberg 		return;
331492a25256SJohan Hedberg 
331592a25256SJohan Hedberg 	switch (ev->type) {
331692a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
331792a25256SJohan Hedberg 		conn->passkey_entered = 0;
331892a25256SJohan Hedberg 		return;
331992a25256SJohan Hedberg 
332092a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
332192a25256SJohan Hedberg 		conn->passkey_entered++;
332292a25256SJohan Hedberg 		break;
332392a25256SJohan Hedberg 
332492a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
332592a25256SJohan Hedberg 		conn->passkey_entered--;
332692a25256SJohan Hedberg 		break;
332792a25256SJohan Hedberg 
332892a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
332992a25256SJohan Hedberg 		conn->passkey_entered = 0;
333092a25256SJohan Hedberg 		break;
333192a25256SJohan Hedberg 
333292a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
333392a25256SJohan Hedberg 		return;
333492a25256SJohan Hedberg 	}
333592a25256SJohan Hedberg 
333692a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
333792a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
333892a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
333992a25256SJohan Hedberg 					 conn->passkey_entered);
334092a25256SJohan Hedberg }
334192a25256SJohan Hedberg 
33426039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3343807deac2SGustavo Padovan 					 struct sk_buff *skb)
33440493684eSMarcel Holtmann {
33450493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
33460493684eSMarcel Holtmann 	struct hci_conn *conn;
33470493684eSMarcel Holtmann 
33480493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
33490493684eSMarcel Holtmann 
33500493684eSMarcel Holtmann 	hci_dev_lock(hdev);
33510493684eSMarcel Holtmann 
33520493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
33532a611692SJohan Hedberg 	if (!conn)
33542a611692SJohan Hedberg 		goto unlock;
33552a611692SJohan Hedberg 
33562a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
33572a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
33582a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
33592a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
33602a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3361fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3362bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3363bab73cb6SJohan Hedberg 				 ev->status);
33642a611692SJohan Hedberg 
336576a68ba0SDavid Herrmann 	hci_conn_drop(conn);
33660493684eSMarcel Holtmann 
33672a611692SJohan Hedberg unlock:
33680493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
33690493684eSMarcel Holtmann }
33700493684eSMarcel Holtmann 
33716039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3372807deac2SGustavo Padovan 					 struct sk_buff *skb)
337341a96212SMarcel Holtmann {
337441a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
337541a96212SMarcel Holtmann 	struct inquiry_entry *ie;
3376cad718edSJohan Hedberg 	struct hci_conn *conn;
337741a96212SMarcel Holtmann 
337841a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
337941a96212SMarcel Holtmann 
338041a96212SMarcel Holtmann 	hci_dev_lock(hdev);
338141a96212SMarcel Holtmann 
3382cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3383cad718edSJohan Hedberg 	if (conn)
3384cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
3385cad718edSJohan Hedberg 
3386cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3387cc11b9c1SAndrei Emeltchenko 	if (ie)
338802b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
338941a96212SMarcel Holtmann 
339041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
339141a96212SMarcel Holtmann }
339241a96212SMarcel Holtmann 
33936039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
33942763eda6SSzymon Janc 					    struct sk_buff *skb)
33952763eda6SSzymon Janc {
33962763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
33972763eda6SSzymon Janc 	struct oob_data *data;
33982763eda6SSzymon Janc 
33992763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
34002763eda6SSzymon Janc 
34012763eda6SSzymon Janc 	hci_dev_lock(hdev);
34022763eda6SSzymon Janc 
3403a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3404e1ba1f15SSzymon Janc 		goto unlock;
3405e1ba1f15SSzymon Janc 
34062763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
34072763eda6SSzymon Janc 	if (data) {
3408519ca9d0SMarcel Holtmann 		if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
3409519ca9d0SMarcel Holtmann 			struct hci_cp_remote_oob_ext_data_reply cp;
3410519ca9d0SMarcel Holtmann 
3411519ca9d0SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
3412519ca9d0SMarcel Holtmann 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
3413519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer192, data->randomizer192,
3414519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer192));
3415519ca9d0SMarcel Holtmann 			memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
3416519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer256, data->randomizer256,
3417519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer256));
3418519ca9d0SMarcel Holtmann 
3419519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
3420519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3421519ca9d0SMarcel Holtmann 		} else {
34222763eda6SSzymon Janc 			struct hci_cp_remote_oob_data_reply cp;
34232763eda6SSzymon Janc 
34242763eda6SSzymon Janc 			bacpy(&cp.bdaddr, &ev->bdaddr);
3425519ca9d0SMarcel Holtmann 			memcpy(cp.hash, data->hash192, sizeof(cp.hash));
3426519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer, data->randomizer192,
3427519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer));
34282763eda6SSzymon Janc 
3429519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
3430519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3431519ca9d0SMarcel Holtmann 		}
34322763eda6SSzymon Janc 	} else {
34332763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
34342763eda6SSzymon Janc 
34352763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
3436519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
3437519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
34382763eda6SSzymon Janc 	}
34392763eda6SSzymon Janc 
3440e1ba1f15SSzymon Janc unlock:
34412763eda6SSzymon Janc 	hci_dev_unlock(hdev);
34422763eda6SSzymon Janc }
34432763eda6SSzymon Janc 
3444d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3445d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3446d5e91192SAndrei Emeltchenko {
3447d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3448d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3449d5e91192SAndrei Emeltchenko 
3450d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3451d5e91192SAndrei Emeltchenko 	       ev->status);
3452d5e91192SAndrei Emeltchenko 
3453d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3454d5e91192SAndrei Emeltchenko 
3455d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3456d5e91192SAndrei Emeltchenko 	if (!hcon) {
3457d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3458d5e91192SAndrei Emeltchenko 		return;
3459d5e91192SAndrei Emeltchenko 	}
3460d5e91192SAndrei Emeltchenko 
3461d5e91192SAndrei Emeltchenko 	if (ev->status) {
3462d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3463d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3464d5e91192SAndrei Emeltchenko 		return;
3465d5e91192SAndrei Emeltchenko 	}
3466d5e91192SAndrei Emeltchenko 
3467d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3468d5e91192SAndrei Emeltchenko 
3469d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3470d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3471d5e91192SAndrei Emeltchenko 
3472d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3473d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
347476a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
3475d5e91192SAndrei Emeltchenko 
3476d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3477d5e91192SAndrei Emeltchenko 
3478cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
3479cf70ff22SAndrei Emeltchenko 
3480d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3481d5e91192SAndrei Emeltchenko }
3482d5e91192SAndrei Emeltchenko 
348327695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
348427695fb4SAndrei Emeltchenko {
348527695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
348627695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
348727695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
348827695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
348927695fb4SAndrei Emeltchenko 
349027695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
349127695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
349227695fb4SAndrei Emeltchenko 	       ev->status);
349327695fb4SAndrei Emeltchenko 
349427695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
349527695fb4SAndrei Emeltchenko 	if (!hcon)
349627695fb4SAndrei Emeltchenko 		return;
349727695fb4SAndrei Emeltchenko 
349827695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
349927695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
350027695fb4SAndrei Emeltchenko 	if (!hchan)
350127695fb4SAndrei Emeltchenko 		return;
350227695fb4SAndrei Emeltchenko 
350327695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
350427695fb4SAndrei Emeltchenko 
350527695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
350627695fb4SAndrei Emeltchenko 
350727695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
350827695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
350927695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
351027695fb4SAndrei Emeltchenko 
351127695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
351227695fb4SAndrei Emeltchenko 
351327695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
351427695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
351527695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
351627695fb4SAndrei Emeltchenko 
351727695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
351827695fb4SAndrei Emeltchenko 	}
351927695fb4SAndrei Emeltchenko }
352027695fb4SAndrei Emeltchenko 
3521606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3522606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3523606e2a10SAndrei Emeltchenko {
3524606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3525606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3526606e2a10SAndrei Emeltchenko 
3527606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3528606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3529606e2a10SAndrei Emeltchenko 
3530606e2a10SAndrei Emeltchenko 	if (ev->status)
3531606e2a10SAndrei Emeltchenko 		return;
3532606e2a10SAndrei Emeltchenko 
3533606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3534606e2a10SAndrei Emeltchenko 
3535606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3536606e2a10SAndrei Emeltchenko 	if (!hchan)
3537606e2a10SAndrei Emeltchenko 		goto unlock;
3538606e2a10SAndrei Emeltchenko 
3539606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3540606e2a10SAndrei Emeltchenko 
3541606e2a10SAndrei Emeltchenko unlock:
3542606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3543606e2a10SAndrei Emeltchenko }
3544606e2a10SAndrei Emeltchenko 
35459eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
35469eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
35479eef6b3aSAndrei Emeltchenko {
35489eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
35499eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
35509eef6b3aSAndrei Emeltchenko 
35519eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
35529eef6b3aSAndrei Emeltchenko 
35539eef6b3aSAndrei Emeltchenko 	if (ev->status)
35549eef6b3aSAndrei Emeltchenko 		return;
35559eef6b3aSAndrei Emeltchenko 
35569eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
35579eef6b3aSAndrei Emeltchenko 
35589eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
35599eef6b3aSAndrei Emeltchenko 	if (hcon) {
35609eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
35619eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
35629eef6b3aSAndrei Emeltchenko 	}
35639eef6b3aSAndrei Emeltchenko 
35649eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
35659eef6b3aSAndrei Emeltchenko }
35669eef6b3aSAndrei Emeltchenko 
35676039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3568fcd89c09SVille Tervo {
3569fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3570fcd89c09SVille Tervo 	struct hci_conn *conn;
357168d6f6deSJohan Hedberg 	struct smp_irk *irk;
3572fcd89c09SVille Tervo 
35739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3574fcd89c09SVille Tervo 
3575fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3576fcd89c09SVille Tervo 
35774f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3578b62f328bSVille Tervo 	if (!conn) {
3579b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3580b62f328bSVille Tervo 		if (!conn) {
3581b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3582230fd16aSAndre Guedes 			goto unlock;
3583b62f328bSVille Tervo 		}
358429b7988aSAndre Guedes 
358529b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3586b9b343d2SAndre Guedes 
3587880be4e8SMarcel Holtmann 		/* The advertising parameters for own address type
3588880be4e8SMarcel Holtmann 		 * define which source address and source address
3589880be4e8SMarcel Holtmann 		 * type this connections has.
3590880be4e8SMarcel Holtmann 		 */
3591880be4e8SMarcel Holtmann 		if (bacmp(&conn->src, BDADDR_ANY)) {
3592880be4e8SMarcel Holtmann 			conn->src_type = ADDR_LE_DEV_PUBLIC;
3593880be4e8SMarcel Holtmann 		} else {
3594880be4e8SMarcel Holtmann 			bacpy(&conn->src, &hdev->static_addr);
3595880be4e8SMarcel Holtmann 			conn->src_type = ADDR_LE_DEV_RANDOM;
3596880be4e8SMarcel Holtmann 		}
3597880be4e8SMarcel Holtmann 
3598b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3599b9b343d2SAndre Guedes 			conn->out = true;
3600b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3601b9b343d2SAndre Guedes 		}
3602b62f328bSVille Tervo 	}
3603fcd89c09SVille Tervo 
360468d6f6deSJohan Hedberg 	/* Track the connection based on the Identity Address from now on */
360568d6f6deSJohan Hedberg 	irk = hci_get_irk(hdev, &ev->bdaddr, ev->bdaddr_type);
360668d6f6deSJohan Hedberg 	if (irk) {
360768d6f6deSJohan Hedberg 		bacpy(&conn->dst, &irk->bdaddr);
360868d6f6deSJohan Hedberg 		conn->dst_type = irk->addr_type;
360968d6f6deSJohan Hedberg 	}
361068d6f6deSJohan Hedberg 
3611cd17decbSAndre Guedes 	if (ev->status) {
3612cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3613cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3614cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3615cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3616cd17decbSAndre Guedes 		hci_conn_del(conn);
3617cd17decbSAndre Guedes 		goto unlock;
3618cd17decbSAndre Guedes 	}
3619cd17decbSAndre Guedes 
3620b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
362101fdb0fcSMarcel Holtmann 		mgmt_device_connected(hdev, &conn->dst, conn->type,
362295b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
362383bc71b4SVinicius Costa Gomes 
36247b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3625fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3626fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3627fcd89c09SVille Tervo 
362818722c24SJukka Rissanen 	if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
362918722c24SJukka Rissanen 		set_bit(HCI_CONN_6LOWPAN, &conn->flags);
363018722c24SJukka Rissanen 
3631fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3632fcd89c09SVille Tervo 
3633fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3634fcd89c09SVille Tervo 
3635fcd89c09SVille Tervo unlock:
3636fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3637fcd89c09SVille Tervo }
3638fcd89c09SVille Tervo 
36396039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
36409aa04c91SAndre Guedes {
3641e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3642e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
36433c9e9195SAndre Guedes 	s8 rssi;
36449aa04c91SAndre Guedes 
3645e95beb41SAndre Guedes 	while (num_reports--) {
3646e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3647e95beb41SAndre Guedes 
36483c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
36493c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
365004124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
36513c9e9195SAndre Guedes 
3652e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
36539aa04c91SAndre Guedes 	}
36549aa04c91SAndre Guedes }
36559aa04c91SAndre Guedes 
36566039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3657a7a595f6SVinicius Costa Gomes {
3658a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3659a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3660bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3661a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3662c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3663a7a595f6SVinicius Costa Gomes 
36649f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3665a7a595f6SVinicius Costa Gomes 
3666a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3667a7a595f6SVinicius Costa Gomes 
3668a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3669bea710feSVinicius Costa Gomes 	if (conn == NULL)
3670bea710feSVinicius Costa Gomes 		goto not_found;
3671a7a595f6SVinicius Costa Gomes 
367298a0b845SJohan Hedberg 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random, conn->out);
3673bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3674bea710feSVinicius Costa Gomes 		goto not_found;
3675bea710feSVinicius Costa Gomes 
3676bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3677a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3678c9839a11SVinicius Costa Gomes 
3679c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3680f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_HIGH;
3681f8776218SAndre Guedes 	else
3682f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_MEDIUM;
3683a7a595f6SVinicius Costa Gomes 
368489cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
3685a7a595f6SVinicius Costa Gomes 
3686a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3687a7a595f6SVinicius Costa Gomes 
3688c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3689c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3690c9839a11SVinicius Costa Gomes 		kfree(ltk);
3691c9839a11SVinicius Costa Gomes 	}
3692c9839a11SVinicius Costa Gomes 
3693a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3694bea710feSVinicius Costa Gomes 
3695bea710feSVinicius Costa Gomes 	return;
3696bea710feSVinicius Costa Gomes 
3697bea710feSVinicius Costa Gomes not_found:
3698bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3699bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3700bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3701a7a595f6SVinicius Costa Gomes }
3702a7a595f6SVinicius Costa Gomes 
37036039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3704fcd89c09SVille Tervo {
3705fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3706fcd89c09SVille Tervo 
3707fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3708fcd89c09SVille Tervo 
3709fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3710fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3711fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3712fcd89c09SVille Tervo 		break;
3713fcd89c09SVille Tervo 
37149aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
37159aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
37169aa04c91SAndre Guedes 		break;
37179aa04c91SAndre Guedes 
3718a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3719a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3720a7a595f6SVinicius Costa Gomes 		break;
3721a7a595f6SVinicius Costa Gomes 
3722fcd89c09SVille Tervo 	default:
3723fcd89c09SVille Tervo 		break;
3724fcd89c09SVille Tervo 	}
3725fcd89c09SVille Tervo }
3726fcd89c09SVille Tervo 
37279495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
37289495b2eeSAndrei Emeltchenko {
37299495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
37309495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
37319495b2eeSAndrei Emeltchenko 
37329495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
37339495b2eeSAndrei Emeltchenko 
37349495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
37359495b2eeSAndrei Emeltchenko 
37369495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
37379495b2eeSAndrei Emeltchenko 	if (!hcon)
37389495b2eeSAndrei Emeltchenko 		return;
37399495b2eeSAndrei Emeltchenko 
37409495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
37419495b2eeSAndrei Emeltchenko }
37429495b2eeSAndrei Emeltchenko 
37431da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
37441da177e4SLinus Torvalds {
3745a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3746a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
37471da177e4SLinus Torvalds 
3748b6ddb638SJohan Hedberg 	hci_dev_lock(hdev);
3749b6ddb638SJohan Hedberg 
3750b6ddb638SJohan Hedberg 	/* Received events are (currently) only needed when a request is
3751b6ddb638SJohan Hedberg 	 * ongoing so avoid unnecessary memory allocation.
3752b6ddb638SJohan Hedberg 	 */
3753b6ddb638SJohan Hedberg 	if (hdev->req_status == HCI_REQ_PEND) {
3754b6ddb638SJohan Hedberg 		kfree_skb(hdev->recv_evt);
3755b6ddb638SJohan Hedberg 		hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
3756b6ddb638SJohan Hedberg 	}
3757b6ddb638SJohan Hedberg 
3758b6ddb638SJohan Hedberg 	hci_dev_unlock(hdev);
3759b6ddb638SJohan Hedberg 
37601da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
37611da177e4SLinus Torvalds 
376202350a72SJohan Hedberg 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
3763c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
3764c1f23a2bSJohannes Berg 		u16 opcode = __le16_to_cpu(cmd_hdr->opcode);
376502350a72SJohan Hedberg 
376602350a72SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, 0);
376702350a72SJohan Hedberg 	}
376802350a72SJohan Hedberg 
3769a9de9248SMarcel Holtmann 	switch (event) {
37701da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
37711da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
37721da177e4SLinus Torvalds 		break;
37731da177e4SLinus Torvalds 
37741da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
37751da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
37761da177e4SLinus Torvalds 		break;
37771da177e4SLinus Torvalds 
3778a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3779a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
378021d9e30eSMarcel Holtmann 		break;
378121d9e30eSMarcel Holtmann 
37821da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
37831da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
37841da177e4SLinus Torvalds 		break;
37851da177e4SLinus Torvalds 
37861da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
37871da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
37881da177e4SLinus Torvalds 		break;
37891da177e4SLinus Torvalds 
37901da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
37911da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
37921da177e4SLinus Torvalds 		break;
37931da177e4SLinus Torvalds 
3794a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3795a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3796a9de9248SMarcel Holtmann 		break;
3797a9de9248SMarcel Holtmann 
37981da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
37991da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
38001da177e4SLinus Torvalds 		break;
38011da177e4SLinus Torvalds 
3802a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3803a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3804a9de9248SMarcel Holtmann 		break;
3805a9de9248SMarcel Holtmann 
3806a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3807a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3808a9de9248SMarcel Holtmann 		break;
3809a9de9248SMarcel Holtmann 
3810a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3811a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3812a9de9248SMarcel Holtmann 		break;
3813a9de9248SMarcel Holtmann 
3814a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3815a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3816a9de9248SMarcel Holtmann 		break;
3817a9de9248SMarcel Holtmann 
3818a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3819a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3820a9de9248SMarcel Holtmann 		break;
3821a9de9248SMarcel Holtmann 
3822a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3823a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3824a9de9248SMarcel Holtmann 		break;
3825a9de9248SMarcel Holtmann 
3826a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3827a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
38281da177e4SLinus Torvalds 		break;
38291da177e4SLinus Torvalds 
38301da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
38311da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
38321da177e4SLinus Torvalds 		break;
38331da177e4SLinus Torvalds 
38341da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
38351da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
38361da177e4SLinus Torvalds 		break;
38371da177e4SLinus Torvalds 
38381da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
38391da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
38401da177e4SLinus Torvalds 		break;
38411da177e4SLinus Torvalds 
38421da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
38431da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
38441da177e4SLinus Torvalds 		break;
38451da177e4SLinus Torvalds 
3846a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3847a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3848a8746417SMarcel Holtmann 		break;
3849a8746417SMarcel Holtmann 
385085a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
385185a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
385285a1e930SMarcel Holtmann 		break;
385385a1e930SMarcel Holtmann 
3854a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3855a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3856a9de9248SMarcel Holtmann 		break;
3857a9de9248SMarcel Holtmann 
3858a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3859a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3860a9de9248SMarcel Holtmann 		break;
3861a9de9248SMarcel Holtmann 
3862a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3863a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3864a9de9248SMarcel Holtmann 		break;
3865a9de9248SMarcel Holtmann 
3866a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3867a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
38681da177e4SLinus Torvalds 		break;
38691da177e4SLinus Torvalds 
38701c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
38711c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
38721c2e0041SJohan Hedberg 		break;
38731c2e0041SJohan Hedberg 
38740493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
38750493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
38760493684eSMarcel Holtmann 		break;
38770493684eSMarcel Holtmann 
387803b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
387903b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
388003b555e1SJohan Hedberg 		break;
388103b555e1SJohan Hedberg 
3882a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3883a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3884a5c29683SJohan Hedberg 		break;
3885a5c29683SJohan Hedberg 
38861143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
38871143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
38881143d458SBrian Gix 		break;
38891143d458SBrian Gix 
389092a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
389192a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
389292a25256SJohan Hedberg 		break;
389392a25256SJohan Hedberg 
389492a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
389592a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
389692a25256SJohan Hedberg 		break;
389792a25256SJohan Hedberg 
38980493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
38990493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
39000493684eSMarcel Holtmann 		break;
39010493684eSMarcel Holtmann 
390241a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
390341a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
390441a96212SMarcel Holtmann 		break;
390541a96212SMarcel Holtmann 
3906fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3907fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3908fcd89c09SVille Tervo 		break;
3909fcd89c09SVille Tervo 
39109495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
39119495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
39129495b2eeSAndrei Emeltchenko 		break;
39139495b2eeSAndrei Emeltchenko 
39142763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
39152763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
39162763eda6SSzymon Janc 		break;
39172763eda6SSzymon Janc 
3918d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
3919d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
3920d5e91192SAndrei Emeltchenko 		break;
3921d5e91192SAndrei Emeltchenko 
392227695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
392327695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
392427695fb4SAndrei Emeltchenko 		break;
392527695fb4SAndrei Emeltchenko 
3926606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
3927606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
3928606e2a10SAndrei Emeltchenko 		break;
3929606e2a10SAndrei Emeltchenko 
39309eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
39319eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
39329eef6b3aSAndrei Emeltchenko 		break;
39339eef6b3aSAndrei Emeltchenko 
393425e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
393525e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
393625e89e99SAndrei Emeltchenko 		break;
393725e89e99SAndrei Emeltchenko 
39381da177e4SLinus Torvalds 	default:
39399f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
39401da177e4SLinus Torvalds 		break;
39411da177e4SLinus Torvalds 	}
39421da177e4SLinus Torvalds 
39431da177e4SLinus Torvalds 	kfree_skb(skb);
39441da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
39451da177e4SLinus Torvalds }
3946