xref: /openbmc/linux/net/bluetooth/hci_event.c (revision a4790dbd)
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 
9627a4cd51dSMarcel Holtmann 
9637a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
9647a4cd51dSMarcel Holtmann {
9657a4cd51dSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
9667a4cd51dSMarcel Holtmann 	bdaddr_t *sent;
9677a4cd51dSMarcel Holtmann 
9687a4cd51dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
9697a4cd51dSMarcel Holtmann 
9707a4cd51dSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
9717a4cd51dSMarcel Holtmann 	if (!sent)
9727a4cd51dSMarcel Holtmann 		return;
9737a4cd51dSMarcel Holtmann 
9747a4cd51dSMarcel Holtmann 	hci_dev_lock(hdev);
9757a4cd51dSMarcel Holtmann 
9767a4cd51dSMarcel Holtmann 	if (!status)
9777a4cd51dSMarcel Holtmann 		bacpy(&hdev->random_addr, sent);
9787a4cd51dSMarcel Holtmann 
9797a4cd51dSMarcel Holtmann 	hci_dev_unlock(hdev);
9807a4cd51dSMarcel Holtmann }
9817a4cd51dSMarcel Holtmann 
982c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
983c1d5dc4aSJohan Hedberg {
984c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
985c1d5dc4aSJohan Hedberg 
986c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
987c1d5dc4aSJohan Hedberg 
988c1d5dc4aSJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
989c1d5dc4aSJohan Hedberg 	if (!sent)
990c1d5dc4aSJohan Hedberg 		return;
991c1d5dc4aSJohan Hedberg 
992c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
993c1d5dc4aSJohan Hedberg 
994778b235aSJohan Hedberg 	if (!status)
995778b235aSJohan Hedberg 		mgmt_advertising(hdev, *sent);
996c1d5dc4aSJohan Hedberg 
99704b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
998c1d5dc4aSJohan Hedberg }
999c1d5dc4aSJohan Hedberg 
1000eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1001eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1002eb9d91f5SAndre Guedes {
1003eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1004eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1005eb9d91f5SAndre Guedes 
10069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1007eb9d91f5SAndre Guedes 
1008eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1009eb9d91f5SAndre Guedes 	if (!cp)
1010eb9d91f5SAndre Guedes 		return;
1011eb9d91f5SAndre Guedes 
1012fef5234aSAndre Guedes 	if (status)
10137ba8b4beSAndre Guedes 		return;
10147ba8b4beSAndre Guedes 
10153fd319b8SAndre Guedes 	switch (cp->enable) {
10163fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
1017d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
101868a8aea4SAndrei Emeltchenko 		break;
101968a8aea4SAndrei Emeltchenko 
102076a388beSAndre Guedes 	case LE_SCAN_DISABLE:
1021d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
102268a8aea4SAndrei Emeltchenko 		break;
102368a8aea4SAndrei Emeltchenko 
102468a8aea4SAndrei Emeltchenko 	default:
102568a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
102668a8aea4SAndrei Emeltchenko 		break;
102735815085SAndre Guedes 	}
1028eb9d91f5SAndre Guedes }
1029eb9d91f5SAndre Guedes 
1030cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1031cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
1032cf1d081fSJohan Hedberg {
1033cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1034cf1d081fSJohan Hedberg 
1035cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1036cf1d081fSJohan Hedberg 
1037cf1d081fSJohan Hedberg 	if (!rp->status)
1038cf1d081fSJohan Hedberg 		hdev->le_white_list_size = rp->size;
1039cf1d081fSJohan Hedberg }
1040cf1d081fSJohan Hedberg 
10419b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
10429b008c04SJohan Hedberg 					    struct sk_buff *skb)
10439b008c04SJohan Hedberg {
10449b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
10459b008c04SJohan Hedberg 
10469b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10479b008c04SJohan Hedberg 
10489b008c04SJohan Hedberg 	if (!rp->status)
10499b008c04SJohan Hedberg 		memcpy(hdev->le_states, rp->le_states, 8);
10509b008c04SJohan Hedberg }
10519b008c04SJohan Hedberg 
10526039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1053f9b49306SAndre Guedes 					   struct sk_buff *skb)
1054f9b49306SAndre Guedes {
105506199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1056f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1057f9b49306SAndre Guedes 
10589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1059f9b49306SAndre Guedes 
106006199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
10618f984dfaSJohan Hedberg 	if (!sent)
1062f9b49306SAndre Guedes 		return;
1063f9b49306SAndre Guedes 
10648f984dfaSJohan Hedberg 	if (!status) {
1065416a4ae5SJohan Hedberg 		if (sent->le) {
1066cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE;
1067416a4ae5SJohan Hedberg 			set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1068416a4ae5SJohan Hedberg 		} else {
1069cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE;
1070416a4ae5SJohan Hedberg 			clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1071f3d3444aSJohan Hedberg 			clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1072416a4ae5SJohan Hedberg 		}
107353b2caabSJohan Hedberg 
107453b2caabSJohan Hedberg 		if (sent->simul)
1075cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE_BREDR;
107653b2caabSJohan Hedberg 		else
1077cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
10788f984dfaSJohan Hedberg 	}
1079f9b49306SAndre Guedes }
1080f9b49306SAndre Guedes 
108193c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
108293c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
108393c284eeSAndrei Emeltchenko {
108493c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
108593c284eeSAndrei Emeltchenko 
108693c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
108793c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
108893c284eeSAndrei Emeltchenko 
108993c284eeSAndrei Emeltchenko 	if (rp->status)
109093c284eeSAndrei Emeltchenko 		return;
109193c284eeSAndrei Emeltchenko 
109293c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
109393c284eeSAndrei Emeltchenko }
109493c284eeSAndrei Emeltchenko 
10956039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1096a9de9248SMarcel Holtmann {
10979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1098a9de9248SMarcel Holtmann 
1099a9de9248SMarcel Holtmann 	if (status) {
1100a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1101314b2381SJohan Hedberg 		return;
1102314b2381SJohan Hedberg 	}
1103314b2381SJohan Hedberg 
110489352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1105a9de9248SMarcel Holtmann }
1106a9de9248SMarcel Holtmann 
11076039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11081da177e4SLinus Torvalds {
1109a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11101da177e4SLinus Torvalds 	struct hci_conn *conn;
11111da177e4SLinus Torvalds 
11129f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1113a9de9248SMarcel Holtmann 
1114a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11151da177e4SLinus Torvalds 	if (!cp)
11161da177e4SLinus Torvalds 		return;
11171da177e4SLinus Torvalds 
11181da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11191da177e4SLinus Torvalds 
11201da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11211da177e4SLinus Torvalds 
11226ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
11231da177e4SLinus Torvalds 
11241da177e4SLinus Torvalds 	if (status) {
11251da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11264c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11271da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11281da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11291da177e4SLinus Torvalds 				hci_conn_del(conn);
11304c67bc74SMarcel Holtmann 			} else
11314c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11321da177e4SLinus Torvalds 		}
11331da177e4SLinus Torvalds 	} else {
11341da177e4SLinus Torvalds 		if (!conn) {
11351da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11361da177e4SLinus Torvalds 			if (conn) {
1137a0c808b3SJohan Hedberg 				conn->out = true;
11381da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11391da177e4SLinus Torvalds 			} else
1140893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11411da177e4SLinus Torvalds 		}
11421da177e4SLinus Torvalds 	}
11431da177e4SLinus Torvalds 
11441da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11451da177e4SLinus Torvalds }
11461da177e4SLinus Torvalds 
1147a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11481da177e4SLinus Torvalds {
1149a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11501da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11511da177e4SLinus Torvalds 	__u16 handle;
11521da177e4SLinus Torvalds 
11539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1154b6a0dc82SMarcel Holtmann 
1155a9de9248SMarcel Holtmann 	if (!status)
1156a9de9248SMarcel Holtmann 		return;
1157a9de9248SMarcel Holtmann 
1158a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11591da177e4SLinus Torvalds 	if (!cp)
1160a9de9248SMarcel Holtmann 		return;
11611da177e4SLinus Torvalds 
11621da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11631da177e4SLinus Torvalds 
11649f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
11651da177e4SLinus Torvalds 
11661da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11671da177e4SLinus Torvalds 
11681da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11695a08ecceSAndrei Emeltchenko 	if (acl) {
11705a08ecceSAndrei Emeltchenko 		sco = acl->link;
11715a08ecceSAndrei Emeltchenko 		if (sco) {
11721da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11731da177e4SLinus Torvalds 
11741da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11751da177e4SLinus Torvalds 			hci_conn_del(sco);
11761da177e4SLinus Torvalds 		}
11775a08ecceSAndrei Emeltchenko 	}
11781da177e4SLinus Torvalds 
11791da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11801da177e4SLinus Torvalds }
11811da177e4SLinus Torvalds 
1182f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1183f8558555SMarcel Holtmann {
1184f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1185f8558555SMarcel Holtmann 	struct hci_conn *conn;
1186f8558555SMarcel Holtmann 
11879f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1188f8558555SMarcel Holtmann 
1189f8558555SMarcel Holtmann 	if (!status)
1190f8558555SMarcel Holtmann 		return;
1191f8558555SMarcel Holtmann 
1192f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1193f8558555SMarcel Holtmann 	if (!cp)
1194f8558555SMarcel Holtmann 		return;
1195f8558555SMarcel Holtmann 
1196f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1197f8558555SMarcel Holtmann 
1198f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1199f8558555SMarcel Holtmann 	if (conn) {
1200f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1201f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
120276a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1203f8558555SMarcel Holtmann 		}
1204f8558555SMarcel Holtmann 	}
1205f8558555SMarcel Holtmann 
1206f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1207f8558555SMarcel Holtmann }
1208f8558555SMarcel Holtmann 
1209f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1210f8558555SMarcel Holtmann {
1211f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1212f8558555SMarcel Holtmann 	struct hci_conn *conn;
1213f8558555SMarcel Holtmann 
12149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1215f8558555SMarcel Holtmann 
1216f8558555SMarcel Holtmann 	if (!status)
1217f8558555SMarcel Holtmann 		return;
1218f8558555SMarcel Holtmann 
1219f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1220f8558555SMarcel Holtmann 	if (!cp)
1221f8558555SMarcel Holtmann 		return;
1222f8558555SMarcel Holtmann 
1223f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1224f8558555SMarcel Holtmann 
1225f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1226f8558555SMarcel Holtmann 	if (conn) {
1227f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1228f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
122976a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1230f8558555SMarcel Holtmann 		}
1231f8558555SMarcel Holtmann 	}
1232f8558555SMarcel Holtmann 
1233f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1234f8558555SMarcel Holtmann }
1235f8558555SMarcel Holtmann 
1236127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1237392599b9SJohan Hedberg 				    struct hci_conn *conn)
1238392599b9SJohan Hedberg {
1239392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1240392599b9SJohan Hedberg 		return 0;
1241392599b9SJohan Hedberg 
1242765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1243392599b9SJohan Hedberg 		return 0;
1244392599b9SJohan Hedberg 
1245392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1246264b8b4eSJohan Hedberg 	 * devices with sec_level MEDIUM or HIGH or if MITM protection
1247264b8b4eSJohan Hedberg 	 * is requested.
1248264b8b4eSJohan Hedberg 	 */
1249807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1250264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
1251264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
1252392599b9SJohan Hedberg 		return 0;
1253392599b9SJohan Hedberg 
1254392599b9SJohan Hedberg 	return 1;
1255392599b9SJohan Hedberg }
1256392599b9SJohan Hedberg 
12576039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
125800abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
125930dc78e1SJohan Hedberg {
126030dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
126130dc78e1SJohan Hedberg 
126230dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
126330dc78e1SJohan Hedberg 
126430dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
126530dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
126630dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
126730dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
126830dc78e1SJohan Hedberg 
126930dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
127030dc78e1SJohan Hedberg }
127130dc78e1SJohan Hedberg 
1272b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
127330dc78e1SJohan Hedberg {
127430dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
127530dc78e1SJohan Hedberg 	struct inquiry_entry *e;
127630dc78e1SJohan Hedberg 
1277b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1278b644ba33SJohan Hedberg 		return false;
1279b644ba33SJohan Hedberg 
1280b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1281c810089cSRam Malovany 	if (!e)
1282c810089cSRam Malovany 		return false;
1283c810089cSRam Malovany 
1284b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1285b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1286b644ba33SJohan Hedberg 		return true;
1287b644ba33SJohan Hedberg 	}
1288b644ba33SJohan Hedberg 
1289b644ba33SJohan Hedberg 	return false;
1290b644ba33SJohan Hedberg }
1291b644ba33SJohan Hedberg 
1292b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1293b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1294b644ba33SJohan Hedberg {
1295b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1296b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1297b644ba33SJohan Hedberg 
1298b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
129904124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
130004124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1301b644ba33SJohan Hedberg 
1302b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1303b644ba33SJohan Hedberg 		return;
1304b644ba33SJohan Hedberg 
130530dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
130630dc78e1SJohan Hedberg 		goto discov_complete;
130730dc78e1SJohan Hedberg 
130830dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
130930dc78e1SJohan Hedberg 		return;
131030dc78e1SJohan Hedberg 
131130dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
13127cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
13137cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
13147cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
13157cc8380eSRam Malovany 	 * Event */
13167cc8380eSRam Malovany 	if (!e)
13177cc8380eSRam Malovany 		return;
13187cc8380eSRam Malovany 
131930dc78e1SJohan Hedberg 	list_del(&e->list);
13207cc8380eSRam Malovany 	if (name) {
13217cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1322b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1323b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1324c3e7c0d9SRam Malovany 	} else {
1325c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
132630dc78e1SJohan Hedberg 	}
132730dc78e1SJohan Hedberg 
1328b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
132930dc78e1SJohan Hedberg 		return;
133030dc78e1SJohan Hedberg 
133130dc78e1SJohan Hedberg discov_complete:
133230dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
133330dc78e1SJohan Hedberg }
133430dc78e1SJohan Hedberg 
1335a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13361da177e4SLinus Torvalds {
1337127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1338127178d2SJohan Hedberg 	struct hci_conn *conn;
1339127178d2SJohan Hedberg 
13409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1341127178d2SJohan Hedberg 
1342127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1343127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1344127178d2SJohan Hedberg 	if (!status)
1345127178d2SJohan Hedberg 		return;
1346127178d2SJohan Hedberg 
1347127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1348127178d2SJohan Hedberg 	if (!cp)
1349127178d2SJohan Hedberg 		return;
1350127178d2SJohan Hedberg 
1351127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1352127178d2SJohan Hedberg 
1353127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1354b644ba33SJohan Hedberg 
1355b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1356b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1357b644ba33SJohan Hedberg 
135879c6c70cSJohan Hedberg 	if (!conn)
135979c6c70cSJohan Hedberg 		goto unlock;
136079c6c70cSJohan Hedberg 
136179c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
136279c6c70cSJohan Hedberg 		goto unlock;
136379c6c70cSJohan Hedberg 
136451a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1365c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
1366c1f23a2bSJohannes Berg 
1367c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
1368c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1369c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
1370127178d2SJohan Hedberg 	}
1371127178d2SJohan Hedberg 
137279c6c70cSJohan Hedberg unlock:
1373127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1374a9de9248SMarcel Holtmann }
13751da177e4SLinus Torvalds 
1376769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1377769be974SMarcel Holtmann {
1378769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1379769be974SMarcel Holtmann 	struct hci_conn *conn;
1380769be974SMarcel Holtmann 
13819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1382769be974SMarcel Holtmann 
1383769be974SMarcel Holtmann 	if (!status)
1384769be974SMarcel Holtmann 		return;
1385769be974SMarcel Holtmann 
1386769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1387769be974SMarcel Holtmann 	if (!cp)
1388769be974SMarcel Holtmann 		return;
1389769be974SMarcel Holtmann 
1390769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1391769be974SMarcel Holtmann 
1392769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1393769be974SMarcel Holtmann 	if (conn) {
1394769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1395769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
139676a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1397769be974SMarcel Holtmann 		}
1398769be974SMarcel Holtmann 	}
1399769be974SMarcel Holtmann 
1400769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1401769be974SMarcel Holtmann }
1402769be974SMarcel Holtmann 
1403769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1404769be974SMarcel Holtmann {
1405769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1406769be974SMarcel Holtmann 	struct hci_conn *conn;
1407769be974SMarcel Holtmann 
14089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1409769be974SMarcel Holtmann 
1410769be974SMarcel Holtmann 	if (!status)
1411769be974SMarcel Holtmann 		return;
1412769be974SMarcel Holtmann 
1413769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1414769be974SMarcel Holtmann 	if (!cp)
1415769be974SMarcel Holtmann 		return;
1416769be974SMarcel Holtmann 
1417769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1418769be974SMarcel Holtmann 
1419769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1420769be974SMarcel Holtmann 	if (conn) {
1421769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1422769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
142376a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1424769be974SMarcel Holtmann 		}
1425769be974SMarcel Holtmann 	}
1426769be974SMarcel Holtmann 
1427769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1428769be974SMarcel Holtmann }
1429769be974SMarcel Holtmann 
1430a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1431a9de9248SMarcel Holtmann {
1432b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1433b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1434b6a0dc82SMarcel Holtmann 	__u16 handle;
1435b6a0dc82SMarcel Holtmann 
14369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1437b6a0dc82SMarcel Holtmann 
1438b6a0dc82SMarcel Holtmann 	if (!status)
1439b6a0dc82SMarcel Holtmann 		return;
1440b6a0dc82SMarcel Holtmann 
1441b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1442b6a0dc82SMarcel Holtmann 	if (!cp)
1443b6a0dc82SMarcel Holtmann 		return;
1444b6a0dc82SMarcel Holtmann 
1445b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1446b6a0dc82SMarcel Holtmann 
14479f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1448b6a0dc82SMarcel Holtmann 
1449b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1450b6a0dc82SMarcel Holtmann 
1451b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14525a08ecceSAndrei Emeltchenko 	if (acl) {
14535a08ecceSAndrei Emeltchenko 		sco = acl->link;
14545a08ecceSAndrei Emeltchenko 		if (sco) {
1455b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1456b6a0dc82SMarcel Holtmann 
1457b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1458b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1459b6a0dc82SMarcel Holtmann 		}
14605a08ecceSAndrei Emeltchenko 	}
1461b6a0dc82SMarcel Holtmann 
1462b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1463a9de9248SMarcel Holtmann }
1464a9de9248SMarcel Holtmann 
1465a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1466a9de9248SMarcel Holtmann {
1467a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
146804837f64SMarcel Holtmann 	struct hci_conn *conn;
146904837f64SMarcel Holtmann 
14709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1471a9de9248SMarcel Holtmann 
1472a9de9248SMarcel Holtmann 	if (!status)
1473a9de9248SMarcel Holtmann 		return;
1474a9de9248SMarcel Holtmann 
1475a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
147604837f64SMarcel Holtmann 	if (!cp)
1477a9de9248SMarcel Holtmann 		return;
147804837f64SMarcel Holtmann 
147904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
148004837f64SMarcel Holtmann 
148104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1482e73439d8SMarcel Holtmann 	if (conn) {
148351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
148404837f64SMarcel Holtmann 
148551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1486e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1487e73439d8SMarcel Holtmann 	}
1488e73439d8SMarcel Holtmann 
148904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
149004837f64SMarcel Holtmann }
149104837f64SMarcel Holtmann 
1492a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1493a9de9248SMarcel Holtmann {
1494a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
149504837f64SMarcel Holtmann 	struct hci_conn *conn;
149604837f64SMarcel Holtmann 
14979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1498a9de9248SMarcel Holtmann 
1499a9de9248SMarcel Holtmann 	if (!status)
1500a9de9248SMarcel Holtmann 		return;
1501a9de9248SMarcel Holtmann 
1502a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
150304837f64SMarcel Holtmann 	if (!cp)
1504a9de9248SMarcel Holtmann 		return;
150504837f64SMarcel Holtmann 
150604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
150704837f64SMarcel Holtmann 
150804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1509e73439d8SMarcel Holtmann 	if (conn) {
151051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
151104837f64SMarcel Holtmann 
151251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1513e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1514e73439d8SMarcel Holtmann 	}
1515e73439d8SMarcel Holtmann 
151604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
151704837f64SMarcel Holtmann }
151804837f64SMarcel Holtmann 
151988c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
152088c3df13SJohan Hedberg {
152188c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
152288c3df13SJohan Hedberg 	struct hci_conn *conn;
152388c3df13SJohan Hedberg 
152488c3df13SJohan Hedberg 	if (!status)
152588c3df13SJohan Hedberg 		return;
152688c3df13SJohan Hedberg 
152788c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
152888c3df13SJohan Hedberg 	if (!cp)
152988c3df13SJohan Hedberg 		return;
153088c3df13SJohan Hedberg 
153188c3df13SJohan Hedberg 	hci_dev_lock(hdev);
153288c3df13SJohan Hedberg 
153388c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
153488c3df13SJohan Hedberg 	if (conn)
153588c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
153688c3df13SJohan Hedberg 				       conn->dst_type, status);
153788c3df13SJohan Hedberg 
153888c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
153988c3df13SJohan Hedberg }
154088c3df13SJohan Hedberg 
1541a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1542a02226d6SAndrei Emeltchenko {
154393c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
154493c284eeSAndrei Emeltchenko 
1545a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
154693c284eeSAndrei Emeltchenko 
154793c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
154893c284eeSAndrei Emeltchenko 	if (!cp)
154993c284eeSAndrei Emeltchenko 		return;
155093c284eeSAndrei Emeltchenko 
1551e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1552e58917b9SAndrei Emeltchenko 
1553e58917b9SAndrei Emeltchenko 	if (status) {
1554e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1555e58917b9SAndrei Emeltchenko 
1556e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1557e58917b9SAndrei Emeltchenko 		if (hcon)
1558e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1559e58917b9SAndrei Emeltchenko 	} else {
156093c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1561a02226d6SAndrei Emeltchenko 	}
1562a02226d6SAndrei Emeltchenko 
1563e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1564e58917b9SAndrei Emeltchenko }
1565e58917b9SAndrei Emeltchenko 
15660b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
15670b26ab9dSAndrei Emeltchenko {
15680b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
15690b26ab9dSAndrei Emeltchenko 
15700b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15710b26ab9dSAndrei Emeltchenko 
15720b26ab9dSAndrei Emeltchenko 	if (status)
15730b26ab9dSAndrei Emeltchenko 		return;
15740b26ab9dSAndrei Emeltchenko 
15750b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
15760b26ab9dSAndrei Emeltchenko 	if (!cp)
15770b26ab9dSAndrei Emeltchenko 		return;
15780b26ab9dSAndrei Emeltchenko 
15790b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
15800b26ab9dSAndrei Emeltchenko }
15810b26ab9dSAndrei Emeltchenko 
15826039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15831da177e4SLinus Torvalds {
15841da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
158530dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
158630dc78e1SJohan Hedberg 	struct inquiry_entry *e;
15871da177e4SLinus Torvalds 
15889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15891da177e4SLinus Torvalds 
1590a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
159189352e7dSAndre Guedes 
159289352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
159389352e7dSAndre Guedes 		return;
159489352e7dSAndre Guedes 
15953e13fa1eSAndre Guedes 	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
15963e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
15973e13fa1eSAndre Guedes 
1598a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
159930dc78e1SJohan Hedberg 		return;
160030dc78e1SJohan Hedberg 
160156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
160230dc78e1SJohan Hedberg 
1603343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
160430dc78e1SJohan Hedberg 		goto unlock;
160530dc78e1SJohan Hedberg 
160630dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1607ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
160830dc78e1SJohan Hedberg 		goto unlock;
160930dc78e1SJohan Hedberg 	}
161030dc78e1SJohan Hedberg 
161130dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
161230dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
161330dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
161430dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
161530dc78e1SJohan Hedberg 	} else {
161630dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
161730dc78e1SJohan Hedberg 	}
161830dc78e1SJohan Hedberg 
161930dc78e1SJohan Hedberg unlock:
162056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16211da177e4SLinus Torvalds }
16221da177e4SLinus Torvalds 
16236039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16241da177e4SLinus Torvalds {
162545bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1626a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16271da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16281da177e4SLinus Torvalds 
16291da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16301da177e4SLinus Torvalds 
163145bb4bf0SMarcel Holtmann 	if (!num_rsp)
163245bb4bf0SMarcel Holtmann 		return;
163345bb4bf0SMarcel Holtmann 
16341519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
16351519cc17SAndre Guedes 		return;
16361519cc17SAndre Guedes 
16371da177e4SLinus Torvalds 	hci_dev_lock(hdev);
163845bb4bf0SMarcel Holtmann 
1639e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1640388fc8faSJohan Hedberg 		bool name_known, ssp;
16413175405bSJohan Hedberg 
16421da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16431da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16441da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16451da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16461da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16471da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16481da177e4SLinus Torvalds 		data.rssi		= 0x00;
164941a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16503175405bSJohan Hedberg 
1651388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
165248264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
165304124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
165404124681SGustavo F. Padovan 				  0);
16551da177e4SLinus Torvalds 	}
165645bb4bf0SMarcel Holtmann 
16571da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16581da177e4SLinus Torvalds }
16591da177e4SLinus Torvalds 
16606039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16611da177e4SLinus Torvalds {
1662a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1663a9de9248SMarcel Holtmann 	struct hci_conn *conn;
16641da177e4SLinus Torvalds 
1665a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
166645bb4bf0SMarcel Holtmann 
16671da177e4SLinus Torvalds 	hci_dev_lock(hdev);
166845bb4bf0SMarcel Holtmann 
1669a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16709499237aSMarcel Holtmann 	if (!conn) {
16719499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16729499237aSMarcel Holtmann 			goto unlock;
16739499237aSMarcel Holtmann 
16749499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1675a9de9248SMarcel Holtmann 		if (!conn)
1676a9de9248SMarcel Holtmann 			goto unlock;
167745bb4bf0SMarcel Holtmann 
16789499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16799499237aSMarcel Holtmann 	}
16809499237aSMarcel Holtmann 
1681a9de9248SMarcel Holtmann 	if (!ev->status) {
1682a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1683769be974SMarcel Holtmann 
1684769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1685769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1686769be974SMarcel Holtmann 			hci_conn_hold(conn);
1687a9ea3ed9SSzymon Janc 
1688a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1689a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1690a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1691a9ea3ed9SSzymon Janc 			else
1692052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1693769be974SMarcel Holtmann 		} else
1694a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1695a9de9248SMarcel Holtmann 
16967d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
16977d0db0a3SMarcel Holtmann 
1698a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1699a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1700a9de9248SMarcel Holtmann 
1701a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1702a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1703a9de9248SMarcel Holtmann 
1704a9de9248SMarcel Holtmann 		/* Get remote features */
1705a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1706a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1707a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1708769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1709769be974SMarcel Holtmann 				     sizeof(cp), &cp);
171045bb4bf0SMarcel Holtmann 		}
1711a9de9248SMarcel Holtmann 
1712a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1713d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1714a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1715a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1716a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
171704124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
171804124681SGustavo F. Padovan 				     &cp);
1719a9de9248SMarcel Holtmann 		}
172017d5c04cSJohan Hedberg 	} else {
1721a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
172217d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
172364c7b77cSMarcel Holtmann 			mgmt_connect_failed(hdev, &conn->dst, conn->type,
172448264f06SJohan Hedberg 					    conn->dst_type, ev->status);
172517d5c04cSJohan Hedberg 	}
172645bb4bf0SMarcel Holtmann 
1727e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1728e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
172945bb4bf0SMarcel Holtmann 
1730769be974SMarcel Holtmann 	if (ev->status) {
1731a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1732a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1733c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1734c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1735a9de9248SMarcel Holtmann 
1736a9de9248SMarcel Holtmann unlock:
17371da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1738a9de9248SMarcel Holtmann 
1739a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
17401da177e4SLinus Torvalds }
17411da177e4SLinus Torvalds 
17426039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17431da177e4SLinus Torvalds {
1744a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17451da177e4SLinus Torvalds 	int mask = hdev->link_mode;
174620714bfeSFrédéric Dalleau 	__u8 flags = 0;
17471da177e4SLinus Torvalds 
17486ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
1749807deac2SGustavo Padovan 	       ev->link_type);
17501da177e4SLinus Torvalds 
175120714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
175220714bfeSFrédéric Dalleau 				      &flags);
17531da177e4SLinus Torvalds 
1754138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1755b9ee0a78SMarcel Holtmann 	    !hci_blacklist_lookup(hdev, &ev->bdaddr, BDADDR_BREDR)) {
17561da177e4SLinus Torvalds 		/* Connection accepted */
1757c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17581da177e4SLinus Torvalds 		struct hci_conn *conn;
17591da177e4SLinus Torvalds 
17601da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1761b6a0dc82SMarcel Holtmann 
1762cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1763cc11b9c1SAndrei Emeltchenko 		if (ie)
1764c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1765c7bdd502SMarcel Holtmann 
17668fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
17678fc9ced3SGustavo Padovan 					       &ev->bdaddr);
17681da177e4SLinus Torvalds 		if (!conn) {
1769cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1770cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1771893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17721da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17731da177e4SLinus Torvalds 				return;
17741da177e4SLinus Torvalds 			}
17751da177e4SLinus Torvalds 		}
1776b6a0dc82SMarcel Holtmann 
17771da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
1778b6a0dc82SMarcel Holtmann 
17791da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17801da177e4SLinus Torvalds 
178120714bfeSFrédéric Dalleau 		if (ev->link_type == ACL_LINK ||
178220714bfeSFrédéric Dalleau 		    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
1783b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
178420714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1785b6a0dc82SMarcel Holtmann 
17861da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17871da177e4SLinus Torvalds 
17881da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17891da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17901da177e4SLinus Torvalds 			else
17911da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17921da177e4SLinus Torvalds 
179304124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
179404124681SGustavo F. Padovan 				     &cp);
179520714bfeSFrédéric Dalleau 		} else if (!(flags & HCI_PROTO_DEFER)) {
1796b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
179720714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1798b6a0dc82SMarcel Holtmann 
1799b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1800a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1801b6a0dc82SMarcel Holtmann 
180282781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
180382781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
180482781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1805b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1806b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1807b6a0dc82SMarcel Holtmann 
1808b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1809b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
181020714bfeSFrédéric Dalleau 		} else {
181120714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT2;
181220714bfeSFrédéric Dalleau 			hci_proto_connect_cfm(conn, 0);
1813b6a0dc82SMarcel Holtmann 		}
18141da177e4SLinus Torvalds 	} else {
18151da177e4SLinus Torvalds 		/* Connection rejected */
18161da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18171da177e4SLinus Torvalds 
18181da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18199f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1820a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18211da177e4SLinus Torvalds 	}
18221da177e4SLinus Torvalds }
18231da177e4SLinus Torvalds 
1824f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
1825f0d6a0eaSMikel Astiz {
1826f0d6a0eaSMikel Astiz 	switch (err) {
1827f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
1828f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
1829f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
1830f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
1831f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
1832f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
1833f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
1834f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
1835f0d6a0eaSMikel Astiz 	default:
1836f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
1837f0d6a0eaSMikel Astiz 	}
1838f0d6a0eaSMikel Astiz }
1839f0d6a0eaSMikel Astiz 
18406039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18411da177e4SLinus Torvalds {
1842a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
1843abf54a50SAndre Guedes 	u8 reason = hci_to_mgmt_reason(ev->reason);
184404837f64SMarcel Holtmann 	struct hci_conn *conn;
184512d4a3b2SJohan Hedberg 	bool mgmt_connected;
18463846220bSAndre Guedes 	u8 type;
18471da177e4SLinus Torvalds 
18489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
18491da177e4SLinus Torvalds 
18501da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18511da177e4SLinus Torvalds 
185204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1853f7520543SJohan Hedberg 	if (!conn)
1854f7520543SJohan Hedberg 		goto unlock;
1855f7520543SJohan Hedberg 
1856f0d6a0eaSMikel Astiz 	if (ev->status) {
185788c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
185888c3df13SJohan Hedberg 				       conn->dst_type, ev->status);
1859abf54a50SAndre Guedes 		goto unlock;
1860abf54a50SAndre Guedes 	}
1861f0d6a0eaSMikel Astiz 
18623846220bSAndre Guedes 	conn->state = BT_CLOSED;
18633846220bSAndre Guedes 
186412d4a3b2SJohan Hedberg 	mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
186512d4a3b2SJohan Hedberg 	mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
186612d4a3b2SJohan Hedberg 				reason, mgmt_connected);
1867f7520543SJohan Hedberg 
18683846220bSAndre Guedes 	if (conn->type == ACL_LINK && conn->flush_key)
18696ec5bcadSVishal Agarwal 		hci_remove_link_key(hdev, &conn->dst);
18703846220bSAndre Guedes 
18713846220bSAndre Guedes 	type = conn->type;
18723846220bSAndre Guedes 
18732950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
18741da177e4SLinus Torvalds 	hci_conn_del(conn);
18752210246cSJohan Hedberg 
18762210246cSJohan Hedberg 	/* Re-enable advertising if necessary, since it might
18772210246cSJohan Hedberg 	 * have been disabled by the connection. From the
18782210246cSJohan Hedberg 	 * HCI_LE_Set_Advertise_Enable command description in
18792210246cSJohan Hedberg 	 * the core specification (v4.0):
18802210246cSJohan Hedberg 	 * "The Controller shall continue advertising until the Host
18812210246cSJohan Hedberg 	 * issues an LE_Set_Advertise_Enable command with
18822210246cSJohan Hedberg 	 * Advertising_Enable set to 0x00 (Advertising is disabled)
18832210246cSJohan Hedberg 	 * or until a connection is created or until the Advertising
18842210246cSJohan Hedberg 	 * is timed out due to Directed Advertising."
18852210246cSJohan Hedberg 	 */
18862210246cSJohan Hedberg 	if (type == LE_LINK)
18875976e608SMarcel Holtmann 		mgmt_reenable_advertising(hdev);
18881da177e4SLinus Torvalds 
1889f7520543SJohan Hedberg unlock:
18901da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18911da177e4SLinus Torvalds }
18921da177e4SLinus Torvalds 
18936039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1894a9de9248SMarcel Holtmann {
1895a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1896a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1897a9de9248SMarcel Holtmann 
18989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1899a9de9248SMarcel Holtmann 
1900a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1901a9de9248SMarcel Holtmann 
1902a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1903d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1904d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1905d7556e20SWaldemar Rymarkiewicz 
1906765c2a96SJohan Hedberg 	if (!ev->status) {
1907aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
190851a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1909d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
191019f8def0SWaldemar Rymarkiewicz 		} else {
1911a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1912765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
191319f8def0SWaldemar Rymarkiewicz 		}
19142a611692SJohan Hedberg 	} else {
1915bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1916bab73cb6SJohan Hedberg 				 ev->status);
19172a611692SJohan Hedberg 	}
1918a9de9248SMarcel Holtmann 
191951a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
192051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1921a9de9248SMarcel Holtmann 
1922f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1923aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1924f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1925f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1926f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1927d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1928d7556e20SWaldemar Rymarkiewicz 				     &cp);
1929f8558555SMarcel Holtmann 		} else {
1930f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1931f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
193276a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1933f8558555SMarcel Holtmann 		}
1934052b30b0SMarcel Holtmann 	} else {
1935a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1936a9de9248SMarcel Holtmann 
1937052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1938052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
193976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
1940052b30b0SMarcel Holtmann 	}
1941052b30b0SMarcel Holtmann 
194251a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1943a9de9248SMarcel Holtmann 		if (!ev->status) {
1944a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1945f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1946f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1947d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1948d7556e20SWaldemar Rymarkiewicz 				     &cp);
1949a9de9248SMarcel Holtmann 		} else {
195051a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1951a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1952a9de9248SMarcel Holtmann 		}
1953a9de9248SMarcel Holtmann 	}
1954a9de9248SMarcel Holtmann 
1955d7556e20SWaldemar Rymarkiewicz unlock:
1956a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1957a9de9248SMarcel Holtmann }
1958a9de9248SMarcel Holtmann 
19596039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1960a9de9248SMarcel Holtmann {
1961127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1962127178d2SJohan Hedberg 	struct hci_conn *conn;
1963127178d2SJohan Hedberg 
1964a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1965a9de9248SMarcel Holtmann 
1966a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1967127178d2SJohan Hedberg 
1968127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1969127178d2SJohan Hedberg 
1970127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1971b644ba33SJohan Hedberg 
1972b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1973b644ba33SJohan Hedberg 		goto check_auth;
1974b644ba33SJohan Hedberg 
1975b644ba33SJohan Hedberg 	if (ev->status == 0)
1976b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1977b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1978b644ba33SJohan Hedberg 	else
1979b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1980b644ba33SJohan Hedberg 
1981b644ba33SJohan Hedberg check_auth:
198279c6c70cSJohan Hedberg 	if (!conn)
198379c6c70cSJohan Hedberg 		goto unlock;
198479c6c70cSJohan Hedberg 
198579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
198679c6c70cSJohan Hedberg 		goto unlock;
198779c6c70cSJohan Hedberg 
198851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1989127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1990127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1991127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1992127178d2SJohan Hedberg 	}
1993127178d2SJohan Hedberg 
199479c6c70cSJohan Hedberg unlock:
1995127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1996a9de9248SMarcel Holtmann }
1997a9de9248SMarcel Holtmann 
19986039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1999a9de9248SMarcel Holtmann {
2000a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2001a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2002a9de9248SMarcel Holtmann 
20039f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2004a9de9248SMarcel Holtmann 
2005a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2006a9de9248SMarcel Holtmann 
2007a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2008dc8357ccSMarcel Holtmann 	if (!conn)
2009dc8357ccSMarcel Holtmann 		goto unlock;
2010dc8357ccSMarcel Holtmann 
2011a9de9248SMarcel Holtmann 	if (!ev->status) {
2012ae293196SMarcel Holtmann 		if (ev->encrypt) {
2013ae293196SMarcel Holtmann 			/* Encryption implies authentication */
2014ae293196SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2015a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
2016da85e5e5SVinicius Costa Gomes 			conn->sec_level = conn->pending_sec_level;
2017abf76badSMarcel Holtmann 
2018914a6ffeSMarcel Holtmann 			/* P-256 authentication key implies FIPS */
2019914a6ffeSMarcel Holtmann 			if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
2020914a6ffeSMarcel Holtmann 				conn->link_mode |= HCI_LM_FIPS;
2021914a6ffeSMarcel Holtmann 
2022abf76badSMarcel Holtmann 			if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
2023abf76badSMarcel Holtmann 			    conn->type == LE_LINK)
2024abf76badSMarcel Holtmann 				set_bit(HCI_CONN_AES_CCM, &conn->flags);
2025abf76badSMarcel Holtmann 		} else {
2026a9de9248SMarcel Holtmann 			conn->link_mode &= ~HCI_LM_ENCRYPT;
2027abf76badSMarcel Holtmann 			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
2028abf76badSMarcel Holtmann 		}
2029a9de9248SMarcel Holtmann 	}
2030a9de9248SMarcel Holtmann 
203151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2032a9de9248SMarcel Holtmann 
2033a7d7723aSGustavo Padovan 	if (ev->status && conn->state == BT_CONNECTED) {
2034bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
203576a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2036a7d7723aSGustavo Padovan 		goto unlock;
2037a7d7723aSGustavo Padovan 	}
2038a7d7723aSGustavo Padovan 
2039f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2040f8558555SMarcel Holtmann 		if (!ev->status)
2041f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2042f8558555SMarcel Holtmann 
2043f8558555SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
204476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2045f8558555SMarcel Holtmann 	} else
2046a9de9248SMarcel Holtmann 		hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2047a9de9248SMarcel Holtmann 
2048a7d7723aSGustavo Padovan unlock:
2049a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2050a9de9248SMarcel Holtmann }
2051a9de9248SMarcel Holtmann 
20526039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2053807deac2SGustavo Padovan 					     struct sk_buff *skb)
2054a9de9248SMarcel Holtmann {
2055a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2056a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2057a9de9248SMarcel Holtmann 
20589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2059a9de9248SMarcel Holtmann 
2060a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2061a9de9248SMarcel Holtmann 
2062a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2063a9de9248SMarcel Holtmann 	if (conn) {
2064a9de9248SMarcel Holtmann 		if (!ev->status)
2065a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2066a9de9248SMarcel Holtmann 
206751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2068a9de9248SMarcel Holtmann 
2069a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2070a9de9248SMarcel Holtmann 	}
2071a9de9248SMarcel Holtmann 
2072a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2073a9de9248SMarcel Holtmann }
2074a9de9248SMarcel Holtmann 
20756039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2076807deac2SGustavo Padovan 				    struct sk_buff *skb)
2077a9de9248SMarcel Holtmann {
2078a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2079a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2080a9de9248SMarcel Holtmann 
20819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2082a9de9248SMarcel Holtmann 
2083a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2084a9de9248SMarcel Holtmann 
2085a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2086ccd556feSJohan Hedberg 	if (!conn)
2087ccd556feSJohan Hedberg 		goto unlock;
2088ccd556feSJohan Hedberg 
2089769be974SMarcel Holtmann 	if (!ev->status)
2090cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
2091a9de9248SMarcel Holtmann 
2092ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2093ccd556feSJohan Hedberg 		goto unlock;
2094ccd556feSJohan Hedberg 
2095ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2096769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2097769be974SMarcel Holtmann 		cp.handle = ev->handle;
2098769be974SMarcel Holtmann 		cp.page = 0x01;
2099ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2100769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2101392599b9SJohan Hedberg 		goto unlock;
2102392599b9SJohan Hedberg 	}
2103392599b9SJohan Hedberg 
2104671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2105127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2106127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2107127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2108127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2109127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2110b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2111b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
211208c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2113b644ba33SJohan Hedberg 				      conn->dev_class);
2114392599b9SJohan Hedberg 
2115127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2116769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2117769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
211876a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2119769be974SMarcel Holtmann 	}
2120769be974SMarcel Holtmann 
2121ccd556feSJohan Hedberg unlock:
2122a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2123a9de9248SMarcel Holtmann }
2124a9de9248SMarcel Holtmann 
21256039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2126a9de9248SMarcel Holtmann {
2127a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
21289238f36aSJohan Hedberg 	u8 status = skb->data[sizeof(*ev)];
2129a9de9248SMarcel Holtmann 	__u16 opcode;
2130a9de9248SMarcel Holtmann 
2131a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2132a9de9248SMarcel Holtmann 
2133a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2134a9de9248SMarcel Holtmann 
2135a9de9248SMarcel Holtmann 	switch (opcode) {
2136a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2137a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2138a9de9248SMarcel Holtmann 		break;
2139a9de9248SMarcel Holtmann 
21404d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
21414d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
21424d93483bSAndre Guedes 		break;
21434d93483bSAndre Guedes 
2144a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2145a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2146a9de9248SMarcel Holtmann 		break;
2147a9de9248SMarcel Holtmann 
2148a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2149a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2150a9de9248SMarcel Holtmann 		break;
2151a9de9248SMarcel Holtmann 
2152a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2153a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2154a9de9248SMarcel Holtmann 		break;
2155a9de9248SMarcel Holtmann 
2156e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2157e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2158e4e8e37cSMarcel Holtmann 		break;
2159e4e8e37cSMarcel Holtmann 
2160a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2161a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2162a9de9248SMarcel Holtmann 		break;
2163a9de9248SMarcel Holtmann 
2164e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2165e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2166e4e8e37cSMarcel Holtmann 		break;
2167e4e8e37cSMarcel Holtmann 
2168e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2169e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2170e4e8e37cSMarcel Holtmann 		break;
2171e4e8e37cSMarcel Holtmann 
2172a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2173a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2174a9de9248SMarcel Holtmann 		break;
2175a9de9248SMarcel Holtmann 
2176a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2177a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2178a9de9248SMarcel Holtmann 		break;
2179a9de9248SMarcel Holtmann 
2180a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2181a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2182a9de9248SMarcel Holtmann 		break;
2183a9de9248SMarcel Holtmann 
2184a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2185a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2186a9de9248SMarcel Holtmann 		break;
2187a9de9248SMarcel Holtmann 
2188a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2189a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2190a9de9248SMarcel Holtmann 		break;
2191a9de9248SMarcel Holtmann 
2192a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2193a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2194a9de9248SMarcel Holtmann 		break;
2195a9de9248SMarcel Holtmann 
2196a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2197a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2198a9de9248SMarcel Holtmann 		break;
2199a9de9248SMarcel Holtmann 
2200a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2201a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2202a9de9248SMarcel Holtmann 		break;
2203a9de9248SMarcel Holtmann 
2204a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2205a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2206a9de9248SMarcel Holtmann 		break;
2207a9de9248SMarcel Holtmann 
2208a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2209a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2210a9de9248SMarcel Holtmann 		break;
2211a9de9248SMarcel Holtmann 
2212b4cb9fb2SMarcel Holtmann 	case HCI_OP_READ_NUM_SUPPORTED_IAC:
2213b4cb9fb2SMarcel Holtmann 		hci_cc_read_num_supported_iac(hdev, skb);
2214b4cb9fb2SMarcel Holtmann 		break;
2215b4cb9fb2SMarcel Holtmann 
2216333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2217333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2218333140b5SMarcel Holtmann 		break;
2219333140b5SMarcel Holtmann 
2220eac83dc6SMarcel Holtmann 	case HCI_OP_WRITE_SC_SUPPORT:
2221eac83dc6SMarcel Holtmann 		hci_cc_write_sc_support(hdev, skb);
2222eac83dc6SMarcel Holtmann 		break;
2223eac83dc6SMarcel Holtmann 
2224a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2225a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2226a9de9248SMarcel Holtmann 		break;
2227a9de9248SMarcel Holtmann 
2228a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2229a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2230a9de9248SMarcel Holtmann 		break;
2231a9de9248SMarcel Holtmann 
2232a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2233a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2234a9de9248SMarcel Holtmann 		break;
2235a9de9248SMarcel Holtmann 
2236971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2237971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2238971e3a4bSAndre Guedes 		break;
2239971e3a4bSAndre Guedes 
2240a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2241a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2242a9de9248SMarcel Holtmann 		break;
2243a9de9248SMarcel Holtmann 
2244a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2245a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2246a9de9248SMarcel Holtmann 		break;
2247a9de9248SMarcel Holtmann 
2248f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2249f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
2250f332ec66SJohan Hedberg 		break;
2251f332ec66SJohan Hedberg 
22524a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
22534a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
22544a3ee763SJohan Hedberg 		break;
22554a3ee763SJohan Hedberg 
2256f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
2257f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
2258f332ec66SJohan Hedberg 		break;
2259f332ec66SJohan Hedberg 
22604a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
22614a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
22624a3ee763SJohan Hedberg 		break;
22634a3ee763SJohan Hedberg 
2264350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2265350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2266350ee4cfSAndrei Emeltchenko 		break;
2267350ee4cfSAndrei Emeltchenko 
22681e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
22691e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
22701e89cffbSAndrei Emeltchenko 		break;
22711e89cffbSAndrei Emeltchenko 
2272928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2273928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2274928abaa7SAndrei Emeltchenko 		break;
2275928abaa7SAndrei Emeltchenko 
2276903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2277903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2278903e4541SAndrei Emeltchenko 		break;
2279903e4541SAndrei Emeltchenko 
2280d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2281d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2282d5859e22SJohan Hedberg 		break;
2283d5859e22SJohan Hedberg 
2284980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2285980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2286980e1a53SJohan Hedberg 		break;
2287980e1a53SJohan Hedberg 
2288980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2289980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2290980e1a53SJohan Hedberg 		break;
2291980e1a53SJohan Hedberg 
2292c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
22934d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_data(hdev, skb);
22944d2d2796SMarcel Holtmann 		break;
22954d2d2796SMarcel Holtmann 
22964d2d2796SMarcel Holtmann 	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
22974d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_ext_data(hdev, skb);
2298c35938b2SSzymon Janc 		break;
2299c35938b2SSzymon Janc 
23006ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
23016ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
23026ed58ec5SVille Tervo 		break;
23036ed58ec5SVille Tervo 
230460e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
230560e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
230660e77321SJohan Hedberg 		break;
230760e77321SJohan Hedberg 
23088fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
23098fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
23108fa19098SJohan Hedberg 		break;
23118fa19098SJohan Hedberg 
2312a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2313a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2314a5c29683SJohan Hedberg 		break;
2315a5c29683SJohan Hedberg 
2316a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2317a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2318a5c29683SJohan Hedberg 		break;
2319a5c29683SJohan Hedberg 
23201143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
23211143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
23221143d458SBrian Gix 		break;
23231143d458SBrian Gix 
23241143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23251143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
232616cde993SSzymon Janc 		break;
232707f7fa5dSAndre Guedes 
23287a4cd51dSMarcel Holtmann 	case HCI_OP_LE_SET_RANDOM_ADDR:
23297a4cd51dSMarcel Holtmann 		hci_cc_le_set_random_addr(hdev, skb);
23307a4cd51dSMarcel Holtmann 		break;
23317a4cd51dSMarcel Holtmann 
2332c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2333c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2334c1d5dc4aSJohan Hedberg 		break;
2335c1d5dc4aSJohan Hedberg 
2336eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2337eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2338eb9d91f5SAndre Guedes 		break;
2339eb9d91f5SAndre Guedes 
2340cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2341cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2342cf1d081fSJohan Hedberg 		break;
2343cf1d081fSJohan Hedberg 
23449b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
23459b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
23469b008c04SJohan Hedberg 		break;
23479b008c04SJohan Hedberg 
2348f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2349f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2350f9b49306SAndre Guedes 		break;
2351f9b49306SAndre Guedes 
235293c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
235393c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
235493c284eeSAndrei Emeltchenko 		break;
235593c284eeSAndrei Emeltchenko 
2356a9de9248SMarcel Holtmann 	default:
23579f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2358a9de9248SMarcel Holtmann 		break;
2359a9de9248SMarcel Holtmann 	}
2360a9de9248SMarcel Holtmann 
2361ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
23626bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23636bd32326SVille Tervo 
2364ad82cdd1SJohan Hedberg 	hci_req_cmd_complete(hdev, opcode, status);
23659238f36aSJohan Hedberg 
2366dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2367a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2368a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2369c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2370a9de9248SMarcel Holtmann 	}
2371a9de9248SMarcel Holtmann }
2372a9de9248SMarcel Holtmann 
23736039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2374a9de9248SMarcel Holtmann {
2375a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2376a9de9248SMarcel Holtmann 	__u16 opcode;
2377a9de9248SMarcel Holtmann 
2378a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2379a9de9248SMarcel Holtmann 
2380a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2381a9de9248SMarcel Holtmann 
2382a9de9248SMarcel Holtmann 	switch (opcode) {
2383a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2384a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2385a9de9248SMarcel Holtmann 		break;
2386a9de9248SMarcel Holtmann 
2387a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2388a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2389a9de9248SMarcel Holtmann 		break;
2390a9de9248SMarcel Holtmann 
2391a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2392a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2393a9de9248SMarcel Holtmann 		break;
2394a9de9248SMarcel Holtmann 
2395f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2396f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2397f8558555SMarcel Holtmann 		break;
2398f8558555SMarcel Holtmann 
2399f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2400f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2401f8558555SMarcel Holtmann 		break;
2402f8558555SMarcel Holtmann 
2403a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2404a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2405a9de9248SMarcel Holtmann 		break;
2406a9de9248SMarcel Holtmann 
2407769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2408769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2409769be974SMarcel Holtmann 		break;
2410769be974SMarcel Holtmann 
2411769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2412769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2413769be974SMarcel Holtmann 		break;
2414769be974SMarcel Holtmann 
2415a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2416a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2417a9de9248SMarcel Holtmann 		break;
2418a9de9248SMarcel Holtmann 
2419a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2420a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2421a9de9248SMarcel Holtmann 		break;
2422a9de9248SMarcel Holtmann 
2423a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2424a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2425a9de9248SMarcel Holtmann 		break;
2426a9de9248SMarcel Holtmann 
24278962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
242888c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
24298962ee74SJohan Hedberg 		break;
24308962ee74SJohan Hedberg 
2431a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2432a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2433a02226d6SAndrei Emeltchenko 		break;
2434a02226d6SAndrei Emeltchenko 
24350b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
24360b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
24370b26ab9dSAndrei Emeltchenko 		break;
24380b26ab9dSAndrei Emeltchenko 
2439a9de9248SMarcel Holtmann 	default:
24409f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2441a9de9248SMarcel Holtmann 		break;
2442a9de9248SMarcel Holtmann 	}
2443a9de9248SMarcel Holtmann 
2444ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
24456bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24466bd32326SVille Tervo 
244702350a72SJohan Hedberg 	if (ev->status ||
244802350a72SJohan Hedberg 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
244933720450SAndre Guedes 		hci_req_cmd_complete(hdev, opcode, ev->status);
24509238f36aSJohan Hedberg 
245110572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2452a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2453a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2454c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2455a9de9248SMarcel Holtmann 	}
2456a9de9248SMarcel Holtmann }
2457a9de9248SMarcel Holtmann 
24586039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2459a9de9248SMarcel Holtmann {
2460a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2461a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2462a9de9248SMarcel Holtmann 
24639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2464a9de9248SMarcel Holtmann 
2465a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2466a9de9248SMarcel Holtmann 
2467a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2468a9de9248SMarcel Holtmann 	if (conn) {
2469a9de9248SMarcel Holtmann 		if (!ev->status) {
2470a9de9248SMarcel Holtmann 			if (ev->role)
2471a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2472a9de9248SMarcel Holtmann 			else
2473a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2474a9de9248SMarcel Holtmann 		}
2475a9de9248SMarcel Holtmann 
247651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2477a9de9248SMarcel Holtmann 
2478a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2479a9de9248SMarcel Holtmann 	}
2480a9de9248SMarcel Holtmann 
2481a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2482a9de9248SMarcel Holtmann }
2483a9de9248SMarcel Holtmann 
24846039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
24851da177e4SLinus Torvalds {
2486a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
24871da177e4SLinus Torvalds 	int i;
24881da177e4SLinus Torvalds 
248932ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
249032ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
249132ac5b9bSAndrei Emeltchenko 		return;
249232ac5b9bSAndrei Emeltchenko 	}
249332ac5b9bSAndrei Emeltchenko 
2494c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2495c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24961da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24971da177e4SLinus Torvalds 		return;
24981da177e4SLinus Torvalds 	}
24991da177e4SLinus Torvalds 
2500c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2501c5993de8SAndrei Emeltchenko 
2502613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2503613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
25041da177e4SLinus Torvalds 		struct hci_conn *conn;
25051da177e4SLinus Torvalds 		__u16  handle, count;
25061da177e4SLinus Torvalds 
2507613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2508613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
25091da177e4SLinus Torvalds 
25101da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2511f4280918SAndrei Emeltchenko 		if (!conn)
2512f4280918SAndrei Emeltchenko 			continue;
2513f4280918SAndrei Emeltchenko 
25141da177e4SLinus Torvalds 		conn->sent -= count;
25151da177e4SLinus Torvalds 
2516f4280918SAndrei Emeltchenko 		switch (conn->type) {
2517f4280918SAndrei Emeltchenko 		case ACL_LINK:
251870f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
251970f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
25201da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2521f4280918SAndrei Emeltchenko 			break;
2522f4280918SAndrei Emeltchenko 
2523f4280918SAndrei Emeltchenko 		case LE_LINK:
25246ed58ec5SVille Tervo 			if (hdev->le_pkts) {
25256ed58ec5SVille Tervo 				hdev->le_cnt += count;
25266ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
25276ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
25286ed58ec5SVille Tervo 			} else {
25296ed58ec5SVille Tervo 				hdev->acl_cnt += count;
25306ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
25316ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
25326ed58ec5SVille Tervo 			}
2533f4280918SAndrei Emeltchenko 			break;
2534f4280918SAndrei Emeltchenko 
2535f4280918SAndrei Emeltchenko 		case SCO_LINK:
253670f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
253770f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
25385b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2539f4280918SAndrei Emeltchenko 			break;
2540f4280918SAndrei Emeltchenko 
2541f4280918SAndrei Emeltchenko 		default:
2542f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2543f4280918SAndrei Emeltchenko 			break;
25441da177e4SLinus Torvalds 		}
25451da177e4SLinus Torvalds 	}
2546a9de9248SMarcel Holtmann 
25473eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25481da177e4SLinus Torvalds }
25491da177e4SLinus Torvalds 
255076ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
255176ef7cf7SAndrei Emeltchenko 						 __u16 handle)
255276ef7cf7SAndrei Emeltchenko {
255376ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
255476ef7cf7SAndrei Emeltchenko 
255576ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
255676ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
255776ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
255876ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
255976ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
256076ef7cf7SAndrei Emeltchenko 		if (chan)
256176ef7cf7SAndrei Emeltchenko 			return chan->conn;
256276ef7cf7SAndrei Emeltchenko 		break;
256376ef7cf7SAndrei Emeltchenko 	default:
256476ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
256576ef7cf7SAndrei Emeltchenko 		break;
256676ef7cf7SAndrei Emeltchenko 	}
256776ef7cf7SAndrei Emeltchenko 
256876ef7cf7SAndrei Emeltchenko 	return NULL;
256976ef7cf7SAndrei Emeltchenko }
257076ef7cf7SAndrei Emeltchenko 
25716039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
257225e89e99SAndrei Emeltchenko {
257325e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
257425e89e99SAndrei Emeltchenko 	int i;
257525e89e99SAndrei Emeltchenko 
257625e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
257725e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
257825e89e99SAndrei Emeltchenko 		return;
257925e89e99SAndrei Emeltchenko 	}
258025e89e99SAndrei Emeltchenko 
258125e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
258225e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
258325e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
258425e89e99SAndrei Emeltchenko 		return;
258525e89e99SAndrei Emeltchenko 	}
258625e89e99SAndrei Emeltchenko 
258725e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
258825e89e99SAndrei Emeltchenko 	       ev->num_hndl);
258925e89e99SAndrei Emeltchenko 
259025e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
259125e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
259276ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
259325e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
259425e89e99SAndrei Emeltchenko 
259525e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
259625e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
259725e89e99SAndrei Emeltchenko 
259876ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
259925e89e99SAndrei Emeltchenko 		if (!conn)
260025e89e99SAndrei Emeltchenko 			continue;
260125e89e99SAndrei Emeltchenko 
260225e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
260325e89e99SAndrei Emeltchenko 
260425e89e99SAndrei Emeltchenko 		switch (conn->type) {
260525e89e99SAndrei Emeltchenko 		case ACL_LINK:
2606bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
260725e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
260825e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
260925e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
261025e89e99SAndrei Emeltchenko 			break;
261125e89e99SAndrei Emeltchenko 
261225e89e99SAndrei Emeltchenko 		default:
261325e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
261425e89e99SAndrei Emeltchenko 			break;
261525e89e99SAndrei Emeltchenko 		}
261625e89e99SAndrei Emeltchenko 	}
261725e89e99SAndrei Emeltchenko 
261825e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
261925e89e99SAndrei Emeltchenko }
262025e89e99SAndrei Emeltchenko 
26216039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
26221da177e4SLinus Torvalds {
2623a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
262404837f64SMarcel Holtmann 	struct hci_conn *conn;
26251da177e4SLinus Torvalds 
26269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
26271da177e4SLinus Torvalds 
26281da177e4SLinus Torvalds 	hci_dev_lock(hdev);
26291da177e4SLinus Torvalds 
263004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
263104837f64SMarcel Holtmann 	if (conn) {
263204837f64SMarcel Holtmann 		conn->mode = ev->mode;
263304837f64SMarcel Holtmann 
26348fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
26358fc9ced3SGustavo Padovan 					&conn->flags)) {
263604837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
263758a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
263804837f64SMarcel Holtmann 			else
263958a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
264004837f64SMarcel Holtmann 		}
2641e73439d8SMarcel Holtmann 
264251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2643e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
264404837f64SMarcel Holtmann 	}
264504837f64SMarcel Holtmann 
264604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
264704837f64SMarcel Holtmann }
264804837f64SMarcel Holtmann 
26496039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26501da177e4SLinus Torvalds {
2651052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2652052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2653052b30b0SMarcel Holtmann 
2654a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2655052b30b0SMarcel Holtmann 
2656052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2657052b30b0SMarcel Holtmann 
2658052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2659b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2660b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2661b6f98044SWaldemar Rymarkiewicz 
2662b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2663052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2664052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
266576a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2666052b30b0SMarcel Holtmann 	}
2667052b30b0SMarcel Holtmann 
2668a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
266903b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
267003b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2671a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2672a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2673a770bb5aSWaldemar Rymarkiewicz 
2674a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2675a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2676a770bb5aSWaldemar Rymarkiewicz 		else
2677a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2678a770bb5aSWaldemar Rymarkiewicz 
2679744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2680a770bb5aSWaldemar Rymarkiewicz 	}
2681980e1a53SJohan Hedberg 
2682b6f98044SWaldemar Rymarkiewicz unlock:
2683052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26841da177e4SLinus Torvalds }
26851da177e4SLinus Torvalds 
26866039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26871da177e4SLinus Torvalds {
268855ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
268955ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
269055ed8ca1SJohan Hedberg 	struct hci_conn *conn;
269155ed8ca1SJohan Hedberg 	struct link_key *key;
269255ed8ca1SJohan Hedberg 
2693a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
269455ed8ca1SJohan Hedberg 
2695034cbea0SAndrei Emeltchenko 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
269655ed8ca1SJohan Hedberg 		return;
269755ed8ca1SJohan Hedberg 
269855ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
269955ed8ca1SJohan Hedberg 
270055ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
270155ed8ca1SJohan Hedberg 	if (!key) {
27026ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
27036ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
270455ed8ca1SJohan Hedberg 		goto not_found;
270555ed8ca1SJohan Hedberg 	}
270655ed8ca1SJohan Hedberg 
27076ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
27086ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
270955ed8ca1SJohan Hedberg 
2710a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2711b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
271255ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
271355ed8ca1SJohan Hedberg 		goto not_found;
271455ed8ca1SJohan Hedberg 	}
271555ed8ca1SJohan Hedberg 
271655ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
271760b83f57SWaldemar Rymarkiewicz 	if (conn) {
271866138ce8SMarcel Holtmann 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
271966138ce8SMarcel Holtmann 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
2720807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
272155ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
272255ed8ca1SJohan Hedberg 			goto not_found;
272355ed8ca1SJohan Hedberg 		}
272455ed8ca1SJohan Hedberg 
272560b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
272660b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
27278fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
27288fc9ced3SGustavo Padovan 			       hdev->name);
272960b83f57SWaldemar Rymarkiewicz 			goto not_found;
273060b83f57SWaldemar Rymarkiewicz 		}
273160b83f57SWaldemar Rymarkiewicz 
273260b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
273360b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
273460b83f57SWaldemar Rymarkiewicz 	}
273560b83f57SWaldemar Rymarkiewicz 
273655ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
27379b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
273855ed8ca1SJohan Hedberg 
273955ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
274055ed8ca1SJohan Hedberg 
274155ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
274255ed8ca1SJohan Hedberg 
274355ed8ca1SJohan Hedberg 	return;
274455ed8ca1SJohan Hedberg 
274555ed8ca1SJohan Hedberg not_found:
274655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
274755ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
27481da177e4SLinus Torvalds }
27491da177e4SLinus Torvalds 
27506039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
27511da177e4SLinus Torvalds {
2752052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2753052b30b0SMarcel Holtmann 	struct hci_conn *conn;
275455ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2755052b30b0SMarcel Holtmann 
2756a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2757052b30b0SMarcel Holtmann 
2758052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2759052b30b0SMarcel Holtmann 
2760052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2761052b30b0SMarcel Holtmann 	if (conn) {
2762052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2763052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2764980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
276513d39315SWaldemar Rymarkiewicz 
276613d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
276713d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
276813d39315SWaldemar Rymarkiewicz 
276976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2770052b30b0SMarcel Holtmann 	}
2771052b30b0SMarcel Holtmann 
2772034cbea0SAndrei Emeltchenko 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
2773d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
277455ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
277555ed8ca1SJohan Hedberg 
2776052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27771da177e4SLinus Torvalds }
27781da177e4SLinus Torvalds 
27796039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
278004837f64SMarcel Holtmann {
2781a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
278204837f64SMarcel Holtmann 	struct hci_conn *conn;
278304837f64SMarcel Holtmann 
27849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
278504837f64SMarcel Holtmann 
278604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
278704837f64SMarcel Holtmann 
278804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27891da177e4SLinus Torvalds 	if (conn && !ev->status) {
27901da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27911da177e4SLinus Torvalds 
2792cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2793cc11b9c1SAndrei Emeltchenko 		if (ie) {
27941da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27951da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27961da177e4SLinus Torvalds 		}
27971da177e4SLinus Torvalds 	}
27981da177e4SLinus Torvalds 
27991da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
28001da177e4SLinus Torvalds }
28011da177e4SLinus Torvalds 
28026039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2803a8746417SMarcel Holtmann {
2804a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2805a8746417SMarcel Holtmann 	struct hci_conn *conn;
2806a8746417SMarcel Holtmann 
28079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2808a8746417SMarcel Holtmann 
2809a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2810a8746417SMarcel Holtmann 
2811a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2812a8746417SMarcel Holtmann 	if (conn && !ev->status)
2813a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2814a8746417SMarcel Holtmann 
2815a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2816a8746417SMarcel Holtmann }
2817a8746417SMarcel Holtmann 
28186039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
281985a1e930SMarcel Holtmann {
2820a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
282185a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
282285a1e930SMarcel Holtmann 
282385a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
282485a1e930SMarcel Holtmann 
282585a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
282685a1e930SMarcel Holtmann 
2827cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2828cc11b9c1SAndrei Emeltchenko 	if (ie) {
282985a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
283085a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
283185a1e930SMarcel Holtmann 	}
283285a1e930SMarcel Holtmann 
283385a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
283485a1e930SMarcel Holtmann }
283585a1e930SMarcel Holtmann 
28366039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2837807deac2SGustavo Padovan 					     struct sk_buff *skb)
2838a9de9248SMarcel Holtmann {
2839a9de9248SMarcel Holtmann 	struct inquiry_data data;
2840a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2841388fc8faSJohan Hedberg 	bool name_known, ssp;
2842a9de9248SMarcel Holtmann 
2843a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2844a9de9248SMarcel Holtmann 
2845a9de9248SMarcel Holtmann 	if (!num_rsp)
2846a9de9248SMarcel Holtmann 		return;
2847a9de9248SMarcel Holtmann 
28481519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
28491519cc17SAndre Guedes 		return;
28501519cc17SAndre Guedes 
2851a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2852a9de9248SMarcel Holtmann 
2853a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2854138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2855138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2856a9de9248SMarcel Holtmann 
2857e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2858a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2859a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2860a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2861a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2862a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2863a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2864a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
286541a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28663175405bSJohan Hedberg 
28673175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2868388fc8faSJohan Hedberg 							      false, &ssp);
286948264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2870e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2871388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2872a9de9248SMarcel Holtmann 		}
2873a9de9248SMarcel Holtmann 	} else {
2874a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2875a9de9248SMarcel Holtmann 
2876e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2877a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2878a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2879a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2880a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2881a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2882a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2883a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
288441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28853175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2886388fc8faSJohan Hedberg 							      false, &ssp);
288748264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2888e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2889388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2890a9de9248SMarcel Holtmann 		}
2891a9de9248SMarcel Holtmann 	}
2892a9de9248SMarcel Holtmann 
2893a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2894a9de9248SMarcel Holtmann }
2895a9de9248SMarcel Holtmann 
28966039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2897807deac2SGustavo Padovan 					struct sk_buff *skb)
2898a9de9248SMarcel Holtmann {
289941a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
290041a96212SMarcel Holtmann 	struct hci_conn *conn;
290141a96212SMarcel Holtmann 
2902a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
290341a96212SMarcel Holtmann 
290441a96212SMarcel Holtmann 	hci_dev_lock(hdev);
290541a96212SMarcel Holtmann 
290641a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2907ccd556feSJohan Hedberg 	if (!conn)
2908ccd556feSJohan Hedberg 		goto unlock;
2909ccd556feSJohan Hedberg 
2910cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
2911cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
2912cad718edSJohan Hedberg 
2913769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
291441a96212SMarcel Holtmann 		struct inquiry_entry *ie;
291541a96212SMarcel Holtmann 
2916cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2917cc11b9c1SAndrei Emeltchenko 		if (ie)
291802b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
291941a96212SMarcel Holtmann 
2920bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
292158a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
2922bbb0eadaSJaganath Kanakkassery 		} else {
2923bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
2924bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
2925bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
2926bbb0eadaSJaganath Kanakkassery 			 * this.
2927bbb0eadaSJaganath Kanakkassery 			 *
2928bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
2929bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
2930bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
2931bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
2932bbb0eadaSJaganath Kanakkassery 		}
2933eb9a8f3fSMarcel Holtmann 
2934eb9a8f3fSMarcel Holtmann 		if (ev->features[0] & LMP_HOST_SC)
2935eb9a8f3fSMarcel Holtmann 			set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
293641a96212SMarcel Holtmann 	}
293741a96212SMarcel Holtmann 
2938ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2939ccd556feSJohan Hedberg 		goto unlock;
2940ccd556feSJohan Hedberg 
2941671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2942127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2943127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2944127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2945127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2946127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2947b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2948b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
294908c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2950b644ba33SJohan Hedberg 				      conn->dev_class);
2951392599b9SJohan Hedberg 
2952127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2953769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2954769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
295576a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2956769be974SMarcel Holtmann 	}
2957769be974SMarcel Holtmann 
2958ccd556feSJohan Hedberg unlock:
295941a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2960a9de9248SMarcel Holtmann }
2961a9de9248SMarcel Holtmann 
29626039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2963807deac2SGustavo Padovan 				       struct sk_buff *skb)
2964a9de9248SMarcel Holtmann {
2965b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2966b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2967b6a0dc82SMarcel Holtmann 
29689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2969b6a0dc82SMarcel Holtmann 
2970b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2971b6a0dc82SMarcel Holtmann 
2972b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
29739dc0a3afSMarcel Holtmann 	if (!conn) {
29749dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
29759dc0a3afSMarcel Holtmann 			goto unlock;
29769dc0a3afSMarcel Holtmann 
29779dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2978b6a0dc82SMarcel Holtmann 		if (!conn)
2979b6a0dc82SMarcel Holtmann 			goto unlock;
2980b6a0dc82SMarcel Holtmann 
29819dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
29829dc0a3afSMarcel Holtmann 	}
29839dc0a3afSMarcel Holtmann 
2984732547f9SMarcel Holtmann 	switch (ev->status) {
2985732547f9SMarcel Holtmann 	case 0x00:
2986732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2987732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2988732547f9SMarcel Holtmann 
2989732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2990732547f9SMarcel Holtmann 		break;
2991732547f9SMarcel Holtmann 
29921a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
2993705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2994732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29951038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2996732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
29972dea632fSFrédéric Dalleau 		if (conn->out) {
2998efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2999efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
30002dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
3001efc7688bSMarcel Holtmann 				goto unlock;
3002efc7688bSMarcel Holtmann 		}
3003732547f9SMarcel Holtmann 		/* fall through */
3004efc7688bSMarcel Holtmann 
3005732547f9SMarcel Holtmann 	default:
3006b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3007732547f9SMarcel Holtmann 		break;
3008732547f9SMarcel Holtmann 	}
3009b6a0dc82SMarcel Holtmann 
3010b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3011b6a0dc82SMarcel Holtmann 	if (ev->status)
3012b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3013b6a0dc82SMarcel Holtmann 
3014b6a0dc82SMarcel Holtmann unlock:
3015b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3016a9de9248SMarcel Holtmann }
3017a9de9248SMarcel Holtmann 
3018efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len)
3019efdcf8e3SMarcel Holtmann {
3020efdcf8e3SMarcel Holtmann 	size_t parsed = 0;
3021efdcf8e3SMarcel Holtmann 
3022efdcf8e3SMarcel Holtmann 	while (parsed < eir_len) {
3023efdcf8e3SMarcel Holtmann 		u8 field_len = eir[0];
3024efdcf8e3SMarcel Holtmann 
3025efdcf8e3SMarcel Holtmann 		if (field_len == 0)
3026efdcf8e3SMarcel Holtmann 			return parsed;
3027efdcf8e3SMarcel Holtmann 
3028efdcf8e3SMarcel Holtmann 		parsed += field_len + 1;
3029efdcf8e3SMarcel Holtmann 		eir += field_len + 1;
3030efdcf8e3SMarcel Holtmann 	}
3031efdcf8e3SMarcel Holtmann 
3032efdcf8e3SMarcel Holtmann 	return eir_len;
3033efdcf8e3SMarcel Holtmann }
3034efdcf8e3SMarcel Holtmann 
30356039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3036807deac2SGustavo Padovan 					    struct sk_buff *skb)
3037a9de9248SMarcel Holtmann {
3038a9de9248SMarcel Holtmann 	struct inquiry_data data;
3039a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3040a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
30419d939d94SVishal Agarwal 	size_t eir_len;
3042a9de9248SMarcel Holtmann 
3043a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3044a9de9248SMarcel Holtmann 
3045a9de9248SMarcel Holtmann 	if (!num_rsp)
3046a9de9248SMarcel Holtmann 		return;
3047a9de9248SMarcel Holtmann 
30481519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30491519cc17SAndre Guedes 		return;
30501519cc17SAndre Guedes 
3051a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3052a9de9248SMarcel Holtmann 
3053e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3054388fc8faSJohan Hedberg 		bool name_known, ssp;
3055561aafbcSJohan Hedberg 
3056a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3057a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3058a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3059a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3060a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3061a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3062a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
306341a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3064561aafbcSJohan Hedberg 
3065a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
30664ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
30674ddb1930SJohan Hedberg 						       sizeof(info->data),
30684ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3069561aafbcSJohan Hedberg 		else
3070561aafbcSJohan Hedberg 			name_known = true;
3071561aafbcSJohan Hedberg 
3072388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3073388fc8faSJohan Hedberg 						      &ssp);
30749d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
307548264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
307604124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
30779d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3078a9de9248SMarcel Holtmann 	}
3079a9de9248SMarcel Holtmann 
3080a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3081a9de9248SMarcel Holtmann }
3082a9de9248SMarcel Holtmann 
30831c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
30841c2e0041SJohan Hedberg 					 struct sk_buff *skb)
30851c2e0041SJohan Hedberg {
30861c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
30871c2e0041SJohan Hedberg 	struct hci_conn *conn;
30881c2e0041SJohan Hedberg 
30899f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
30901c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
30911c2e0041SJohan Hedberg 
30921c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
30931c2e0041SJohan Hedberg 
30941c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30951c2e0041SJohan Hedberg 	if (!conn)
30961c2e0041SJohan Hedberg 		goto unlock;
30971c2e0041SJohan Hedberg 
30981c2e0041SJohan Hedberg 	if (!ev->status)
30991c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
31001c2e0041SJohan Hedberg 
31011c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
31021c2e0041SJohan Hedberg 
31031c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3104bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
310576a68ba0SDavid Herrmann 		hci_conn_drop(conn);
31061c2e0041SJohan Hedberg 		goto unlock;
31071c2e0041SJohan Hedberg 	}
31081c2e0041SJohan Hedberg 
31091c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
31101c2e0041SJohan Hedberg 		if (!ev->status)
31111c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
31121c2e0041SJohan Hedberg 
31131c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
311476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
31151c2e0041SJohan Hedberg 	} else {
31161c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
31171c2e0041SJohan Hedberg 
31181c2e0041SJohan Hedberg 		hci_conn_hold(conn);
31191c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
312076a68ba0SDavid Herrmann 		hci_conn_drop(conn);
31211c2e0041SJohan Hedberg 	}
31221c2e0041SJohan Hedberg 
31231c2e0041SJohan Hedberg unlock:
31241c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
31251c2e0041SJohan Hedberg }
31261c2e0041SJohan Hedberg 
31276039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
312817fa4b9dSJohan Hedberg {
312917fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
3130acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_DEDICATED_BONDING ||
3131acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_DEDICATED_BONDING_MITM) {
313217fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
313317fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
3134acabae96SMikel Astiz 		if (conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT ||
3135acabae96SMikel Astiz 		    conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)
3136acabae96SMikel Astiz 			return HCI_AT_DEDICATED_BONDING;
313717fa4b9dSJohan Hedberg 		else
3138acabae96SMikel Astiz 			return HCI_AT_DEDICATED_BONDING_MITM;
313917fa4b9dSJohan Hedberg 	}
314017fa4b9dSJohan Hedberg 
314117fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
3142acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
3143acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
314458797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
314517fa4b9dSJohan Hedberg 
314617fa4b9dSJohan Hedberg 	return conn->auth_type;
314717fa4b9dSJohan Hedberg }
314817fa4b9dSJohan Hedberg 
31496039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
31500493684eSMarcel Holtmann {
31510493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
31520493684eSMarcel Holtmann 	struct hci_conn *conn;
31530493684eSMarcel Holtmann 
31540493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31550493684eSMarcel Holtmann 
31560493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31570493684eSMarcel Holtmann 
31580493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
315903b555e1SJohan Hedberg 	if (!conn)
316003b555e1SJohan Hedberg 		goto unlock;
316103b555e1SJohan Hedberg 
31620493684eSMarcel Holtmann 	hci_conn_hold(conn);
31630493684eSMarcel Holtmann 
3164a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
316503b555e1SJohan Hedberg 		goto unlock;
316603b555e1SJohan Hedberg 
3167a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
316803b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
316917fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
317017fa4b9dSJohan Hedberg 
317117fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31727a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
31737a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
31747a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
3175a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
31767cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
31777cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
317817fa4b9dSJohan Hedberg 
31798fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
31808fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3181ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3182ce85ee13SSzymon Janc 		else
3183ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3184ce85ee13SSzymon Janc 
318517fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
318617fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
318703b555e1SJohan Hedberg 	} else {
318803b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
318903b555e1SJohan Hedberg 
319003b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31919f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
319203b555e1SJohan Hedberg 
319303b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
319403b555e1SJohan Hedberg 			     sizeof(cp), &cp);
319503b555e1SJohan Hedberg 	}
319603b555e1SJohan Hedberg 
319703b555e1SJohan Hedberg unlock:
319803b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
319903b555e1SJohan Hedberg }
320003b555e1SJohan Hedberg 
32016039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
320203b555e1SJohan Hedberg {
320303b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
320403b555e1SJohan Hedberg 	struct hci_conn *conn;
320503b555e1SJohan Hedberg 
320603b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
320703b555e1SJohan Hedberg 
320803b555e1SJohan Hedberg 	hci_dev_lock(hdev);
320903b555e1SJohan Hedberg 
321003b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
321103b555e1SJohan Hedberg 	if (!conn)
321203b555e1SJohan Hedberg 		goto unlock;
321303b555e1SJohan Hedberg 
321403b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
321503b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
321658a681efSJohan Hedberg 	if (ev->oob_data)
321758a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
321803b555e1SJohan Hedberg 
321903b555e1SJohan Hedberg unlock:
32200493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32210493684eSMarcel Holtmann }
32220493684eSMarcel Holtmann 
32236039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3224a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3225a5c29683SJohan Hedberg {
3226a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
322755bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
32287a828908SJohan Hedberg 	struct hci_conn *conn;
3229a5c29683SJohan Hedberg 
3230a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3231a5c29683SJohan Hedberg 
3232a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3233a5c29683SJohan Hedberg 
3234a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
32357a828908SJohan Hedberg 		goto unlock;
32367a828908SJohan Hedberg 
32377a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32387a828908SJohan Hedberg 	if (!conn)
32397a828908SJohan Hedberg 		goto unlock;
32407a828908SJohan Hedberg 
32417a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
32427a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
32437a828908SJohan Hedberg 
32447a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
32457a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
32467a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
32477a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
32487a828908SJohan Hedberg 	 * bit set. */
3249a767631aSMikel Astiz 	if (!conn->connect_cfm_cb && loc_mitm &&
3250a767631aSMikel Astiz 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
32517a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
32527a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
32537a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
32547a828908SJohan Hedberg 		goto unlock;
32557a828908SJohan Hedberg 	}
32567a828908SJohan Hedberg 
32577a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
3258a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
3259a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
326055bc1a37SJohan Hedberg 
326155bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
326255bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
326355bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
326451a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
326555bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
326655bc1a37SJohan Hedberg 			confirm_hint = 1;
326755bc1a37SJohan Hedberg 			goto confirm;
326855bc1a37SJohan Hedberg 		}
326955bc1a37SJohan Hedberg 
32709f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
32719f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
32729f61656aSJohan Hedberg 
32739f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
32749f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
32757bc18d9dSJohan Hedberg 			queue_delayed_work(conn->hdev->workqueue,
32767bc18d9dSJohan Hedberg 					   &conn->auto_accept_work, delay);
32779f61656aSJohan Hedberg 			goto unlock;
32789f61656aSJohan Hedberg 		}
32799f61656aSJohan Hedberg 
32807a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
32817a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
32827a828908SJohan Hedberg 		goto unlock;
32837a828908SJohan Hedberg 	}
32847a828908SJohan Hedberg 
328555bc1a37SJohan Hedberg confirm:
3286272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
328755bc1a37SJohan Hedberg 				  confirm_hint);
3288a5c29683SJohan Hedberg 
32897a828908SJohan Hedberg unlock:
3290a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3291a5c29683SJohan Hedberg }
3292a5c29683SJohan Hedberg 
32936039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
32941143d458SBrian Gix 					 struct sk_buff *skb)
32951143d458SBrian Gix {
32961143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
32971143d458SBrian Gix 
32981143d458SBrian Gix 	BT_DBG("%s", hdev->name);
32991143d458SBrian Gix 
3300a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3301272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
33021143d458SBrian Gix }
33031143d458SBrian Gix 
330492a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
330592a25256SJohan Hedberg 					struct sk_buff *skb)
330692a25256SJohan Hedberg {
330792a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
330892a25256SJohan Hedberg 	struct hci_conn *conn;
330992a25256SJohan Hedberg 
331092a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
331192a25256SJohan Hedberg 
331292a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
331392a25256SJohan Hedberg 	if (!conn)
331492a25256SJohan Hedberg 		return;
331592a25256SJohan Hedberg 
331692a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
331792a25256SJohan Hedberg 	conn->passkey_entered = 0;
331892a25256SJohan Hedberg 
331992a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
332092a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
332192a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
332292a25256SJohan Hedberg 					 conn->passkey_entered);
332392a25256SJohan Hedberg }
332492a25256SJohan Hedberg 
332592a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
332692a25256SJohan Hedberg {
332792a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
332892a25256SJohan Hedberg 	struct hci_conn *conn;
332992a25256SJohan Hedberg 
333092a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
333192a25256SJohan Hedberg 
333292a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
333392a25256SJohan Hedberg 	if (!conn)
333492a25256SJohan Hedberg 		return;
333592a25256SJohan Hedberg 
333692a25256SJohan Hedberg 	switch (ev->type) {
333792a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
333892a25256SJohan Hedberg 		conn->passkey_entered = 0;
333992a25256SJohan Hedberg 		return;
334092a25256SJohan Hedberg 
334192a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
334292a25256SJohan Hedberg 		conn->passkey_entered++;
334392a25256SJohan Hedberg 		break;
334492a25256SJohan Hedberg 
334592a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
334692a25256SJohan Hedberg 		conn->passkey_entered--;
334792a25256SJohan Hedberg 		break;
334892a25256SJohan Hedberg 
334992a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
335092a25256SJohan Hedberg 		conn->passkey_entered = 0;
335192a25256SJohan Hedberg 		break;
335292a25256SJohan Hedberg 
335392a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
335492a25256SJohan Hedberg 		return;
335592a25256SJohan Hedberg 	}
335692a25256SJohan Hedberg 
335792a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
335892a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
335992a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
336092a25256SJohan Hedberg 					 conn->passkey_entered);
336192a25256SJohan Hedberg }
336292a25256SJohan Hedberg 
33636039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3364807deac2SGustavo Padovan 					 struct sk_buff *skb)
33650493684eSMarcel Holtmann {
33660493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
33670493684eSMarcel Holtmann 	struct hci_conn *conn;
33680493684eSMarcel Holtmann 
33690493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
33700493684eSMarcel Holtmann 
33710493684eSMarcel Holtmann 	hci_dev_lock(hdev);
33720493684eSMarcel Holtmann 
33730493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
33742a611692SJohan Hedberg 	if (!conn)
33752a611692SJohan Hedberg 		goto unlock;
33762a611692SJohan Hedberg 
33772a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
33782a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
33792a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
33802a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
33812a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3382fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3383bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3384bab73cb6SJohan Hedberg 				 ev->status);
33852a611692SJohan Hedberg 
338676a68ba0SDavid Herrmann 	hci_conn_drop(conn);
33870493684eSMarcel Holtmann 
33882a611692SJohan Hedberg unlock:
33890493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
33900493684eSMarcel Holtmann }
33910493684eSMarcel Holtmann 
33926039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3393807deac2SGustavo Padovan 					 struct sk_buff *skb)
339441a96212SMarcel Holtmann {
339541a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
339641a96212SMarcel Holtmann 	struct inquiry_entry *ie;
3397cad718edSJohan Hedberg 	struct hci_conn *conn;
339841a96212SMarcel Holtmann 
339941a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
340041a96212SMarcel Holtmann 
340141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
340241a96212SMarcel Holtmann 
3403cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3404cad718edSJohan Hedberg 	if (conn)
3405cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
3406cad718edSJohan Hedberg 
3407cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3408cc11b9c1SAndrei Emeltchenko 	if (ie)
340902b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
341041a96212SMarcel Holtmann 
341141a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
341241a96212SMarcel Holtmann }
341341a96212SMarcel Holtmann 
34146039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
34152763eda6SSzymon Janc 					    struct sk_buff *skb)
34162763eda6SSzymon Janc {
34172763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
34182763eda6SSzymon Janc 	struct oob_data *data;
34192763eda6SSzymon Janc 
34202763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
34212763eda6SSzymon Janc 
34222763eda6SSzymon Janc 	hci_dev_lock(hdev);
34232763eda6SSzymon Janc 
3424a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3425e1ba1f15SSzymon Janc 		goto unlock;
3426e1ba1f15SSzymon Janc 
34272763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
34282763eda6SSzymon Janc 	if (data) {
3429519ca9d0SMarcel Holtmann 		if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
3430519ca9d0SMarcel Holtmann 			struct hci_cp_remote_oob_ext_data_reply cp;
3431519ca9d0SMarcel Holtmann 
3432519ca9d0SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
3433519ca9d0SMarcel Holtmann 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
3434519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer192, data->randomizer192,
3435519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer192));
3436519ca9d0SMarcel Holtmann 			memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
3437519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer256, data->randomizer256,
3438519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer256));
3439519ca9d0SMarcel Holtmann 
3440519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
3441519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3442519ca9d0SMarcel Holtmann 		} else {
34432763eda6SSzymon Janc 			struct hci_cp_remote_oob_data_reply cp;
34442763eda6SSzymon Janc 
34452763eda6SSzymon Janc 			bacpy(&cp.bdaddr, &ev->bdaddr);
3446519ca9d0SMarcel Holtmann 			memcpy(cp.hash, data->hash192, sizeof(cp.hash));
3447519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer, data->randomizer192,
3448519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer));
34492763eda6SSzymon Janc 
3450519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
3451519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3452519ca9d0SMarcel Holtmann 		}
34532763eda6SSzymon Janc 	} else {
34542763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
34552763eda6SSzymon Janc 
34562763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
3457519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
3458519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
34592763eda6SSzymon Janc 	}
34602763eda6SSzymon Janc 
3461e1ba1f15SSzymon Janc unlock:
34622763eda6SSzymon Janc 	hci_dev_unlock(hdev);
34632763eda6SSzymon Janc }
34642763eda6SSzymon Janc 
3465d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3466d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3467d5e91192SAndrei Emeltchenko {
3468d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3469d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3470d5e91192SAndrei Emeltchenko 
3471d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3472d5e91192SAndrei Emeltchenko 	       ev->status);
3473d5e91192SAndrei Emeltchenko 
3474d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3475d5e91192SAndrei Emeltchenko 
3476d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3477d5e91192SAndrei Emeltchenko 	if (!hcon) {
3478d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3479d5e91192SAndrei Emeltchenko 		return;
3480d5e91192SAndrei Emeltchenko 	}
3481d5e91192SAndrei Emeltchenko 
3482d5e91192SAndrei Emeltchenko 	if (ev->status) {
3483d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3484d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3485d5e91192SAndrei Emeltchenko 		return;
3486d5e91192SAndrei Emeltchenko 	}
3487d5e91192SAndrei Emeltchenko 
3488d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3489d5e91192SAndrei Emeltchenko 
3490d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3491d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3492d5e91192SAndrei Emeltchenko 
3493d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3494d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
349576a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
3496d5e91192SAndrei Emeltchenko 
3497d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3498d5e91192SAndrei Emeltchenko 
3499cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
3500cf70ff22SAndrei Emeltchenko 
3501d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3502d5e91192SAndrei Emeltchenko }
3503d5e91192SAndrei Emeltchenko 
350427695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
350527695fb4SAndrei Emeltchenko {
350627695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
350727695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
350827695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
350927695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
351027695fb4SAndrei Emeltchenko 
351127695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
351227695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
351327695fb4SAndrei Emeltchenko 	       ev->status);
351427695fb4SAndrei Emeltchenko 
351527695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
351627695fb4SAndrei Emeltchenko 	if (!hcon)
351727695fb4SAndrei Emeltchenko 		return;
351827695fb4SAndrei Emeltchenko 
351927695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
352027695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
352127695fb4SAndrei Emeltchenko 	if (!hchan)
352227695fb4SAndrei Emeltchenko 		return;
352327695fb4SAndrei Emeltchenko 
352427695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
352527695fb4SAndrei Emeltchenko 
352627695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
352727695fb4SAndrei Emeltchenko 
352827695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
352927695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
353027695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
353127695fb4SAndrei Emeltchenko 
353227695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
353327695fb4SAndrei Emeltchenko 
353427695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
353527695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
353627695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
353727695fb4SAndrei Emeltchenko 
353827695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
353927695fb4SAndrei Emeltchenko 	}
354027695fb4SAndrei Emeltchenko }
354127695fb4SAndrei Emeltchenko 
3542606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3543606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3544606e2a10SAndrei Emeltchenko {
3545606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3546606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3547606e2a10SAndrei Emeltchenko 
3548606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3549606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3550606e2a10SAndrei Emeltchenko 
3551606e2a10SAndrei Emeltchenko 	if (ev->status)
3552606e2a10SAndrei Emeltchenko 		return;
3553606e2a10SAndrei Emeltchenko 
3554606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3555606e2a10SAndrei Emeltchenko 
3556606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3557606e2a10SAndrei Emeltchenko 	if (!hchan)
3558606e2a10SAndrei Emeltchenko 		goto unlock;
3559606e2a10SAndrei Emeltchenko 
3560606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3561606e2a10SAndrei Emeltchenko 
3562606e2a10SAndrei Emeltchenko unlock:
3563606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3564606e2a10SAndrei Emeltchenko }
3565606e2a10SAndrei Emeltchenko 
35669eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
35679eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
35689eef6b3aSAndrei Emeltchenko {
35699eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
35709eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
35719eef6b3aSAndrei Emeltchenko 
35729eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
35739eef6b3aSAndrei Emeltchenko 
35749eef6b3aSAndrei Emeltchenko 	if (ev->status)
35759eef6b3aSAndrei Emeltchenko 		return;
35769eef6b3aSAndrei Emeltchenko 
35779eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
35789eef6b3aSAndrei Emeltchenko 
35799eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
35809eef6b3aSAndrei Emeltchenko 	if (hcon) {
35819eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
35829eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
35839eef6b3aSAndrei Emeltchenko 	}
35849eef6b3aSAndrei Emeltchenko 
35859eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
35869eef6b3aSAndrei Emeltchenko }
35879eef6b3aSAndrei Emeltchenko 
35886039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3589fcd89c09SVille Tervo {
3590fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3591fcd89c09SVille Tervo 	struct hci_conn *conn;
359268d6f6deSJohan Hedberg 	struct smp_irk *irk;
3593fcd89c09SVille Tervo 
35949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3595fcd89c09SVille Tervo 
3596fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3597fcd89c09SVille Tervo 
35984f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3599b62f328bSVille Tervo 	if (!conn) {
3600b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3601b62f328bSVille Tervo 		if (!conn) {
3602b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3603230fd16aSAndre Guedes 			goto unlock;
3604b62f328bSVille Tervo 		}
360529b7988aSAndre Guedes 
360629b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3607b9b343d2SAndre Guedes 
3608880be4e8SMarcel Holtmann 		/* The advertising parameters for own address type
3609880be4e8SMarcel Holtmann 		 * define which source address and source address
3610880be4e8SMarcel Holtmann 		 * type this connections has.
3611880be4e8SMarcel Holtmann 		 */
3612880be4e8SMarcel Holtmann 		if (bacmp(&conn->src, BDADDR_ANY)) {
3613880be4e8SMarcel Holtmann 			conn->src_type = ADDR_LE_DEV_PUBLIC;
3614880be4e8SMarcel Holtmann 		} else {
3615880be4e8SMarcel Holtmann 			bacpy(&conn->src, &hdev->static_addr);
3616880be4e8SMarcel Holtmann 			conn->src_type = ADDR_LE_DEV_RANDOM;
3617880be4e8SMarcel Holtmann 		}
3618880be4e8SMarcel Holtmann 
3619b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3620b9b343d2SAndre Guedes 			conn->out = true;
3621b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3622b9b343d2SAndre Guedes 		}
3623b62f328bSVille Tervo 	}
3624fcd89c09SVille Tervo 
36257be2edbbSJohan Hedberg 	/* Ensure that the hci_conn contains the identity address type
36267be2edbbSJohan Hedberg 	 * regardless of which address the connection was made with.
36277be2edbbSJohan Hedberg 	 *
36287be2edbbSJohan Hedberg 	 * If the controller has a public BD_ADDR, then by default
36297be2edbbSJohan Hedberg 	 * use that one. If this is a LE only controller without
36307be2edbbSJohan Hedberg 	 * a public address, default to the static random address.
36317be2edbbSJohan Hedberg 	 *
36327be2edbbSJohan Hedberg 	 * For debugging purposes it is possible to force
36337be2edbbSJohan Hedberg 	 * controllers with a public address to use the static
36347be2edbbSJohan Hedberg 	 * random address instead.
36357be2edbbSJohan Hedberg 	 */
36367be2edbbSJohan Hedberg 	if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags) ||
36377be2edbbSJohan Hedberg 	    !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
36387be2edbbSJohan Hedberg 		bacpy(&conn->src, &hdev->static_addr);
36397be2edbbSJohan Hedberg 		conn->src_type = ADDR_LE_DEV_RANDOM;
36407be2edbbSJohan Hedberg 	} else {
36417be2edbbSJohan Hedberg 		bacpy(&conn->src, &hdev->bdaddr);
36427be2edbbSJohan Hedberg 		conn->src_type = ADDR_LE_DEV_PUBLIC;
36437be2edbbSJohan Hedberg 	}
36447be2edbbSJohan Hedberg 
3645edb4b466SMarcel Holtmann 	/* Lookup the identity address from the stored connection
3646edb4b466SMarcel Holtmann 	 * address and address type.
3647edb4b466SMarcel Holtmann 	 *
3648edb4b466SMarcel Holtmann 	 * When establishing connections to an identity address, the
3649edb4b466SMarcel Holtmann 	 * connection procedure will store the resolvable random
3650edb4b466SMarcel Holtmann 	 * address first. Now if it can be converted back into the
3651edb4b466SMarcel Holtmann 	 * identity address, start using the identity address from
3652edb4b466SMarcel Holtmann 	 * now on.
3653edb4b466SMarcel Holtmann 	 */
3654edb4b466SMarcel Holtmann 	irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
365568d6f6deSJohan Hedberg 	if (irk) {
365668d6f6deSJohan Hedberg 		bacpy(&conn->dst, &irk->bdaddr);
365768d6f6deSJohan Hedberg 		conn->dst_type = irk->addr_type;
365868d6f6deSJohan Hedberg 	}
365968d6f6deSJohan Hedberg 
3660cd17decbSAndre Guedes 	if (ev->status) {
366106c053fbSAndre Guedes 		hci_le_conn_failed(conn, ev->status);
3662cd17decbSAndre Guedes 		goto unlock;
3663cd17decbSAndre Guedes 	}
3664cd17decbSAndre Guedes 
3665b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
366601fdb0fcSMarcel Holtmann 		mgmt_device_connected(hdev, &conn->dst, conn->type,
366795b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
366883bc71b4SVinicius Costa Gomes 
36697b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3670fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3671fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3672fcd89c09SVille Tervo 
367318722c24SJukka Rissanen 	if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
367418722c24SJukka Rissanen 		set_bit(HCI_CONN_6LOWPAN, &conn->flags);
367518722c24SJukka Rissanen 
3676fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3677fcd89c09SVille Tervo 
3678fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3679fcd89c09SVille Tervo 
3680a4790dbdSAndre Guedes 	hci_pend_le_conn_del(hdev, &conn->dst, conn->dst_type);
3681a4790dbdSAndre Guedes 
3682fcd89c09SVille Tervo unlock:
3683fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3684fcd89c09SVille Tervo }
3685fcd89c09SVille Tervo 
3686a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */
3687a4790dbdSAndre Guedes static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
3688a4790dbdSAndre Guedes 				  u8 addr_type)
3689a4790dbdSAndre Guedes {
3690a4790dbdSAndre Guedes 	struct hci_conn *conn;
3691a4790dbdSAndre Guedes 
3692a4790dbdSAndre Guedes 	if (!hci_pend_le_conn_lookup(hdev, addr, addr_type))
3693a4790dbdSAndre Guedes 		return;
3694a4790dbdSAndre Guedes 
3695a4790dbdSAndre Guedes 	conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
3696a4790dbdSAndre Guedes 			      HCI_AT_NO_BONDING);
3697a4790dbdSAndre Guedes 	if (!IS_ERR(conn))
3698a4790dbdSAndre Guedes 		return;
3699a4790dbdSAndre Guedes 
3700a4790dbdSAndre Guedes 	switch (PTR_ERR(conn)) {
3701a4790dbdSAndre Guedes 	case -EBUSY:
3702a4790dbdSAndre Guedes 		/* If hci_connect() returns -EBUSY it means there is already
3703a4790dbdSAndre Guedes 		 * an LE connection attempt going on. Since controllers don't
3704a4790dbdSAndre Guedes 		 * support more than one connection attempt at the time, we
3705a4790dbdSAndre Guedes 		 * don't consider this an error case.
3706a4790dbdSAndre Guedes 		 */
3707a4790dbdSAndre Guedes 		break;
3708a4790dbdSAndre Guedes 	default:
3709a4790dbdSAndre Guedes 		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
3710a4790dbdSAndre Guedes 	}
3711a4790dbdSAndre Guedes }
3712a4790dbdSAndre Guedes 
37136039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
37149aa04c91SAndre Guedes {
3715e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3716e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
37173c9e9195SAndre Guedes 	s8 rssi;
37189aa04c91SAndre Guedes 
3719a4790dbdSAndre Guedes 	hci_dev_lock(hdev);
3720a4790dbdSAndre Guedes 
3721e95beb41SAndre Guedes 	while (num_reports--) {
3722e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3723e95beb41SAndre Guedes 
3724a4790dbdSAndre Guedes 		if (ev->evt_type == LE_ADV_IND ||
3725a4790dbdSAndre Guedes 		    ev->evt_type == LE_ADV_DIRECT_IND)
3726a4790dbdSAndre Guedes 			check_pending_le_conn(hdev, &ev->bdaddr,
3727a4790dbdSAndre Guedes 					      ev->bdaddr_type);
3728a4790dbdSAndre Guedes 
37293c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
37303c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
373104124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
37323c9e9195SAndre Guedes 
3733e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
37349aa04c91SAndre Guedes 	}
3735a4790dbdSAndre Guedes 
3736a4790dbdSAndre Guedes 	hci_dev_unlock(hdev);
37379aa04c91SAndre Guedes }
37389aa04c91SAndre Guedes 
37396039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3740a7a595f6SVinicius Costa Gomes {
3741a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3742a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3743bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3744a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3745c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3746a7a595f6SVinicius Costa Gomes 
37479f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3748a7a595f6SVinicius Costa Gomes 
3749a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3750a7a595f6SVinicius Costa Gomes 
3751a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3752bea710feSVinicius Costa Gomes 	if (conn == NULL)
3753bea710feSVinicius Costa Gomes 		goto not_found;
3754a7a595f6SVinicius Costa Gomes 
375598a0b845SJohan Hedberg 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random, conn->out);
3756bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3757bea710feSVinicius Costa Gomes 		goto not_found;
3758bea710feSVinicius Costa Gomes 
3759bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3760a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3761c9839a11SVinicius Costa Gomes 
3762c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3763f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_HIGH;
3764f8776218SAndre Guedes 	else
3765f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_MEDIUM;
3766a7a595f6SVinicius Costa Gomes 
376789cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
3768a7a595f6SVinicius Costa Gomes 
3769a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3770a7a595f6SVinicius Costa Gomes 
3771c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3772c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3773c9839a11SVinicius Costa Gomes 		kfree(ltk);
3774c9839a11SVinicius Costa Gomes 	}
3775c9839a11SVinicius Costa Gomes 
3776a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3777bea710feSVinicius Costa Gomes 
3778bea710feSVinicius Costa Gomes 	return;
3779bea710feSVinicius Costa Gomes 
3780bea710feSVinicius Costa Gomes not_found:
3781bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3782bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3783bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3784a7a595f6SVinicius Costa Gomes }
3785a7a595f6SVinicius Costa Gomes 
37866039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3787fcd89c09SVille Tervo {
3788fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3789fcd89c09SVille Tervo 
3790fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3791fcd89c09SVille Tervo 
3792fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3793fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3794fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3795fcd89c09SVille Tervo 		break;
3796fcd89c09SVille Tervo 
37979aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
37989aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
37999aa04c91SAndre Guedes 		break;
38009aa04c91SAndre Guedes 
3801a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3802a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3803a7a595f6SVinicius Costa Gomes 		break;
3804a7a595f6SVinicius Costa Gomes 
3805fcd89c09SVille Tervo 	default:
3806fcd89c09SVille Tervo 		break;
3807fcd89c09SVille Tervo 	}
3808fcd89c09SVille Tervo }
3809fcd89c09SVille Tervo 
38109495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
38119495b2eeSAndrei Emeltchenko {
38129495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
38139495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
38149495b2eeSAndrei Emeltchenko 
38159495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
38169495b2eeSAndrei Emeltchenko 
38179495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
38189495b2eeSAndrei Emeltchenko 
38199495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
38209495b2eeSAndrei Emeltchenko 	if (!hcon)
38219495b2eeSAndrei Emeltchenko 		return;
38229495b2eeSAndrei Emeltchenko 
38239495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
38249495b2eeSAndrei Emeltchenko }
38259495b2eeSAndrei Emeltchenko 
38261da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
38271da177e4SLinus Torvalds {
3828a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3829a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
38301da177e4SLinus Torvalds 
3831b6ddb638SJohan Hedberg 	hci_dev_lock(hdev);
3832b6ddb638SJohan Hedberg 
3833b6ddb638SJohan Hedberg 	/* Received events are (currently) only needed when a request is
3834b6ddb638SJohan Hedberg 	 * ongoing so avoid unnecessary memory allocation.
3835b6ddb638SJohan Hedberg 	 */
3836b6ddb638SJohan Hedberg 	if (hdev->req_status == HCI_REQ_PEND) {
3837b6ddb638SJohan Hedberg 		kfree_skb(hdev->recv_evt);
3838b6ddb638SJohan Hedberg 		hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
3839b6ddb638SJohan Hedberg 	}
3840b6ddb638SJohan Hedberg 
3841b6ddb638SJohan Hedberg 	hci_dev_unlock(hdev);
3842b6ddb638SJohan Hedberg 
38431da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
38441da177e4SLinus Torvalds 
384502350a72SJohan Hedberg 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
3846c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
3847c1f23a2bSJohannes Berg 		u16 opcode = __le16_to_cpu(cmd_hdr->opcode);
384802350a72SJohan Hedberg 
384902350a72SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, 0);
385002350a72SJohan Hedberg 	}
385102350a72SJohan Hedberg 
3852a9de9248SMarcel Holtmann 	switch (event) {
38531da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
38541da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
38551da177e4SLinus Torvalds 		break;
38561da177e4SLinus Torvalds 
38571da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
38581da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
38591da177e4SLinus Torvalds 		break;
38601da177e4SLinus Torvalds 
3861a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3862a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
386321d9e30eSMarcel Holtmann 		break;
386421d9e30eSMarcel Holtmann 
38651da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
38661da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
38671da177e4SLinus Torvalds 		break;
38681da177e4SLinus Torvalds 
38691da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
38701da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
38711da177e4SLinus Torvalds 		break;
38721da177e4SLinus Torvalds 
38731da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
38741da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
38751da177e4SLinus Torvalds 		break;
38761da177e4SLinus Torvalds 
3877a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3878a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3879a9de9248SMarcel Holtmann 		break;
3880a9de9248SMarcel Holtmann 
38811da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
38821da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
38831da177e4SLinus Torvalds 		break;
38841da177e4SLinus Torvalds 
3885a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3886a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3887a9de9248SMarcel Holtmann 		break;
3888a9de9248SMarcel Holtmann 
3889a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3890a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3891a9de9248SMarcel Holtmann 		break;
3892a9de9248SMarcel Holtmann 
3893a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3894a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3895a9de9248SMarcel Holtmann 		break;
3896a9de9248SMarcel Holtmann 
3897a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3898a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3899a9de9248SMarcel Holtmann 		break;
3900a9de9248SMarcel Holtmann 
3901a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3902a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3903a9de9248SMarcel Holtmann 		break;
3904a9de9248SMarcel Holtmann 
3905a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3906a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3907a9de9248SMarcel Holtmann 		break;
3908a9de9248SMarcel Holtmann 
3909a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3910a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
39111da177e4SLinus Torvalds 		break;
39121da177e4SLinus Torvalds 
39131da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
39141da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
39151da177e4SLinus Torvalds 		break;
39161da177e4SLinus Torvalds 
39171da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
39181da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
39191da177e4SLinus Torvalds 		break;
39201da177e4SLinus Torvalds 
39211da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
39221da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
39231da177e4SLinus Torvalds 		break;
39241da177e4SLinus Torvalds 
39251da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
39261da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
39271da177e4SLinus Torvalds 		break;
39281da177e4SLinus Torvalds 
3929a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3930a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3931a8746417SMarcel Holtmann 		break;
3932a8746417SMarcel Holtmann 
393385a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
393485a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
393585a1e930SMarcel Holtmann 		break;
393685a1e930SMarcel Holtmann 
3937a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3938a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3939a9de9248SMarcel Holtmann 		break;
3940a9de9248SMarcel Holtmann 
3941a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3942a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3943a9de9248SMarcel Holtmann 		break;
3944a9de9248SMarcel Holtmann 
3945a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3946a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3947a9de9248SMarcel Holtmann 		break;
3948a9de9248SMarcel Holtmann 
3949a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3950a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
39511da177e4SLinus Torvalds 		break;
39521da177e4SLinus Torvalds 
39531c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
39541c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
39551c2e0041SJohan Hedberg 		break;
39561c2e0041SJohan Hedberg 
39570493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
39580493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
39590493684eSMarcel Holtmann 		break;
39600493684eSMarcel Holtmann 
396103b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
396203b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
396303b555e1SJohan Hedberg 		break;
396403b555e1SJohan Hedberg 
3965a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3966a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3967a5c29683SJohan Hedberg 		break;
3968a5c29683SJohan Hedberg 
39691143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
39701143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
39711143d458SBrian Gix 		break;
39721143d458SBrian Gix 
397392a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
397492a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
397592a25256SJohan Hedberg 		break;
397692a25256SJohan Hedberg 
397792a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
397892a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
397992a25256SJohan Hedberg 		break;
398092a25256SJohan Hedberg 
39810493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
39820493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
39830493684eSMarcel Holtmann 		break;
39840493684eSMarcel Holtmann 
398541a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
398641a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
398741a96212SMarcel Holtmann 		break;
398841a96212SMarcel Holtmann 
3989fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3990fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3991fcd89c09SVille Tervo 		break;
3992fcd89c09SVille Tervo 
39939495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
39949495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
39959495b2eeSAndrei Emeltchenko 		break;
39969495b2eeSAndrei Emeltchenko 
39972763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
39982763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
39992763eda6SSzymon Janc 		break;
40002763eda6SSzymon Janc 
4001d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
4002d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
4003d5e91192SAndrei Emeltchenko 		break;
4004d5e91192SAndrei Emeltchenko 
400527695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
400627695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
400727695fb4SAndrei Emeltchenko 		break;
400827695fb4SAndrei Emeltchenko 
4009606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4010606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
4011606e2a10SAndrei Emeltchenko 		break;
4012606e2a10SAndrei Emeltchenko 
40139eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
40149eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
40159eef6b3aSAndrei Emeltchenko 		break;
40169eef6b3aSAndrei Emeltchenko 
401725e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
401825e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
401925e89e99SAndrei Emeltchenko 		break;
402025e89e99SAndrei Emeltchenko 
40211da177e4SLinus Torvalds 	default:
40229f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
40231da177e4SLinus Torvalds 		break;
40241da177e4SLinus Torvalds 	}
40251da177e4SLinus Torvalds 
40261da177e4SLinus Torvalds 	kfree_skb(skb);
40271da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
40281da177e4SLinus Torvalds }
4029