xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 9489eca4)
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 
10410f36b589SMarcel Holtmann static void hci_cc_le_clear_white_list(struct hci_dev *hdev,
10420f36b589SMarcel Holtmann 				       struct sk_buff *skb)
10430f36b589SMarcel Holtmann {
10440f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
10450f36b589SMarcel Holtmann 
10460f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10470f36b589SMarcel Holtmann 
10480f36b589SMarcel Holtmann 	if (!status)
10490f36b589SMarcel Holtmann 		hci_white_list_clear(hdev);
10500f36b589SMarcel Holtmann }
10510f36b589SMarcel Holtmann 
10520f36b589SMarcel Holtmann static void hci_cc_le_add_to_white_list(struct hci_dev *hdev,
10530f36b589SMarcel Holtmann 					struct sk_buff *skb)
10540f36b589SMarcel Holtmann {
10550f36b589SMarcel Holtmann 	struct hci_cp_le_add_to_white_list *sent;
10560f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
10570f36b589SMarcel Holtmann 
10580f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10590f36b589SMarcel Holtmann 
10600f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST);
10610f36b589SMarcel Holtmann 	if (!sent)
10620f36b589SMarcel Holtmann 		return;
10630f36b589SMarcel Holtmann 
10640f36b589SMarcel Holtmann 	if (!status)
10650f36b589SMarcel Holtmann 		hci_white_list_add(hdev, &sent->bdaddr, sent->bdaddr_type);
10660f36b589SMarcel Holtmann }
10670f36b589SMarcel Holtmann 
10680f36b589SMarcel Holtmann static void hci_cc_le_del_from_white_list(struct hci_dev *hdev,
10690f36b589SMarcel Holtmann 					  struct sk_buff *skb)
10700f36b589SMarcel Holtmann {
10710f36b589SMarcel Holtmann 	struct hci_cp_le_del_from_white_list *sent;
10720f36b589SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
10730f36b589SMarcel Holtmann 
10740f36b589SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10750f36b589SMarcel Holtmann 
10760f36b589SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST);
10770f36b589SMarcel Holtmann 	if (!sent)
10780f36b589SMarcel Holtmann 		return;
10790f36b589SMarcel Holtmann 
10800f36b589SMarcel Holtmann 	if (!status)
10810f36b589SMarcel Holtmann 		hci_white_list_del(hdev, &sent->bdaddr, sent->bdaddr_type);
10820f36b589SMarcel Holtmann }
10830f36b589SMarcel Holtmann 
10849b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
10859b008c04SJohan Hedberg 					    struct sk_buff *skb)
10869b008c04SJohan Hedberg {
10879b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
10889b008c04SJohan Hedberg 
10899b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10909b008c04SJohan Hedberg 
10919b008c04SJohan Hedberg 	if (!rp->status)
10929b008c04SJohan Hedberg 		memcpy(hdev->le_states, rp->le_states, 8);
10939b008c04SJohan Hedberg }
10949b008c04SJohan Hedberg 
10956039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1096f9b49306SAndre Guedes 					   struct sk_buff *skb)
1097f9b49306SAndre Guedes {
109806199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1099f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1100f9b49306SAndre Guedes 
11019f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1102f9b49306SAndre Guedes 
110306199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
11048f984dfaSJohan Hedberg 	if (!sent)
1105f9b49306SAndre Guedes 		return;
1106f9b49306SAndre Guedes 
11078f984dfaSJohan Hedberg 	if (!status) {
1108416a4ae5SJohan Hedberg 		if (sent->le) {
1109cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE;
1110416a4ae5SJohan Hedberg 			set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1111416a4ae5SJohan Hedberg 		} else {
1112cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE;
1113416a4ae5SJohan Hedberg 			clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1114f3d3444aSJohan Hedberg 			clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1115416a4ae5SJohan Hedberg 		}
111653b2caabSJohan Hedberg 
111753b2caabSJohan Hedberg 		if (sent->simul)
1118cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE_BREDR;
111953b2caabSJohan Hedberg 		else
1120cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
11218f984dfaSJohan Hedberg 	}
1122f9b49306SAndre Guedes }
1123f9b49306SAndre Guedes 
112456ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
112556ed2cb8SJohan Hedberg {
112656ed2cb8SJohan Hedberg 	struct hci_cp_le_set_adv_param *cp;
112756ed2cb8SJohan Hedberg 	u8 status = *((u8 *) skb->data);
112856ed2cb8SJohan Hedberg 
112956ed2cb8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
113056ed2cb8SJohan Hedberg 
113156ed2cb8SJohan Hedberg 	if (status)
113256ed2cb8SJohan Hedberg 		return;
113356ed2cb8SJohan Hedberg 
113456ed2cb8SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
113556ed2cb8SJohan Hedberg 	if (!cp)
113656ed2cb8SJohan Hedberg 		return;
113756ed2cb8SJohan Hedberg 
113856ed2cb8SJohan Hedberg 	hci_dev_lock(hdev);
113956ed2cb8SJohan Hedberg 	hdev->adv_addr_type = cp->own_address_type;
114056ed2cb8SJohan Hedberg 	hci_dev_unlock(hdev);
114156ed2cb8SJohan Hedberg }
114256ed2cb8SJohan Hedberg 
114393c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
114493c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
114593c284eeSAndrei Emeltchenko {
114693c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
114793c284eeSAndrei Emeltchenko 
114893c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
114993c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
115093c284eeSAndrei Emeltchenko 
115193c284eeSAndrei Emeltchenko 	if (rp->status)
115293c284eeSAndrei Emeltchenko 		return;
115393c284eeSAndrei Emeltchenko 
115493c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
115593c284eeSAndrei Emeltchenko }
115693c284eeSAndrei Emeltchenko 
11576039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1158a9de9248SMarcel Holtmann {
11599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1160a9de9248SMarcel Holtmann 
1161a9de9248SMarcel Holtmann 	if (status) {
1162a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1163314b2381SJohan Hedberg 		return;
1164314b2381SJohan Hedberg 	}
1165314b2381SJohan Hedberg 
116689352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1167a9de9248SMarcel Holtmann }
1168a9de9248SMarcel Holtmann 
11696039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11701da177e4SLinus Torvalds {
1171a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11721da177e4SLinus Torvalds 	struct hci_conn *conn;
11731da177e4SLinus Torvalds 
11749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1175a9de9248SMarcel Holtmann 
1176a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11771da177e4SLinus Torvalds 	if (!cp)
11781da177e4SLinus Torvalds 		return;
11791da177e4SLinus Torvalds 
11801da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11811da177e4SLinus Torvalds 
11821da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11831da177e4SLinus Torvalds 
11846ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
11851da177e4SLinus Torvalds 
11861da177e4SLinus Torvalds 	if (status) {
11871da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11884c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11891da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11901da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11911da177e4SLinus Torvalds 				hci_conn_del(conn);
11924c67bc74SMarcel Holtmann 			} else
11934c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11941da177e4SLinus Torvalds 		}
11951da177e4SLinus Torvalds 	} else {
11961da177e4SLinus Torvalds 		if (!conn) {
11971da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11981da177e4SLinus Torvalds 			if (conn) {
1199a0c808b3SJohan Hedberg 				conn->out = true;
12001da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
12011da177e4SLinus Torvalds 			} else
1202893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12031da177e4SLinus Torvalds 		}
12041da177e4SLinus Torvalds 	}
12051da177e4SLinus Torvalds 
12061da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12071da177e4SLinus Torvalds }
12081da177e4SLinus Torvalds 
1209a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12101da177e4SLinus Torvalds {
1211a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12121da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12131da177e4SLinus Torvalds 	__u16 handle;
12141da177e4SLinus Torvalds 
12159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1216b6a0dc82SMarcel Holtmann 
1217a9de9248SMarcel Holtmann 	if (!status)
1218a9de9248SMarcel Holtmann 		return;
1219a9de9248SMarcel Holtmann 
1220a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12211da177e4SLinus Torvalds 	if (!cp)
1222a9de9248SMarcel Holtmann 		return;
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12251da177e4SLinus Torvalds 
12269f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
12271da177e4SLinus Torvalds 
12281da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12291da177e4SLinus Torvalds 
12301da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12315a08ecceSAndrei Emeltchenko 	if (acl) {
12325a08ecceSAndrei Emeltchenko 		sco = acl->link;
12335a08ecceSAndrei Emeltchenko 		if (sco) {
12341da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12351da177e4SLinus Torvalds 
12361da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12371da177e4SLinus Torvalds 			hci_conn_del(sco);
12381da177e4SLinus Torvalds 		}
12395a08ecceSAndrei Emeltchenko 	}
12401da177e4SLinus Torvalds 
12411da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12421da177e4SLinus Torvalds }
12431da177e4SLinus Torvalds 
1244f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1245f8558555SMarcel Holtmann {
1246f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1247f8558555SMarcel Holtmann 	struct hci_conn *conn;
1248f8558555SMarcel Holtmann 
12499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1250f8558555SMarcel Holtmann 
1251f8558555SMarcel Holtmann 	if (!status)
1252f8558555SMarcel Holtmann 		return;
1253f8558555SMarcel Holtmann 
1254f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1255f8558555SMarcel Holtmann 	if (!cp)
1256f8558555SMarcel Holtmann 		return;
1257f8558555SMarcel Holtmann 
1258f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1259f8558555SMarcel Holtmann 
1260f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1261f8558555SMarcel Holtmann 	if (conn) {
1262f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1263f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
126476a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1265f8558555SMarcel Holtmann 		}
1266f8558555SMarcel Holtmann 	}
1267f8558555SMarcel Holtmann 
1268f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1269f8558555SMarcel Holtmann }
1270f8558555SMarcel Holtmann 
1271f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1272f8558555SMarcel Holtmann {
1273f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1274f8558555SMarcel Holtmann 	struct hci_conn *conn;
1275f8558555SMarcel Holtmann 
12769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1277f8558555SMarcel Holtmann 
1278f8558555SMarcel Holtmann 	if (!status)
1279f8558555SMarcel Holtmann 		return;
1280f8558555SMarcel Holtmann 
1281f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1282f8558555SMarcel Holtmann 	if (!cp)
1283f8558555SMarcel Holtmann 		return;
1284f8558555SMarcel Holtmann 
1285f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1286f8558555SMarcel Holtmann 
1287f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1288f8558555SMarcel Holtmann 	if (conn) {
1289f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1290f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
129176a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1292f8558555SMarcel Holtmann 		}
1293f8558555SMarcel Holtmann 	}
1294f8558555SMarcel Holtmann 
1295f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1296f8558555SMarcel Holtmann }
1297f8558555SMarcel Holtmann 
1298127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1299392599b9SJohan Hedberg 				    struct hci_conn *conn)
1300392599b9SJohan Hedberg {
1301392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1302392599b9SJohan Hedberg 		return 0;
1303392599b9SJohan Hedberg 
1304765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1305392599b9SJohan Hedberg 		return 0;
1306392599b9SJohan Hedberg 
1307392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1308264b8b4eSJohan Hedberg 	 * devices with sec_level MEDIUM or HIGH or if MITM protection
1309264b8b4eSJohan Hedberg 	 * is requested.
1310264b8b4eSJohan Hedberg 	 */
1311807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1312264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
1313264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
1314392599b9SJohan Hedberg 		return 0;
1315392599b9SJohan Hedberg 
1316392599b9SJohan Hedberg 	return 1;
1317392599b9SJohan Hedberg }
1318392599b9SJohan Hedberg 
13196039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
132000abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
132130dc78e1SJohan Hedberg {
132230dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
132330dc78e1SJohan Hedberg 
132430dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
132530dc78e1SJohan Hedberg 
132630dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
132730dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
132830dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
132930dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
133030dc78e1SJohan Hedberg 
133130dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
133230dc78e1SJohan Hedberg }
133330dc78e1SJohan Hedberg 
1334b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
133530dc78e1SJohan Hedberg {
133630dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
133730dc78e1SJohan Hedberg 	struct inquiry_entry *e;
133830dc78e1SJohan Hedberg 
1339b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1340b644ba33SJohan Hedberg 		return false;
1341b644ba33SJohan Hedberg 
1342b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1343c810089cSRam Malovany 	if (!e)
1344c810089cSRam Malovany 		return false;
1345c810089cSRam Malovany 
1346b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1347b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1348b644ba33SJohan Hedberg 		return true;
1349b644ba33SJohan Hedberg 	}
1350b644ba33SJohan Hedberg 
1351b644ba33SJohan Hedberg 	return false;
1352b644ba33SJohan Hedberg }
1353b644ba33SJohan Hedberg 
1354b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1355b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1356b644ba33SJohan Hedberg {
1357b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1358b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1359b644ba33SJohan Hedberg 
1360b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
136104124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
136204124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1363b644ba33SJohan Hedberg 
1364b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1365b644ba33SJohan Hedberg 		return;
1366b644ba33SJohan Hedberg 
136730dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
136830dc78e1SJohan Hedberg 		goto discov_complete;
136930dc78e1SJohan Hedberg 
137030dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
137130dc78e1SJohan Hedberg 		return;
137230dc78e1SJohan Hedberg 
137330dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
13747cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
13757cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
13767cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
13777cc8380eSRam Malovany 	 * Event */
13787cc8380eSRam Malovany 	if (!e)
13797cc8380eSRam Malovany 		return;
13807cc8380eSRam Malovany 
138130dc78e1SJohan Hedberg 	list_del(&e->list);
13827cc8380eSRam Malovany 	if (name) {
13837cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1384b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1385b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1386c3e7c0d9SRam Malovany 	} else {
1387c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
138830dc78e1SJohan Hedberg 	}
138930dc78e1SJohan Hedberg 
1390b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
139130dc78e1SJohan Hedberg 		return;
139230dc78e1SJohan Hedberg 
139330dc78e1SJohan Hedberg discov_complete:
139430dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
139530dc78e1SJohan Hedberg }
139630dc78e1SJohan Hedberg 
1397a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13981da177e4SLinus Torvalds {
1399127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1400127178d2SJohan Hedberg 	struct hci_conn *conn;
1401127178d2SJohan Hedberg 
14029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1403127178d2SJohan Hedberg 
1404127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1405127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1406127178d2SJohan Hedberg 	if (!status)
1407127178d2SJohan Hedberg 		return;
1408127178d2SJohan Hedberg 
1409127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1410127178d2SJohan Hedberg 	if (!cp)
1411127178d2SJohan Hedberg 		return;
1412127178d2SJohan Hedberg 
1413127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1414127178d2SJohan Hedberg 
1415127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1416b644ba33SJohan Hedberg 
1417b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1418b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1419b644ba33SJohan Hedberg 
142079c6c70cSJohan Hedberg 	if (!conn)
142179c6c70cSJohan Hedberg 		goto unlock;
142279c6c70cSJohan Hedberg 
142379c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
142479c6c70cSJohan Hedberg 		goto unlock;
142579c6c70cSJohan Hedberg 
142651a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1427c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
1428c1f23a2bSJohannes Berg 
1429c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
1430c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1431c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
1432127178d2SJohan Hedberg 	}
1433127178d2SJohan Hedberg 
143479c6c70cSJohan Hedberg unlock:
1435127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1436a9de9248SMarcel Holtmann }
14371da177e4SLinus Torvalds 
1438769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1439769be974SMarcel Holtmann {
1440769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1441769be974SMarcel Holtmann 	struct hci_conn *conn;
1442769be974SMarcel Holtmann 
14439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1444769be974SMarcel Holtmann 
1445769be974SMarcel Holtmann 	if (!status)
1446769be974SMarcel Holtmann 		return;
1447769be974SMarcel Holtmann 
1448769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1449769be974SMarcel Holtmann 	if (!cp)
1450769be974SMarcel Holtmann 		return;
1451769be974SMarcel Holtmann 
1452769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1453769be974SMarcel Holtmann 
1454769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1455769be974SMarcel Holtmann 	if (conn) {
1456769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1457769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
145876a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1459769be974SMarcel Holtmann 		}
1460769be974SMarcel Holtmann 	}
1461769be974SMarcel Holtmann 
1462769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1463769be974SMarcel Holtmann }
1464769be974SMarcel Holtmann 
1465769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1466769be974SMarcel Holtmann {
1467769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1468769be974SMarcel Holtmann 	struct hci_conn *conn;
1469769be974SMarcel Holtmann 
14709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1471769be974SMarcel Holtmann 
1472769be974SMarcel Holtmann 	if (!status)
1473769be974SMarcel Holtmann 		return;
1474769be974SMarcel Holtmann 
1475769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1476769be974SMarcel Holtmann 	if (!cp)
1477769be974SMarcel Holtmann 		return;
1478769be974SMarcel Holtmann 
1479769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1480769be974SMarcel Holtmann 
1481769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1482769be974SMarcel Holtmann 	if (conn) {
1483769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1484769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
148576a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1486769be974SMarcel Holtmann 		}
1487769be974SMarcel Holtmann 	}
1488769be974SMarcel Holtmann 
1489769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1490769be974SMarcel Holtmann }
1491769be974SMarcel Holtmann 
1492a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1493a9de9248SMarcel Holtmann {
1494b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1495b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1496b6a0dc82SMarcel Holtmann 	__u16 handle;
1497b6a0dc82SMarcel Holtmann 
14989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1499b6a0dc82SMarcel Holtmann 
1500b6a0dc82SMarcel Holtmann 	if (!status)
1501b6a0dc82SMarcel Holtmann 		return;
1502b6a0dc82SMarcel Holtmann 
1503b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1504b6a0dc82SMarcel Holtmann 	if (!cp)
1505b6a0dc82SMarcel Holtmann 		return;
1506b6a0dc82SMarcel Holtmann 
1507b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1508b6a0dc82SMarcel Holtmann 
15099f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1510b6a0dc82SMarcel Holtmann 
1511b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1512b6a0dc82SMarcel Holtmann 
1513b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15145a08ecceSAndrei Emeltchenko 	if (acl) {
15155a08ecceSAndrei Emeltchenko 		sco = acl->link;
15165a08ecceSAndrei Emeltchenko 		if (sco) {
1517b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1518b6a0dc82SMarcel Holtmann 
1519b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1520b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1521b6a0dc82SMarcel Holtmann 		}
15225a08ecceSAndrei Emeltchenko 	}
1523b6a0dc82SMarcel Holtmann 
1524b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1525a9de9248SMarcel Holtmann }
1526a9de9248SMarcel Holtmann 
1527a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1528a9de9248SMarcel Holtmann {
1529a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
153004837f64SMarcel Holtmann 	struct hci_conn *conn;
153104837f64SMarcel Holtmann 
15329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1533a9de9248SMarcel Holtmann 
1534a9de9248SMarcel Holtmann 	if (!status)
1535a9de9248SMarcel Holtmann 		return;
1536a9de9248SMarcel Holtmann 
1537a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
153804837f64SMarcel Holtmann 	if (!cp)
1539a9de9248SMarcel Holtmann 		return;
154004837f64SMarcel Holtmann 
154104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
154204837f64SMarcel Holtmann 
154304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1544e73439d8SMarcel Holtmann 	if (conn) {
154551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
154604837f64SMarcel Holtmann 
154751a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1548e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1549e73439d8SMarcel Holtmann 	}
1550e73439d8SMarcel Holtmann 
155104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
155204837f64SMarcel Holtmann }
155304837f64SMarcel Holtmann 
1554a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1555a9de9248SMarcel Holtmann {
1556a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
155704837f64SMarcel Holtmann 	struct hci_conn *conn;
155804837f64SMarcel Holtmann 
15599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1560a9de9248SMarcel Holtmann 
1561a9de9248SMarcel Holtmann 	if (!status)
1562a9de9248SMarcel Holtmann 		return;
1563a9de9248SMarcel Holtmann 
1564a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
156504837f64SMarcel Holtmann 	if (!cp)
1566a9de9248SMarcel Holtmann 		return;
156704837f64SMarcel Holtmann 
156804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
156904837f64SMarcel Holtmann 
157004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1571e73439d8SMarcel Holtmann 	if (conn) {
157251a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
157304837f64SMarcel Holtmann 
157451a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1575e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1576e73439d8SMarcel Holtmann 	}
1577e73439d8SMarcel Holtmann 
157804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
157904837f64SMarcel Holtmann }
158004837f64SMarcel Holtmann 
158188c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
158288c3df13SJohan Hedberg {
158388c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
158488c3df13SJohan Hedberg 	struct hci_conn *conn;
158588c3df13SJohan Hedberg 
158688c3df13SJohan Hedberg 	if (!status)
158788c3df13SJohan Hedberg 		return;
158888c3df13SJohan Hedberg 
158988c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
159088c3df13SJohan Hedberg 	if (!cp)
159188c3df13SJohan Hedberg 		return;
159288c3df13SJohan Hedberg 
159388c3df13SJohan Hedberg 	hci_dev_lock(hdev);
159488c3df13SJohan Hedberg 
159588c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
159688c3df13SJohan Hedberg 	if (conn)
159788c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
159888c3df13SJohan Hedberg 				       conn->dst_type, status);
159988c3df13SJohan Hedberg 
160088c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
160188c3df13SJohan Hedberg }
160288c3df13SJohan Hedberg 
1603a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1604a02226d6SAndrei Emeltchenko {
160593c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
160693c284eeSAndrei Emeltchenko 
1607a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
160893c284eeSAndrei Emeltchenko 
160993c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
161093c284eeSAndrei Emeltchenko 	if (!cp)
161193c284eeSAndrei Emeltchenko 		return;
161293c284eeSAndrei Emeltchenko 
1613e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1614e58917b9SAndrei Emeltchenko 
1615e58917b9SAndrei Emeltchenko 	if (status) {
1616e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1617e58917b9SAndrei Emeltchenko 
1618e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1619e58917b9SAndrei Emeltchenko 		if (hcon)
1620e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1621e58917b9SAndrei Emeltchenko 	} else {
162293c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1623a02226d6SAndrei Emeltchenko 	}
1624a02226d6SAndrei Emeltchenko 
1625e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1626e58917b9SAndrei Emeltchenko }
1627e58917b9SAndrei Emeltchenko 
16280b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
16290b26ab9dSAndrei Emeltchenko {
16300b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
16310b26ab9dSAndrei Emeltchenko 
16320b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
16330b26ab9dSAndrei Emeltchenko 
16340b26ab9dSAndrei Emeltchenko 	if (status)
16350b26ab9dSAndrei Emeltchenko 		return;
16360b26ab9dSAndrei Emeltchenko 
16370b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
16380b26ab9dSAndrei Emeltchenko 	if (!cp)
16390b26ab9dSAndrei Emeltchenko 		return;
16400b26ab9dSAndrei Emeltchenko 
16410b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
16420b26ab9dSAndrei Emeltchenko }
16430b26ab9dSAndrei Emeltchenko 
1644cb1d68f7SJohan Hedberg static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
1645cb1d68f7SJohan Hedberg {
1646cb1d68f7SJohan Hedberg 	struct hci_cp_le_create_conn *cp;
1647cb1d68f7SJohan Hedberg 	struct hci_conn *conn;
1648cb1d68f7SJohan Hedberg 
1649cb1d68f7SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1650cb1d68f7SJohan Hedberg 
1651cb1d68f7SJohan Hedberg 	/* All connection failure handling is taken care of by the
1652cb1d68f7SJohan Hedberg 	 * hci_le_conn_failed function which is triggered by the HCI
1653cb1d68f7SJohan Hedberg 	 * request completion callbacks used for connecting.
1654cb1d68f7SJohan Hedberg 	 */
1655cb1d68f7SJohan Hedberg 	if (status)
1656cb1d68f7SJohan Hedberg 		return;
1657cb1d68f7SJohan Hedberg 
1658cb1d68f7SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1659cb1d68f7SJohan Hedberg 	if (!cp)
1660cb1d68f7SJohan Hedberg 		return;
1661cb1d68f7SJohan Hedberg 
1662cb1d68f7SJohan Hedberg 	hci_dev_lock(hdev);
1663cb1d68f7SJohan Hedberg 
1664cb1d68f7SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1665cb1d68f7SJohan Hedberg 	if (!conn)
1666cb1d68f7SJohan Hedberg 		goto unlock;
1667cb1d68f7SJohan Hedberg 
1668cb1d68f7SJohan Hedberg 	/* Store the initiator and responder address information which
1669cb1d68f7SJohan Hedberg 	 * is needed for SMP. These values will not change during the
1670cb1d68f7SJohan Hedberg 	 * lifetime of the connection.
1671cb1d68f7SJohan Hedberg 	 */
1672cb1d68f7SJohan Hedberg 	conn->init_addr_type = cp->own_address_type;
1673cb1d68f7SJohan Hedberg 	if (cp->own_address_type == ADDR_LE_DEV_RANDOM)
1674cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &hdev->random_addr);
1675cb1d68f7SJohan Hedberg 	else
1676cb1d68f7SJohan Hedberg 		bacpy(&conn->init_addr, &hdev->bdaddr);
1677cb1d68f7SJohan Hedberg 
1678cb1d68f7SJohan Hedberg 	conn->resp_addr_type = cp->peer_addr_type;
1679cb1d68f7SJohan Hedberg 	bacpy(&conn->resp_addr, &cp->peer_addr);
1680cb1d68f7SJohan Hedberg 
16819489eca4SJohan Hedberg 	/* We don't want the connection attempt to stick around
16829489eca4SJohan Hedberg 	 * indefinitely since LE doesn't have a page timeout concept
16839489eca4SJohan Hedberg 	 * like BR/EDR. Set a timer for any connection that doesn't use
16849489eca4SJohan Hedberg 	 * the white list for connecting.
16859489eca4SJohan Hedberg 	 */
16869489eca4SJohan Hedberg 	if (cp->filter_policy == HCI_LE_USE_PEER_ADDR)
16879489eca4SJohan Hedberg 		queue_delayed_work(conn->hdev->workqueue,
16889489eca4SJohan Hedberg 				   &conn->le_conn_timeout,
16899489eca4SJohan Hedberg 				   HCI_LE_CONN_TIMEOUT);
16909489eca4SJohan Hedberg 
1691cb1d68f7SJohan Hedberg unlock:
1692cb1d68f7SJohan Hedberg 	hci_dev_unlock(hdev);
1693cb1d68f7SJohan Hedberg }
1694cb1d68f7SJohan Hedberg 
16956039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16961da177e4SLinus Torvalds {
16971da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
169830dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
169930dc78e1SJohan Hedberg 	struct inquiry_entry *e;
17001da177e4SLinus Torvalds 
17019f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
17021da177e4SLinus Torvalds 
1703a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
170489352e7dSAndre Guedes 
170589352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
170689352e7dSAndre Guedes 		return;
170789352e7dSAndre Guedes 
17083e13fa1eSAndre Guedes 	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
17093e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
17103e13fa1eSAndre Guedes 
1711a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
171230dc78e1SJohan Hedberg 		return;
171330dc78e1SJohan Hedberg 
171456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
171530dc78e1SJohan Hedberg 
1716343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
171730dc78e1SJohan Hedberg 		goto unlock;
171830dc78e1SJohan Hedberg 
171930dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1720ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
172130dc78e1SJohan Hedberg 		goto unlock;
172230dc78e1SJohan Hedberg 	}
172330dc78e1SJohan Hedberg 
172430dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
172530dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
172630dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
172730dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
172830dc78e1SJohan Hedberg 	} else {
172930dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
173030dc78e1SJohan Hedberg 	}
173130dc78e1SJohan Hedberg 
173230dc78e1SJohan Hedberg unlock:
173356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
17341da177e4SLinus Torvalds }
17351da177e4SLinus Torvalds 
17366039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
17371da177e4SLinus Torvalds {
173845bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1739a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
17401da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
17411da177e4SLinus Torvalds 
17421da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
17431da177e4SLinus Torvalds 
174445bb4bf0SMarcel Holtmann 	if (!num_rsp)
174545bb4bf0SMarcel Holtmann 		return;
174645bb4bf0SMarcel Holtmann 
17471519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
17481519cc17SAndre Guedes 		return;
17491519cc17SAndre Guedes 
17501da177e4SLinus Torvalds 	hci_dev_lock(hdev);
175145bb4bf0SMarcel Holtmann 
1752e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1753388fc8faSJohan Hedberg 		bool name_known, ssp;
17543175405bSJohan Hedberg 
17551da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
17561da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
17571da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
17581da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
17591da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
17601da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17611da177e4SLinus Torvalds 		data.rssi		= 0x00;
176241a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17633175405bSJohan Hedberg 
1764388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
176548264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
176604124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
176704124681SGustavo F. Padovan 				  0);
17681da177e4SLinus Torvalds 	}
176945bb4bf0SMarcel Holtmann 
17701da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17711da177e4SLinus Torvalds }
17721da177e4SLinus Torvalds 
17736039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17741da177e4SLinus Torvalds {
1775a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1776a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17771da177e4SLinus Torvalds 
1778a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
177945bb4bf0SMarcel Holtmann 
17801da177e4SLinus Torvalds 	hci_dev_lock(hdev);
178145bb4bf0SMarcel Holtmann 
1782a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17839499237aSMarcel Holtmann 	if (!conn) {
17849499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17859499237aSMarcel Holtmann 			goto unlock;
17869499237aSMarcel Holtmann 
17879499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1788a9de9248SMarcel Holtmann 		if (!conn)
1789a9de9248SMarcel Holtmann 			goto unlock;
179045bb4bf0SMarcel Holtmann 
17919499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17929499237aSMarcel Holtmann 	}
17939499237aSMarcel Holtmann 
1794a9de9248SMarcel Holtmann 	if (!ev->status) {
1795a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1796769be974SMarcel Holtmann 
1797769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1798769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1799769be974SMarcel Holtmann 			hci_conn_hold(conn);
1800a9ea3ed9SSzymon Janc 
1801a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1802a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1803a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1804a9ea3ed9SSzymon Janc 			else
1805052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1806769be974SMarcel Holtmann 		} else
1807a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1808a9de9248SMarcel Holtmann 
18097d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
18107d0db0a3SMarcel Holtmann 
1811a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1812a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1813a9de9248SMarcel Holtmann 
1814a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1815a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1816a9de9248SMarcel Holtmann 
1817a9de9248SMarcel Holtmann 		/* Get remote features */
1818a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1819a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1820a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1821769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1822769be974SMarcel Holtmann 				     sizeof(cp), &cp);
182345bb4bf0SMarcel Holtmann 		}
1824a9de9248SMarcel Holtmann 
1825a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1826d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1827a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1828a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1829a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
183004124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
183104124681SGustavo F. Padovan 				     &cp);
1832a9de9248SMarcel Holtmann 		}
183317d5c04cSJohan Hedberg 	} else {
1834a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
183517d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
183664c7b77cSMarcel Holtmann 			mgmt_connect_failed(hdev, &conn->dst, conn->type,
183748264f06SJohan Hedberg 					    conn->dst_type, ev->status);
183817d5c04cSJohan Hedberg 	}
183945bb4bf0SMarcel Holtmann 
1840e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1841e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
184245bb4bf0SMarcel Holtmann 
1843769be974SMarcel Holtmann 	if (ev->status) {
1844a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1845a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1846c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1847c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1848a9de9248SMarcel Holtmann 
1849a9de9248SMarcel Holtmann unlock:
18501da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1851a9de9248SMarcel Holtmann 
1852a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
18531da177e4SLinus Torvalds }
18541da177e4SLinus Torvalds 
18556039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18561da177e4SLinus Torvalds {
1857a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
18581da177e4SLinus Torvalds 	int mask = hdev->link_mode;
185920714bfeSFrédéric Dalleau 	__u8 flags = 0;
18601da177e4SLinus Torvalds 
18616ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
1862807deac2SGustavo Padovan 	       ev->link_type);
18631da177e4SLinus Torvalds 
186420714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
186520714bfeSFrédéric Dalleau 				      &flags);
18661da177e4SLinus Torvalds 
1867138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1868b9ee0a78SMarcel Holtmann 	    !hci_blacklist_lookup(hdev, &ev->bdaddr, BDADDR_BREDR)) {
18691da177e4SLinus Torvalds 		/* Connection accepted */
1870c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
18711da177e4SLinus Torvalds 		struct hci_conn *conn;
18721da177e4SLinus Torvalds 
18731da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1874b6a0dc82SMarcel Holtmann 
1875cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1876cc11b9c1SAndrei Emeltchenko 		if (ie)
1877c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1878c7bdd502SMarcel Holtmann 
18798fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
18808fc9ced3SGustavo Padovan 					       &ev->bdaddr);
18811da177e4SLinus Torvalds 		if (!conn) {
1882cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1883cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1884893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
18851da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
18861da177e4SLinus Torvalds 				return;
18871da177e4SLinus Torvalds 			}
18881da177e4SLinus Torvalds 		}
1889b6a0dc82SMarcel Holtmann 
18901da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
1891b6a0dc82SMarcel Holtmann 
18921da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
18931da177e4SLinus Torvalds 
189420714bfeSFrédéric Dalleau 		if (ev->link_type == ACL_LINK ||
189520714bfeSFrédéric Dalleau 		    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
1896b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
189720714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1898b6a0dc82SMarcel Holtmann 
18991da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
19001da177e4SLinus Torvalds 
19011da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
19021da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
19031da177e4SLinus Torvalds 			else
19041da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
19051da177e4SLinus Torvalds 
190604124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
190704124681SGustavo F. Padovan 				     &cp);
190820714bfeSFrédéric Dalleau 		} else if (!(flags & HCI_PROTO_DEFER)) {
1909b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
191020714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1911b6a0dc82SMarcel Holtmann 
1912b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1913a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1914b6a0dc82SMarcel Holtmann 
191582781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
191682781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
191782781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1918b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1919b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1920b6a0dc82SMarcel Holtmann 
1921b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1922b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
192320714bfeSFrédéric Dalleau 		} else {
192420714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT2;
192520714bfeSFrédéric Dalleau 			hci_proto_connect_cfm(conn, 0);
1926b6a0dc82SMarcel Holtmann 		}
19271da177e4SLinus Torvalds 	} else {
19281da177e4SLinus Torvalds 		/* Connection rejected */
19291da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
19301da177e4SLinus Torvalds 
19311da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
19329f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1933a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
19341da177e4SLinus Torvalds 	}
19351da177e4SLinus Torvalds }
19361da177e4SLinus Torvalds 
1937f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
1938f0d6a0eaSMikel Astiz {
1939f0d6a0eaSMikel Astiz 	switch (err) {
1940f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
1941f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
1942f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
1943f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
1944f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
1945f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
1946f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
1947f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
1948f0d6a0eaSMikel Astiz 	default:
1949f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
1950f0d6a0eaSMikel Astiz 	}
1951f0d6a0eaSMikel Astiz }
1952f0d6a0eaSMikel Astiz 
19536039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19541da177e4SLinus Torvalds {
1955a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
1956abf54a50SAndre Guedes 	u8 reason = hci_to_mgmt_reason(ev->reason);
19579fcb18efSAndre Guedes 	struct hci_conn_params *params;
195804837f64SMarcel Holtmann 	struct hci_conn *conn;
195912d4a3b2SJohan Hedberg 	bool mgmt_connected;
19603846220bSAndre Guedes 	u8 type;
19611da177e4SLinus Torvalds 
19629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
19631da177e4SLinus Torvalds 
19641da177e4SLinus Torvalds 	hci_dev_lock(hdev);
19651da177e4SLinus Torvalds 
196604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1967f7520543SJohan Hedberg 	if (!conn)
1968f7520543SJohan Hedberg 		goto unlock;
1969f7520543SJohan Hedberg 
1970f0d6a0eaSMikel Astiz 	if (ev->status) {
197188c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
197288c3df13SJohan Hedberg 				       conn->dst_type, ev->status);
1973abf54a50SAndre Guedes 		goto unlock;
1974abf54a50SAndre Guedes 	}
1975f0d6a0eaSMikel Astiz 
19763846220bSAndre Guedes 	conn->state = BT_CLOSED;
19773846220bSAndre Guedes 
197812d4a3b2SJohan Hedberg 	mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
197912d4a3b2SJohan Hedberg 	mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
198012d4a3b2SJohan Hedberg 				reason, mgmt_connected);
1981f7520543SJohan Hedberg 
19823846220bSAndre Guedes 	if (conn->type == ACL_LINK && conn->flush_key)
19836ec5bcadSVishal Agarwal 		hci_remove_link_key(hdev, &conn->dst);
19843846220bSAndre Guedes 
19859fcb18efSAndre Guedes 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
19869fcb18efSAndre Guedes 	if (params) {
19879fcb18efSAndre Guedes 		switch (params->auto_connect) {
19889fcb18efSAndre Guedes 		case HCI_AUTO_CONN_LINK_LOSS:
19899fcb18efSAndre Guedes 			if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
19909fcb18efSAndre Guedes 				break;
19919fcb18efSAndre Guedes 			/* Fall through */
19929fcb18efSAndre Guedes 
19939fcb18efSAndre Guedes 		case HCI_AUTO_CONN_ALWAYS:
19949fcb18efSAndre Guedes 			hci_pend_le_conn_add(hdev, &conn->dst, conn->dst_type);
19959fcb18efSAndre Guedes 			break;
19969fcb18efSAndre Guedes 
19979fcb18efSAndre Guedes 		default:
19989fcb18efSAndre Guedes 			break;
19999fcb18efSAndre Guedes 		}
20009fcb18efSAndre Guedes 	}
20019fcb18efSAndre Guedes 
20023846220bSAndre Guedes 	type = conn->type;
20033846220bSAndre Guedes 
20042950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
20051da177e4SLinus Torvalds 	hci_conn_del(conn);
20062210246cSJohan Hedberg 
20072210246cSJohan Hedberg 	/* Re-enable advertising if necessary, since it might
20082210246cSJohan Hedberg 	 * have been disabled by the connection. From the
20092210246cSJohan Hedberg 	 * HCI_LE_Set_Advertise_Enable command description in
20102210246cSJohan Hedberg 	 * the core specification (v4.0):
20112210246cSJohan Hedberg 	 * "The Controller shall continue advertising until the Host
20122210246cSJohan Hedberg 	 * issues an LE_Set_Advertise_Enable command with
20132210246cSJohan Hedberg 	 * Advertising_Enable set to 0x00 (Advertising is disabled)
20142210246cSJohan Hedberg 	 * or until a connection is created or until the Advertising
20152210246cSJohan Hedberg 	 * is timed out due to Directed Advertising."
20162210246cSJohan Hedberg 	 */
20172210246cSJohan Hedberg 	if (type == LE_LINK)
20185976e608SMarcel Holtmann 		mgmt_reenable_advertising(hdev);
20191da177e4SLinus Torvalds 
2020f7520543SJohan Hedberg unlock:
20211da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
20221da177e4SLinus Torvalds }
20231da177e4SLinus Torvalds 
20246039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2025a9de9248SMarcel Holtmann {
2026a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2027a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2028a9de9248SMarcel Holtmann 
20299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2030a9de9248SMarcel Holtmann 
2031a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2032a9de9248SMarcel Holtmann 
2033a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2034d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2035d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2036d7556e20SWaldemar Rymarkiewicz 
2037765c2a96SJohan Hedberg 	if (!ev->status) {
2038aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
203951a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2040d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
204119f8def0SWaldemar Rymarkiewicz 		} else {
2042a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2043765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
204419f8def0SWaldemar Rymarkiewicz 		}
20452a611692SJohan Hedberg 	} else {
2046bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
2047bab73cb6SJohan Hedberg 				 ev->status);
20482a611692SJohan Hedberg 	}
2049a9de9248SMarcel Holtmann 
205051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
205151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2052a9de9248SMarcel Holtmann 
2053f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2054aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2055f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2056f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2057f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2058d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2059d7556e20SWaldemar Rymarkiewicz 				     &cp);
2060f8558555SMarcel Holtmann 		} else {
2061f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2062f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
206376a68ba0SDavid Herrmann 			hci_conn_drop(conn);
2064f8558555SMarcel Holtmann 		}
2065052b30b0SMarcel Holtmann 	} else {
2066a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2067a9de9248SMarcel Holtmann 
2068052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2069052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
207076a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2071052b30b0SMarcel Holtmann 	}
2072052b30b0SMarcel Holtmann 
207351a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2074a9de9248SMarcel Holtmann 		if (!ev->status) {
2075a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2076f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2077f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2078d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2079d7556e20SWaldemar Rymarkiewicz 				     &cp);
2080a9de9248SMarcel Holtmann 		} else {
208151a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2082a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2083a9de9248SMarcel Holtmann 		}
2084a9de9248SMarcel Holtmann 	}
2085a9de9248SMarcel Holtmann 
2086d7556e20SWaldemar Rymarkiewicz unlock:
2087a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2088a9de9248SMarcel Holtmann }
2089a9de9248SMarcel Holtmann 
20906039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2091a9de9248SMarcel Holtmann {
2092127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2093127178d2SJohan Hedberg 	struct hci_conn *conn;
2094127178d2SJohan Hedberg 
2095a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2096a9de9248SMarcel Holtmann 
2097a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2098127178d2SJohan Hedberg 
2099127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2100127178d2SJohan Hedberg 
2101127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2102b644ba33SJohan Hedberg 
2103b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2104b644ba33SJohan Hedberg 		goto check_auth;
2105b644ba33SJohan Hedberg 
2106b644ba33SJohan Hedberg 	if (ev->status == 0)
2107b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2108b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2109b644ba33SJohan Hedberg 	else
2110b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2111b644ba33SJohan Hedberg 
2112b644ba33SJohan Hedberg check_auth:
211379c6c70cSJohan Hedberg 	if (!conn)
211479c6c70cSJohan Hedberg 		goto unlock;
211579c6c70cSJohan Hedberg 
211679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
211779c6c70cSJohan Hedberg 		goto unlock;
211879c6c70cSJohan Hedberg 
211951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2120127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2121127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2122127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2123127178d2SJohan Hedberg 	}
2124127178d2SJohan Hedberg 
212579c6c70cSJohan Hedberg unlock:
2126127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2127a9de9248SMarcel Holtmann }
2128a9de9248SMarcel Holtmann 
21296039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2130a9de9248SMarcel Holtmann {
2131a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2132a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2133a9de9248SMarcel Holtmann 
21349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2135a9de9248SMarcel Holtmann 
2136a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2137a9de9248SMarcel Holtmann 
2138a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2139dc8357ccSMarcel Holtmann 	if (!conn)
2140dc8357ccSMarcel Holtmann 		goto unlock;
2141dc8357ccSMarcel Holtmann 
2142a9de9248SMarcel Holtmann 	if (!ev->status) {
2143ae293196SMarcel Holtmann 		if (ev->encrypt) {
2144ae293196SMarcel Holtmann 			/* Encryption implies authentication */
2145ae293196SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2146a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
2147da85e5e5SVinicius Costa Gomes 			conn->sec_level = conn->pending_sec_level;
2148abf76badSMarcel Holtmann 
2149914a6ffeSMarcel Holtmann 			/* P-256 authentication key implies FIPS */
2150914a6ffeSMarcel Holtmann 			if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
2151914a6ffeSMarcel Holtmann 				conn->link_mode |= HCI_LM_FIPS;
2152914a6ffeSMarcel Holtmann 
2153abf76badSMarcel Holtmann 			if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
2154abf76badSMarcel Holtmann 			    conn->type == LE_LINK)
2155abf76badSMarcel Holtmann 				set_bit(HCI_CONN_AES_CCM, &conn->flags);
2156abf76badSMarcel Holtmann 		} else {
2157a9de9248SMarcel Holtmann 			conn->link_mode &= ~HCI_LM_ENCRYPT;
2158abf76badSMarcel Holtmann 			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
2159abf76badSMarcel Holtmann 		}
2160a9de9248SMarcel Holtmann 	}
2161a9de9248SMarcel Holtmann 
216251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2163a9de9248SMarcel Holtmann 
2164a7d7723aSGustavo Padovan 	if (ev->status && conn->state == BT_CONNECTED) {
2165bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
216676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2167a7d7723aSGustavo Padovan 		goto unlock;
2168a7d7723aSGustavo Padovan 	}
2169a7d7723aSGustavo Padovan 
2170f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2171f8558555SMarcel Holtmann 		if (!ev->status)
2172f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2173f8558555SMarcel Holtmann 
2174f8558555SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
217576a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2176f8558555SMarcel Holtmann 	} else
2177a9de9248SMarcel Holtmann 		hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2178a9de9248SMarcel Holtmann 
2179a7d7723aSGustavo Padovan unlock:
2180a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2181a9de9248SMarcel Holtmann }
2182a9de9248SMarcel Holtmann 
21836039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2184807deac2SGustavo Padovan 					     struct sk_buff *skb)
2185a9de9248SMarcel Holtmann {
2186a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2187a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2188a9de9248SMarcel Holtmann 
21899f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2190a9de9248SMarcel Holtmann 
2191a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2192a9de9248SMarcel Holtmann 
2193a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2194a9de9248SMarcel Holtmann 	if (conn) {
2195a9de9248SMarcel Holtmann 		if (!ev->status)
2196a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2197a9de9248SMarcel Holtmann 
219851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2199a9de9248SMarcel Holtmann 
2200a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2201a9de9248SMarcel Holtmann 	}
2202a9de9248SMarcel Holtmann 
2203a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2204a9de9248SMarcel Holtmann }
2205a9de9248SMarcel Holtmann 
22066039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2207807deac2SGustavo Padovan 				    struct sk_buff *skb)
2208a9de9248SMarcel Holtmann {
2209a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2210a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2211a9de9248SMarcel Holtmann 
22129f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2213a9de9248SMarcel Holtmann 
2214a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2215a9de9248SMarcel Holtmann 
2216a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2217ccd556feSJohan Hedberg 	if (!conn)
2218ccd556feSJohan Hedberg 		goto unlock;
2219ccd556feSJohan Hedberg 
2220769be974SMarcel Holtmann 	if (!ev->status)
2221cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
2222a9de9248SMarcel Holtmann 
2223ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2224ccd556feSJohan Hedberg 		goto unlock;
2225ccd556feSJohan Hedberg 
2226ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2227769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2228769be974SMarcel Holtmann 		cp.handle = ev->handle;
2229769be974SMarcel Holtmann 		cp.page = 0x01;
2230ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2231769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2232392599b9SJohan Hedberg 		goto unlock;
2233392599b9SJohan Hedberg 	}
2234392599b9SJohan Hedberg 
2235671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2236127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2237127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2238127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2239127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2240127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2241b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2242b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
224308c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2244b644ba33SJohan Hedberg 				      conn->dev_class);
2245392599b9SJohan Hedberg 
2246127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2247769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2248769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
224976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2250769be974SMarcel Holtmann 	}
2251769be974SMarcel Holtmann 
2252ccd556feSJohan Hedberg unlock:
2253a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2254a9de9248SMarcel Holtmann }
2255a9de9248SMarcel Holtmann 
22566039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2257a9de9248SMarcel Holtmann {
2258a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
22599238f36aSJohan Hedberg 	u8 status = skb->data[sizeof(*ev)];
2260a9de9248SMarcel Holtmann 	__u16 opcode;
2261a9de9248SMarcel Holtmann 
2262a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2263a9de9248SMarcel Holtmann 
2264a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2265a9de9248SMarcel Holtmann 
2266a9de9248SMarcel Holtmann 	switch (opcode) {
2267a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2268a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2269a9de9248SMarcel Holtmann 		break;
2270a9de9248SMarcel Holtmann 
22714d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
22724d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
22734d93483bSAndre Guedes 		break;
22744d93483bSAndre Guedes 
2275a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2276a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2277a9de9248SMarcel Holtmann 		break;
2278a9de9248SMarcel Holtmann 
2279a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2280a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2281a9de9248SMarcel Holtmann 		break;
2282a9de9248SMarcel Holtmann 
2283a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2284a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2285a9de9248SMarcel Holtmann 		break;
2286a9de9248SMarcel Holtmann 
2287e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2288e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2289e4e8e37cSMarcel Holtmann 		break;
2290e4e8e37cSMarcel Holtmann 
2291a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2292a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2293a9de9248SMarcel Holtmann 		break;
2294a9de9248SMarcel Holtmann 
2295e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2296e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2297e4e8e37cSMarcel Holtmann 		break;
2298e4e8e37cSMarcel Holtmann 
2299e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2300e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2301e4e8e37cSMarcel Holtmann 		break;
2302e4e8e37cSMarcel Holtmann 
2303a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2304a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2305a9de9248SMarcel Holtmann 		break;
2306a9de9248SMarcel Holtmann 
2307a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2308a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2309a9de9248SMarcel Holtmann 		break;
2310a9de9248SMarcel Holtmann 
2311a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2312a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2313a9de9248SMarcel Holtmann 		break;
2314a9de9248SMarcel Holtmann 
2315a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2316a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2317a9de9248SMarcel Holtmann 		break;
2318a9de9248SMarcel Holtmann 
2319a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2320a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2321a9de9248SMarcel Holtmann 		break;
2322a9de9248SMarcel Holtmann 
2323a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2324a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2325a9de9248SMarcel Holtmann 		break;
2326a9de9248SMarcel Holtmann 
2327a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2328a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2329a9de9248SMarcel Holtmann 		break;
2330a9de9248SMarcel Holtmann 
2331a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2332a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2333a9de9248SMarcel Holtmann 		break;
2334a9de9248SMarcel Holtmann 
2335a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2336a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2337a9de9248SMarcel Holtmann 		break;
2338a9de9248SMarcel Holtmann 
2339a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2340a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2341a9de9248SMarcel Holtmann 		break;
2342a9de9248SMarcel Holtmann 
2343b4cb9fb2SMarcel Holtmann 	case HCI_OP_READ_NUM_SUPPORTED_IAC:
2344b4cb9fb2SMarcel Holtmann 		hci_cc_read_num_supported_iac(hdev, skb);
2345b4cb9fb2SMarcel Holtmann 		break;
2346b4cb9fb2SMarcel Holtmann 
2347333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2348333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2349333140b5SMarcel Holtmann 		break;
2350333140b5SMarcel Holtmann 
2351eac83dc6SMarcel Holtmann 	case HCI_OP_WRITE_SC_SUPPORT:
2352eac83dc6SMarcel Holtmann 		hci_cc_write_sc_support(hdev, skb);
2353eac83dc6SMarcel Holtmann 		break;
2354eac83dc6SMarcel Holtmann 
2355a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2356a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2357a9de9248SMarcel Holtmann 		break;
2358a9de9248SMarcel Holtmann 
2359a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2360a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2361a9de9248SMarcel Holtmann 		break;
2362a9de9248SMarcel Holtmann 
2363a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2364a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2365a9de9248SMarcel Holtmann 		break;
2366a9de9248SMarcel Holtmann 
2367971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2368971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2369971e3a4bSAndre Guedes 		break;
2370971e3a4bSAndre Guedes 
2371a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2372a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2373a9de9248SMarcel Holtmann 		break;
2374a9de9248SMarcel Holtmann 
2375a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2376a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2377a9de9248SMarcel Holtmann 		break;
2378a9de9248SMarcel Holtmann 
2379f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2380f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
2381f332ec66SJohan Hedberg 		break;
2382f332ec66SJohan Hedberg 
23834a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
23844a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
23854a3ee763SJohan Hedberg 		break;
23864a3ee763SJohan Hedberg 
2387f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
2388f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
2389f332ec66SJohan Hedberg 		break;
2390f332ec66SJohan Hedberg 
23914a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
23924a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
23934a3ee763SJohan Hedberg 		break;
23944a3ee763SJohan Hedberg 
2395350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2396350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2397350ee4cfSAndrei Emeltchenko 		break;
2398350ee4cfSAndrei Emeltchenko 
23991e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
24001e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
24011e89cffbSAndrei Emeltchenko 		break;
24021e89cffbSAndrei Emeltchenko 
2403928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2404928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2405928abaa7SAndrei Emeltchenko 		break;
2406928abaa7SAndrei Emeltchenko 
2407903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2408903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2409903e4541SAndrei Emeltchenko 		break;
2410903e4541SAndrei Emeltchenko 
2411d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2412d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2413d5859e22SJohan Hedberg 		break;
2414d5859e22SJohan Hedberg 
2415980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2416980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2417980e1a53SJohan Hedberg 		break;
2418980e1a53SJohan Hedberg 
2419980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2420980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2421980e1a53SJohan Hedberg 		break;
2422980e1a53SJohan Hedberg 
2423c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
24244d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_data(hdev, skb);
24254d2d2796SMarcel Holtmann 		break;
24264d2d2796SMarcel Holtmann 
24274d2d2796SMarcel Holtmann 	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
24284d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_ext_data(hdev, skb);
2429c35938b2SSzymon Janc 		break;
2430c35938b2SSzymon Janc 
24316ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
24326ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
24336ed58ec5SVille Tervo 		break;
24346ed58ec5SVille Tervo 
243560e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
243660e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
243760e77321SJohan Hedberg 		break;
243860e77321SJohan Hedberg 
24398fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
24408fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
24418fa19098SJohan Hedberg 		break;
24428fa19098SJohan Hedberg 
2443a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2444a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2445a5c29683SJohan Hedberg 		break;
2446a5c29683SJohan Hedberg 
2447a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2448a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2449a5c29683SJohan Hedberg 		break;
2450a5c29683SJohan Hedberg 
24511143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
24521143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
24531143d458SBrian Gix 		break;
24541143d458SBrian Gix 
24551143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
24561143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
245716cde993SSzymon Janc 		break;
245807f7fa5dSAndre Guedes 
24597a4cd51dSMarcel Holtmann 	case HCI_OP_LE_SET_RANDOM_ADDR:
24607a4cd51dSMarcel Holtmann 		hci_cc_le_set_random_addr(hdev, skb);
24617a4cd51dSMarcel Holtmann 		break;
24627a4cd51dSMarcel Holtmann 
2463c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2464c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2465c1d5dc4aSJohan Hedberg 		break;
2466c1d5dc4aSJohan Hedberg 
2467eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2468eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2469eb9d91f5SAndre Guedes 		break;
2470eb9d91f5SAndre Guedes 
2471cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2472cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2473cf1d081fSJohan Hedberg 		break;
2474cf1d081fSJohan Hedberg 
24750f36b589SMarcel Holtmann 	case HCI_OP_LE_CLEAR_WHITE_LIST:
24760f36b589SMarcel Holtmann 		hci_cc_le_clear_white_list(hdev, skb);
24770f36b589SMarcel Holtmann 		break;
24780f36b589SMarcel Holtmann 
24790f36b589SMarcel Holtmann 	case HCI_OP_LE_ADD_TO_WHITE_LIST:
24800f36b589SMarcel Holtmann 		hci_cc_le_add_to_white_list(hdev, skb);
24810f36b589SMarcel Holtmann 		break;
24820f36b589SMarcel Holtmann 
24830f36b589SMarcel Holtmann 	case HCI_OP_LE_DEL_FROM_WHITE_LIST:
24840f36b589SMarcel Holtmann 		hci_cc_le_del_from_white_list(hdev, skb);
24850f36b589SMarcel Holtmann 		break;
24860f36b589SMarcel Holtmann 
24879b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
24889b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
24899b008c04SJohan Hedberg 		break;
24909b008c04SJohan Hedberg 
2491f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2492f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2493f9b49306SAndre Guedes 		break;
2494f9b49306SAndre Guedes 
249556ed2cb8SJohan Hedberg 	case HCI_OP_LE_SET_ADV_PARAM:
249656ed2cb8SJohan Hedberg 		hci_cc_set_adv_param(hdev, skb);
249756ed2cb8SJohan Hedberg 		break;
249856ed2cb8SJohan Hedberg 
249993c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
250093c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
250193c284eeSAndrei Emeltchenko 		break;
250293c284eeSAndrei Emeltchenko 
2503a9de9248SMarcel Holtmann 	default:
25049f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2505a9de9248SMarcel Holtmann 		break;
2506a9de9248SMarcel Holtmann 	}
2507a9de9248SMarcel Holtmann 
2508ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
25096bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
25106bd32326SVille Tervo 
2511ad82cdd1SJohan Hedberg 	hci_req_cmd_complete(hdev, opcode, status);
25129238f36aSJohan Hedberg 
2513dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2514a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2515a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2516c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2517a9de9248SMarcel Holtmann 	}
2518a9de9248SMarcel Holtmann }
2519a9de9248SMarcel Holtmann 
25206039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2521a9de9248SMarcel Holtmann {
2522a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2523a9de9248SMarcel Holtmann 	__u16 opcode;
2524a9de9248SMarcel Holtmann 
2525a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2526a9de9248SMarcel Holtmann 
2527a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2528a9de9248SMarcel Holtmann 
2529a9de9248SMarcel Holtmann 	switch (opcode) {
2530a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2531a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2532a9de9248SMarcel Holtmann 		break;
2533a9de9248SMarcel Holtmann 
2534a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2535a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2536a9de9248SMarcel Holtmann 		break;
2537a9de9248SMarcel Holtmann 
2538a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2539a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2540a9de9248SMarcel Holtmann 		break;
2541a9de9248SMarcel Holtmann 
2542f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2543f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2544f8558555SMarcel Holtmann 		break;
2545f8558555SMarcel Holtmann 
2546f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2547f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2548f8558555SMarcel Holtmann 		break;
2549f8558555SMarcel Holtmann 
2550a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2551a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2552a9de9248SMarcel Holtmann 		break;
2553a9de9248SMarcel Holtmann 
2554769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2555769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2556769be974SMarcel Holtmann 		break;
2557769be974SMarcel Holtmann 
2558769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2559769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2560769be974SMarcel Holtmann 		break;
2561769be974SMarcel Holtmann 
2562a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2563a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2564a9de9248SMarcel Holtmann 		break;
2565a9de9248SMarcel Holtmann 
2566a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2567a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2568a9de9248SMarcel Holtmann 		break;
2569a9de9248SMarcel Holtmann 
2570a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2571a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2572a9de9248SMarcel Holtmann 		break;
2573a9de9248SMarcel Holtmann 
25748962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
257588c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
25768962ee74SJohan Hedberg 		break;
25778962ee74SJohan Hedberg 
2578a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2579a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2580a02226d6SAndrei Emeltchenko 		break;
2581a02226d6SAndrei Emeltchenko 
25820b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
25830b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
25840b26ab9dSAndrei Emeltchenko 		break;
25850b26ab9dSAndrei Emeltchenko 
2586cb1d68f7SJohan Hedberg 	case HCI_OP_LE_CREATE_CONN:
2587cb1d68f7SJohan Hedberg 		hci_cs_le_create_conn(hdev, ev->status);
2588cb1d68f7SJohan Hedberg 		break;
2589cb1d68f7SJohan Hedberg 
2590a9de9248SMarcel Holtmann 	default:
25919f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2592a9de9248SMarcel Holtmann 		break;
2593a9de9248SMarcel Holtmann 	}
2594a9de9248SMarcel Holtmann 
2595ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
25966bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
25976bd32326SVille Tervo 
259802350a72SJohan Hedberg 	if (ev->status ||
259902350a72SJohan Hedberg 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
260033720450SAndre Guedes 		hci_req_cmd_complete(hdev, opcode, ev->status);
26019238f36aSJohan Hedberg 
260210572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2603a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2604a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2605c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2606a9de9248SMarcel Holtmann 	}
2607a9de9248SMarcel Holtmann }
2608a9de9248SMarcel Holtmann 
26096039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2610a9de9248SMarcel Holtmann {
2611a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2612a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2613a9de9248SMarcel Holtmann 
26149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2615a9de9248SMarcel Holtmann 
2616a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2617a9de9248SMarcel Holtmann 
2618a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2619a9de9248SMarcel Holtmann 	if (conn) {
2620a9de9248SMarcel Holtmann 		if (!ev->status) {
2621a9de9248SMarcel Holtmann 			if (ev->role)
2622a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2623a9de9248SMarcel Holtmann 			else
2624a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2625a9de9248SMarcel Holtmann 		}
2626a9de9248SMarcel Holtmann 
262751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2628a9de9248SMarcel Holtmann 
2629a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2630a9de9248SMarcel Holtmann 	}
2631a9de9248SMarcel Holtmann 
2632a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2633a9de9248SMarcel Holtmann }
2634a9de9248SMarcel Holtmann 
26356039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
26361da177e4SLinus Torvalds {
2637a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
26381da177e4SLinus Torvalds 	int i;
26391da177e4SLinus Torvalds 
264032ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
264132ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
264232ac5b9bSAndrei Emeltchenko 		return;
264332ac5b9bSAndrei Emeltchenko 	}
264432ac5b9bSAndrei Emeltchenko 
2645c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2646c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
26471da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
26481da177e4SLinus Torvalds 		return;
26491da177e4SLinus Torvalds 	}
26501da177e4SLinus Torvalds 
2651c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2652c5993de8SAndrei Emeltchenko 
2653613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2654613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
26551da177e4SLinus Torvalds 		struct hci_conn *conn;
26561da177e4SLinus Torvalds 		__u16  handle, count;
26571da177e4SLinus Torvalds 
2658613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2659613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
26601da177e4SLinus Torvalds 
26611da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2662f4280918SAndrei Emeltchenko 		if (!conn)
2663f4280918SAndrei Emeltchenko 			continue;
2664f4280918SAndrei Emeltchenko 
26651da177e4SLinus Torvalds 		conn->sent -= count;
26661da177e4SLinus Torvalds 
2667f4280918SAndrei Emeltchenko 		switch (conn->type) {
2668f4280918SAndrei Emeltchenko 		case ACL_LINK:
266970f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
267070f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
26711da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2672f4280918SAndrei Emeltchenko 			break;
2673f4280918SAndrei Emeltchenko 
2674f4280918SAndrei Emeltchenko 		case LE_LINK:
26756ed58ec5SVille Tervo 			if (hdev->le_pkts) {
26766ed58ec5SVille Tervo 				hdev->le_cnt += count;
26776ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
26786ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
26796ed58ec5SVille Tervo 			} else {
26806ed58ec5SVille Tervo 				hdev->acl_cnt += count;
26816ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
26826ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
26836ed58ec5SVille Tervo 			}
2684f4280918SAndrei Emeltchenko 			break;
2685f4280918SAndrei Emeltchenko 
2686f4280918SAndrei Emeltchenko 		case SCO_LINK:
268770f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
268870f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
26895b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2690f4280918SAndrei Emeltchenko 			break;
2691f4280918SAndrei Emeltchenko 
2692f4280918SAndrei Emeltchenko 		default:
2693f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2694f4280918SAndrei Emeltchenko 			break;
26951da177e4SLinus Torvalds 		}
26961da177e4SLinus Torvalds 	}
2697a9de9248SMarcel Holtmann 
26983eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
26991da177e4SLinus Torvalds }
27001da177e4SLinus Torvalds 
270176ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
270276ef7cf7SAndrei Emeltchenko 						 __u16 handle)
270376ef7cf7SAndrei Emeltchenko {
270476ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
270576ef7cf7SAndrei Emeltchenko 
270676ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
270776ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
270876ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
270976ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
271076ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
271176ef7cf7SAndrei Emeltchenko 		if (chan)
271276ef7cf7SAndrei Emeltchenko 			return chan->conn;
271376ef7cf7SAndrei Emeltchenko 		break;
271476ef7cf7SAndrei Emeltchenko 	default:
271576ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
271676ef7cf7SAndrei Emeltchenko 		break;
271776ef7cf7SAndrei Emeltchenko 	}
271876ef7cf7SAndrei Emeltchenko 
271976ef7cf7SAndrei Emeltchenko 	return NULL;
272076ef7cf7SAndrei Emeltchenko }
272176ef7cf7SAndrei Emeltchenko 
27226039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
272325e89e99SAndrei Emeltchenko {
272425e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
272525e89e99SAndrei Emeltchenko 	int i;
272625e89e99SAndrei Emeltchenko 
272725e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
272825e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
272925e89e99SAndrei Emeltchenko 		return;
273025e89e99SAndrei Emeltchenko 	}
273125e89e99SAndrei Emeltchenko 
273225e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
273325e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
273425e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
273525e89e99SAndrei Emeltchenko 		return;
273625e89e99SAndrei Emeltchenko 	}
273725e89e99SAndrei Emeltchenko 
273825e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
273925e89e99SAndrei Emeltchenko 	       ev->num_hndl);
274025e89e99SAndrei Emeltchenko 
274125e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
274225e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
274376ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
274425e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
274525e89e99SAndrei Emeltchenko 
274625e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
274725e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
274825e89e99SAndrei Emeltchenko 
274976ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
275025e89e99SAndrei Emeltchenko 		if (!conn)
275125e89e99SAndrei Emeltchenko 			continue;
275225e89e99SAndrei Emeltchenko 
275325e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
275425e89e99SAndrei Emeltchenko 
275525e89e99SAndrei Emeltchenko 		switch (conn->type) {
275625e89e99SAndrei Emeltchenko 		case ACL_LINK:
2757bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
275825e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
275925e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
276025e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
276125e89e99SAndrei Emeltchenko 			break;
276225e89e99SAndrei Emeltchenko 
276325e89e99SAndrei Emeltchenko 		default:
276425e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
276525e89e99SAndrei Emeltchenko 			break;
276625e89e99SAndrei Emeltchenko 		}
276725e89e99SAndrei Emeltchenko 	}
276825e89e99SAndrei Emeltchenko 
276925e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
277025e89e99SAndrei Emeltchenko }
277125e89e99SAndrei Emeltchenko 
27726039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
27731da177e4SLinus Torvalds {
2774a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
277504837f64SMarcel Holtmann 	struct hci_conn *conn;
27761da177e4SLinus Torvalds 
27779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
27781da177e4SLinus Torvalds 
27791da177e4SLinus Torvalds 	hci_dev_lock(hdev);
27801da177e4SLinus Torvalds 
278104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
278204837f64SMarcel Holtmann 	if (conn) {
278304837f64SMarcel Holtmann 		conn->mode = ev->mode;
278404837f64SMarcel Holtmann 
27858fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
27868fc9ced3SGustavo Padovan 					&conn->flags)) {
278704837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
278858a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
278904837f64SMarcel Holtmann 			else
279058a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
279104837f64SMarcel Holtmann 		}
2792e73439d8SMarcel Holtmann 
279351a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2794e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
279504837f64SMarcel Holtmann 	}
279604837f64SMarcel Holtmann 
279704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
279804837f64SMarcel Holtmann }
279904837f64SMarcel Holtmann 
28006039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
28011da177e4SLinus Torvalds {
2802052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2803052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2804052b30b0SMarcel Holtmann 
2805a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2806052b30b0SMarcel Holtmann 
2807052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2808052b30b0SMarcel Holtmann 
2809052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2810b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2811b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2812b6f98044SWaldemar Rymarkiewicz 
2813b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2814052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2815052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
281676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2817052b30b0SMarcel Holtmann 	}
2818052b30b0SMarcel Holtmann 
2819a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
282003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
282103b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2822a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2823a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2824a770bb5aSWaldemar Rymarkiewicz 
2825a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2826a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2827a770bb5aSWaldemar Rymarkiewicz 		else
2828a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2829a770bb5aSWaldemar Rymarkiewicz 
2830744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2831a770bb5aSWaldemar Rymarkiewicz 	}
2832980e1a53SJohan Hedberg 
2833b6f98044SWaldemar Rymarkiewicz unlock:
2834052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
28351da177e4SLinus Torvalds }
28361da177e4SLinus Torvalds 
28376039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
28381da177e4SLinus Torvalds {
283955ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
284055ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
284155ed8ca1SJohan Hedberg 	struct hci_conn *conn;
284255ed8ca1SJohan Hedberg 	struct link_key *key;
284355ed8ca1SJohan Hedberg 
2844a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
284555ed8ca1SJohan Hedberg 
2846034cbea0SAndrei Emeltchenko 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
284755ed8ca1SJohan Hedberg 		return;
284855ed8ca1SJohan Hedberg 
284955ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
285055ed8ca1SJohan Hedberg 
285155ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
285255ed8ca1SJohan Hedberg 	if (!key) {
28536ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
28546ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
285555ed8ca1SJohan Hedberg 		goto not_found;
285655ed8ca1SJohan Hedberg 	}
285755ed8ca1SJohan Hedberg 
28586ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
28596ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
286055ed8ca1SJohan Hedberg 
2861a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2862b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
286355ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
286455ed8ca1SJohan Hedberg 		goto not_found;
286555ed8ca1SJohan Hedberg 	}
286655ed8ca1SJohan Hedberg 
286755ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
286860b83f57SWaldemar Rymarkiewicz 	if (conn) {
286966138ce8SMarcel Holtmann 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
287066138ce8SMarcel Holtmann 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
2871807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
287255ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
287355ed8ca1SJohan Hedberg 			goto not_found;
287455ed8ca1SJohan Hedberg 		}
287555ed8ca1SJohan Hedberg 
287660b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
287760b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
28788fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
28798fc9ced3SGustavo Padovan 			       hdev->name);
288060b83f57SWaldemar Rymarkiewicz 			goto not_found;
288160b83f57SWaldemar Rymarkiewicz 		}
288260b83f57SWaldemar Rymarkiewicz 
288360b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
288460b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
288560b83f57SWaldemar Rymarkiewicz 	}
288660b83f57SWaldemar Rymarkiewicz 
288755ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
28889b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
288955ed8ca1SJohan Hedberg 
289055ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
289155ed8ca1SJohan Hedberg 
289255ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
289355ed8ca1SJohan Hedberg 
289455ed8ca1SJohan Hedberg 	return;
289555ed8ca1SJohan Hedberg 
289655ed8ca1SJohan Hedberg not_found:
289755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
289855ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
28991da177e4SLinus Torvalds }
29001da177e4SLinus Torvalds 
29016039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
29021da177e4SLinus Torvalds {
2903052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2904052b30b0SMarcel Holtmann 	struct hci_conn *conn;
290555ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2906052b30b0SMarcel Holtmann 
2907a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2908052b30b0SMarcel Holtmann 
2909052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2910052b30b0SMarcel Holtmann 
2911052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2912052b30b0SMarcel Holtmann 	if (conn) {
2913052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2914052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2915980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
291613d39315SWaldemar Rymarkiewicz 
291713d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
291813d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
291913d39315SWaldemar Rymarkiewicz 
292076a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2921052b30b0SMarcel Holtmann 	}
2922052b30b0SMarcel Holtmann 
2923034cbea0SAndrei Emeltchenko 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
2924d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
292555ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
292655ed8ca1SJohan Hedberg 
2927052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
29281da177e4SLinus Torvalds }
29291da177e4SLinus Torvalds 
29306039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
293104837f64SMarcel Holtmann {
2932a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
293304837f64SMarcel Holtmann 	struct hci_conn *conn;
293404837f64SMarcel Holtmann 
29359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
293604837f64SMarcel Holtmann 
293704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
293804837f64SMarcel Holtmann 
293904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
29401da177e4SLinus Torvalds 	if (conn && !ev->status) {
29411da177e4SLinus Torvalds 		struct inquiry_entry *ie;
29421da177e4SLinus Torvalds 
2943cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2944cc11b9c1SAndrei Emeltchenko 		if (ie) {
29451da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
29461da177e4SLinus Torvalds 			ie->timestamp = jiffies;
29471da177e4SLinus Torvalds 		}
29481da177e4SLinus Torvalds 	}
29491da177e4SLinus Torvalds 
29501da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
29511da177e4SLinus Torvalds }
29521da177e4SLinus Torvalds 
29536039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2954a8746417SMarcel Holtmann {
2955a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2956a8746417SMarcel Holtmann 	struct hci_conn *conn;
2957a8746417SMarcel Holtmann 
29589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2959a8746417SMarcel Holtmann 
2960a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2961a8746417SMarcel Holtmann 
2962a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2963a8746417SMarcel Holtmann 	if (conn && !ev->status)
2964a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2965a8746417SMarcel Holtmann 
2966a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2967a8746417SMarcel Holtmann }
2968a8746417SMarcel Holtmann 
29696039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
297085a1e930SMarcel Holtmann {
2971a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
297285a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
297385a1e930SMarcel Holtmann 
297485a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
297585a1e930SMarcel Holtmann 
297685a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
297785a1e930SMarcel Holtmann 
2978cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2979cc11b9c1SAndrei Emeltchenko 	if (ie) {
298085a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
298185a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
298285a1e930SMarcel Holtmann 	}
298385a1e930SMarcel Holtmann 
298485a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
298585a1e930SMarcel Holtmann }
298685a1e930SMarcel Holtmann 
29876039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2988807deac2SGustavo Padovan 					     struct sk_buff *skb)
2989a9de9248SMarcel Holtmann {
2990a9de9248SMarcel Holtmann 	struct inquiry_data data;
2991a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2992388fc8faSJohan Hedberg 	bool name_known, ssp;
2993a9de9248SMarcel Holtmann 
2994a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2995a9de9248SMarcel Holtmann 
2996a9de9248SMarcel Holtmann 	if (!num_rsp)
2997a9de9248SMarcel Holtmann 		return;
2998a9de9248SMarcel Holtmann 
29991519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30001519cc17SAndre Guedes 		return;
30011519cc17SAndre Guedes 
3002a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3003a9de9248SMarcel Holtmann 
3004a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3005138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3006138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3007a9de9248SMarcel Holtmann 
3008e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3009a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3010a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3011a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3012a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3013a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3014a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3015a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
301641a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
30173175405bSJohan Hedberg 
30183175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3019388fc8faSJohan Hedberg 							      false, &ssp);
302048264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3021e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3022388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3023a9de9248SMarcel Holtmann 		}
3024a9de9248SMarcel Holtmann 	} else {
3025a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3026a9de9248SMarcel Holtmann 
3027e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3028a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3029a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3030a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3031a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3032a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3033a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3034a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
303541a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
30363175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3037388fc8faSJohan Hedberg 							      false, &ssp);
303848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3039e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3040388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3041a9de9248SMarcel Holtmann 		}
3042a9de9248SMarcel Holtmann 	}
3043a9de9248SMarcel Holtmann 
3044a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3045a9de9248SMarcel Holtmann }
3046a9de9248SMarcel Holtmann 
30476039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3048807deac2SGustavo Padovan 					struct sk_buff *skb)
3049a9de9248SMarcel Holtmann {
305041a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
305141a96212SMarcel Holtmann 	struct hci_conn *conn;
305241a96212SMarcel Holtmann 
3053a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
305441a96212SMarcel Holtmann 
305541a96212SMarcel Holtmann 	hci_dev_lock(hdev);
305641a96212SMarcel Holtmann 
305741a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3058ccd556feSJohan Hedberg 	if (!conn)
3059ccd556feSJohan Hedberg 		goto unlock;
3060ccd556feSJohan Hedberg 
3061cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
3062cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
3063cad718edSJohan Hedberg 
3064769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
306541a96212SMarcel Holtmann 		struct inquiry_entry *ie;
306641a96212SMarcel Holtmann 
3067cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3068cc11b9c1SAndrei Emeltchenko 		if (ie)
306902b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
307041a96212SMarcel Holtmann 
3071bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
307258a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
3073bbb0eadaSJaganath Kanakkassery 		} else {
3074bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
3075bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
3076bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
3077bbb0eadaSJaganath Kanakkassery 			 * this.
3078bbb0eadaSJaganath Kanakkassery 			 *
3079bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
3080bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
3081bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
3082bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
3083bbb0eadaSJaganath Kanakkassery 		}
3084eb9a8f3fSMarcel Holtmann 
3085eb9a8f3fSMarcel Holtmann 		if (ev->features[0] & LMP_HOST_SC)
3086eb9a8f3fSMarcel Holtmann 			set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
308741a96212SMarcel Holtmann 	}
308841a96212SMarcel Holtmann 
3089ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3090ccd556feSJohan Hedberg 		goto unlock;
3091ccd556feSJohan Hedberg 
3092671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3093127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3094127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3095127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3096127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3097127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3098b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3099b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
310008c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
3101b644ba33SJohan Hedberg 				      conn->dev_class);
3102392599b9SJohan Hedberg 
3103127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3104769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3105769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
310676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
3107769be974SMarcel Holtmann 	}
3108769be974SMarcel Holtmann 
3109ccd556feSJohan Hedberg unlock:
311041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3111a9de9248SMarcel Holtmann }
3112a9de9248SMarcel Holtmann 
31136039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3114807deac2SGustavo Padovan 				       struct sk_buff *skb)
3115a9de9248SMarcel Holtmann {
3116b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3117b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3118b6a0dc82SMarcel Holtmann 
31199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3120b6a0dc82SMarcel Holtmann 
3121b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3122b6a0dc82SMarcel Holtmann 
3123b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
31249dc0a3afSMarcel Holtmann 	if (!conn) {
31259dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
31269dc0a3afSMarcel Holtmann 			goto unlock;
31279dc0a3afSMarcel Holtmann 
31289dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3129b6a0dc82SMarcel Holtmann 		if (!conn)
3130b6a0dc82SMarcel Holtmann 			goto unlock;
3131b6a0dc82SMarcel Holtmann 
31329dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
31339dc0a3afSMarcel Holtmann 	}
31349dc0a3afSMarcel Holtmann 
3135732547f9SMarcel Holtmann 	switch (ev->status) {
3136732547f9SMarcel Holtmann 	case 0x00:
3137732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3138732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3139732547f9SMarcel Holtmann 
3140732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3141732547f9SMarcel Holtmann 		break;
3142732547f9SMarcel Holtmann 
31431a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
3144705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3145732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
31461038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3147732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
31482dea632fSFrédéric Dalleau 		if (conn->out) {
3149efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3150efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
31512dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
3152efc7688bSMarcel Holtmann 				goto unlock;
3153efc7688bSMarcel Holtmann 		}
3154732547f9SMarcel Holtmann 		/* fall through */
3155efc7688bSMarcel Holtmann 
3156732547f9SMarcel Holtmann 	default:
3157b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3158732547f9SMarcel Holtmann 		break;
3159732547f9SMarcel Holtmann 	}
3160b6a0dc82SMarcel Holtmann 
3161b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3162b6a0dc82SMarcel Holtmann 	if (ev->status)
3163b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3164b6a0dc82SMarcel Holtmann 
3165b6a0dc82SMarcel Holtmann unlock:
3166b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3167a9de9248SMarcel Holtmann }
3168a9de9248SMarcel Holtmann 
3169efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len)
3170efdcf8e3SMarcel Holtmann {
3171efdcf8e3SMarcel Holtmann 	size_t parsed = 0;
3172efdcf8e3SMarcel Holtmann 
3173efdcf8e3SMarcel Holtmann 	while (parsed < eir_len) {
3174efdcf8e3SMarcel Holtmann 		u8 field_len = eir[0];
3175efdcf8e3SMarcel Holtmann 
3176efdcf8e3SMarcel Holtmann 		if (field_len == 0)
3177efdcf8e3SMarcel Holtmann 			return parsed;
3178efdcf8e3SMarcel Holtmann 
3179efdcf8e3SMarcel Holtmann 		parsed += field_len + 1;
3180efdcf8e3SMarcel Holtmann 		eir += field_len + 1;
3181efdcf8e3SMarcel Holtmann 	}
3182efdcf8e3SMarcel Holtmann 
3183efdcf8e3SMarcel Holtmann 	return eir_len;
3184efdcf8e3SMarcel Holtmann }
3185efdcf8e3SMarcel Holtmann 
31866039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3187807deac2SGustavo Padovan 					    struct sk_buff *skb)
3188a9de9248SMarcel Holtmann {
3189a9de9248SMarcel Holtmann 	struct inquiry_data data;
3190a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3191a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
31929d939d94SVishal Agarwal 	size_t eir_len;
3193a9de9248SMarcel Holtmann 
3194a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3195a9de9248SMarcel Holtmann 
3196a9de9248SMarcel Holtmann 	if (!num_rsp)
3197a9de9248SMarcel Holtmann 		return;
3198a9de9248SMarcel Holtmann 
31991519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
32001519cc17SAndre Guedes 		return;
32011519cc17SAndre Guedes 
3202a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3203a9de9248SMarcel Holtmann 
3204e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3205388fc8faSJohan Hedberg 		bool name_known, ssp;
3206561aafbcSJohan Hedberg 
3207a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3208a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3209a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3210a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3211a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3212a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3213a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
321441a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3215561aafbcSJohan Hedberg 
3216a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
32174ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
32184ddb1930SJohan Hedberg 						       sizeof(info->data),
32194ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3220561aafbcSJohan Hedberg 		else
3221561aafbcSJohan Hedberg 			name_known = true;
3222561aafbcSJohan Hedberg 
3223388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3224388fc8faSJohan Hedberg 						      &ssp);
32259d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
322648264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
322704124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
32289d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3229a9de9248SMarcel Holtmann 	}
3230a9de9248SMarcel Holtmann 
3231a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3232a9de9248SMarcel Holtmann }
3233a9de9248SMarcel Holtmann 
32341c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
32351c2e0041SJohan Hedberg 					 struct sk_buff *skb)
32361c2e0041SJohan Hedberg {
32371c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
32381c2e0041SJohan Hedberg 	struct hci_conn *conn;
32391c2e0041SJohan Hedberg 
32409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
32411c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
32421c2e0041SJohan Hedberg 
32431c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
32441c2e0041SJohan Hedberg 
32451c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
32461c2e0041SJohan Hedberg 	if (!conn)
32471c2e0041SJohan Hedberg 		goto unlock;
32481c2e0041SJohan Hedberg 
32491c2e0041SJohan Hedberg 	if (!ev->status)
32501c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
32511c2e0041SJohan Hedberg 
32521c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
32531c2e0041SJohan Hedberg 
32541c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3255bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
325676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
32571c2e0041SJohan Hedberg 		goto unlock;
32581c2e0041SJohan Hedberg 	}
32591c2e0041SJohan Hedberg 
32601c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
32611c2e0041SJohan Hedberg 		if (!ev->status)
32621c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
32631c2e0041SJohan Hedberg 
32641c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
326576a68ba0SDavid Herrmann 		hci_conn_drop(conn);
32661c2e0041SJohan Hedberg 	} else {
32671c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
32681c2e0041SJohan Hedberg 
32691c2e0041SJohan Hedberg 		hci_conn_hold(conn);
32701c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
327176a68ba0SDavid Herrmann 		hci_conn_drop(conn);
32721c2e0041SJohan Hedberg 	}
32731c2e0041SJohan Hedberg 
32741c2e0041SJohan Hedberg unlock:
32751c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
32761c2e0041SJohan Hedberg }
32771c2e0041SJohan Hedberg 
32786039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
327917fa4b9dSJohan Hedberg {
328017fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
3281acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_DEDICATED_BONDING ||
3282acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_DEDICATED_BONDING_MITM) {
328317fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
328417fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
3285acabae96SMikel Astiz 		if (conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT ||
3286acabae96SMikel Astiz 		    conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)
3287acabae96SMikel Astiz 			return HCI_AT_DEDICATED_BONDING;
328817fa4b9dSJohan Hedberg 		else
3289acabae96SMikel Astiz 			return HCI_AT_DEDICATED_BONDING_MITM;
329017fa4b9dSJohan Hedberg 	}
329117fa4b9dSJohan Hedberg 
329217fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
3293acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
3294acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
329558797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
329617fa4b9dSJohan Hedberg 
329717fa4b9dSJohan Hedberg 	return conn->auth_type;
329817fa4b9dSJohan Hedberg }
329917fa4b9dSJohan Hedberg 
33006039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
33010493684eSMarcel Holtmann {
33020493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
33030493684eSMarcel Holtmann 	struct hci_conn *conn;
33040493684eSMarcel Holtmann 
33050493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
33060493684eSMarcel Holtmann 
33070493684eSMarcel Holtmann 	hci_dev_lock(hdev);
33080493684eSMarcel Holtmann 
33090493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
331003b555e1SJohan Hedberg 	if (!conn)
331103b555e1SJohan Hedberg 		goto unlock;
331203b555e1SJohan Hedberg 
33130493684eSMarcel Holtmann 	hci_conn_hold(conn);
33140493684eSMarcel Holtmann 
3315a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
331603b555e1SJohan Hedberg 		goto unlock;
331703b555e1SJohan Hedberg 
3318a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
331903b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
332017fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
332117fa4b9dSJohan Hedberg 
332217fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
33237a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
33247a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
33257a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
3326a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
33277cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
33287cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
332917fa4b9dSJohan Hedberg 
33308fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
33318fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3332ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3333ce85ee13SSzymon Janc 		else
3334ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3335ce85ee13SSzymon Janc 
333617fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
333717fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
333803b555e1SJohan Hedberg 	} else {
333903b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
334003b555e1SJohan Hedberg 
334103b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
33429f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
334303b555e1SJohan Hedberg 
334403b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
334503b555e1SJohan Hedberg 			     sizeof(cp), &cp);
334603b555e1SJohan Hedberg 	}
334703b555e1SJohan Hedberg 
334803b555e1SJohan Hedberg unlock:
334903b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
335003b555e1SJohan Hedberg }
335103b555e1SJohan Hedberg 
33526039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
335303b555e1SJohan Hedberg {
335403b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
335503b555e1SJohan Hedberg 	struct hci_conn *conn;
335603b555e1SJohan Hedberg 
335703b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
335803b555e1SJohan Hedberg 
335903b555e1SJohan Hedberg 	hci_dev_lock(hdev);
336003b555e1SJohan Hedberg 
336103b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
336203b555e1SJohan Hedberg 	if (!conn)
336303b555e1SJohan Hedberg 		goto unlock;
336403b555e1SJohan Hedberg 
336503b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
336603b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
336758a681efSJohan Hedberg 	if (ev->oob_data)
336858a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
336903b555e1SJohan Hedberg 
337003b555e1SJohan Hedberg unlock:
33710493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
33720493684eSMarcel Holtmann }
33730493684eSMarcel Holtmann 
33746039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3375a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3376a5c29683SJohan Hedberg {
3377a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
337855bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
33797a828908SJohan Hedberg 	struct hci_conn *conn;
3380a5c29683SJohan Hedberg 
3381a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3382a5c29683SJohan Hedberg 
3383a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3384a5c29683SJohan Hedberg 
3385a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
33867a828908SJohan Hedberg 		goto unlock;
33877a828908SJohan Hedberg 
33887a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
33897a828908SJohan Hedberg 	if (!conn)
33907a828908SJohan Hedberg 		goto unlock;
33917a828908SJohan Hedberg 
33927a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
33937a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
33947a828908SJohan Hedberg 
33957a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
33967a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
33977a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
33987a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
33997a828908SJohan Hedberg 	 * bit set. */
3400a767631aSMikel Astiz 	if (!conn->connect_cfm_cb && loc_mitm &&
3401a767631aSMikel Astiz 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
34027a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
34037a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
34047a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
34057a828908SJohan Hedberg 		goto unlock;
34067a828908SJohan Hedberg 	}
34077a828908SJohan Hedberg 
34087a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
3409a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
3410a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
341155bc1a37SJohan Hedberg 
341255bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
341355bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
341455bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
341551a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
341655bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
341755bc1a37SJohan Hedberg 			confirm_hint = 1;
341855bc1a37SJohan Hedberg 			goto confirm;
341955bc1a37SJohan Hedberg 		}
342055bc1a37SJohan Hedberg 
34219f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
34229f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
34239f61656aSJohan Hedberg 
34249f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
34259f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
34267bc18d9dSJohan Hedberg 			queue_delayed_work(conn->hdev->workqueue,
34277bc18d9dSJohan Hedberg 					   &conn->auto_accept_work, delay);
34289f61656aSJohan Hedberg 			goto unlock;
34299f61656aSJohan Hedberg 		}
34309f61656aSJohan Hedberg 
34317a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
34327a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
34337a828908SJohan Hedberg 		goto unlock;
34347a828908SJohan Hedberg 	}
34357a828908SJohan Hedberg 
343655bc1a37SJohan Hedberg confirm:
3437272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
343855bc1a37SJohan Hedberg 				  confirm_hint);
3439a5c29683SJohan Hedberg 
34407a828908SJohan Hedberg unlock:
3441a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3442a5c29683SJohan Hedberg }
3443a5c29683SJohan Hedberg 
34446039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
34451143d458SBrian Gix 					 struct sk_buff *skb)
34461143d458SBrian Gix {
34471143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
34481143d458SBrian Gix 
34491143d458SBrian Gix 	BT_DBG("%s", hdev->name);
34501143d458SBrian Gix 
3451a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3452272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
34531143d458SBrian Gix }
34541143d458SBrian Gix 
345592a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
345692a25256SJohan Hedberg 					struct sk_buff *skb)
345792a25256SJohan Hedberg {
345892a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
345992a25256SJohan Hedberg 	struct hci_conn *conn;
346092a25256SJohan Hedberg 
346192a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
346292a25256SJohan Hedberg 
346392a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
346492a25256SJohan Hedberg 	if (!conn)
346592a25256SJohan Hedberg 		return;
346692a25256SJohan Hedberg 
346792a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
346892a25256SJohan Hedberg 	conn->passkey_entered = 0;
346992a25256SJohan Hedberg 
347092a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
347192a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
347292a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
347392a25256SJohan Hedberg 					 conn->passkey_entered);
347492a25256SJohan Hedberg }
347592a25256SJohan Hedberg 
347692a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
347792a25256SJohan Hedberg {
347892a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
347992a25256SJohan Hedberg 	struct hci_conn *conn;
348092a25256SJohan Hedberg 
348192a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
348292a25256SJohan Hedberg 
348392a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
348492a25256SJohan Hedberg 	if (!conn)
348592a25256SJohan Hedberg 		return;
348692a25256SJohan Hedberg 
348792a25256SJohan Hedberg 	switch (ev->type) {
348892a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
348992a25256SJohan Hedberg 		conn->passkey_entered = 0;
349092a25256SJohan Hedberg 		return;
349192a25256SJohan Hedberg 
349292a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
349392a25256SJohan Hedberg 		conn->passkey_entered++;
349492a25256SJohan Hedberg 		break;
349592a25256SJohan Hedberg 
349692a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
349792a25256SJohan Hedberg 		conn->passkey_entered--;
349892a25256SJohan Hedberg 		break;
349992a25256SJohan Hedberg 
350092a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
350192a25256SJohan Hedberg 		conn->passkey_entered = 0;
350292a25256SJohan Hedberg 		break;
350392a25256SJohan Hedberg 
350492a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
350592a25256SJohan Hedberg 		return;
350692a25256SJohan Hedberg 	}
350792a25256SJohan Hedberg 
350892a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
350992a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
351092a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
351192a25256SJohan Hedberg 					 conn->passkey_entered);
351292a25256SJohan Hedberg }
351392a25256SJohan Hedberg 
35146039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3515807deac2SGustavo Padovan 					 struct sk_buff *skb)
35160493684eSMarcel Holtmann {
35170493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
35180493684eSMarcel Holtmann 	struct hci_conn *conn;
35190493684eSMarcel Holtmann 
35200493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
35210493684eSMarcel Holtmann 
35220493684eSMarcel Holtmann 	hci_dev_lock(hdev);
35230493684eSMarcel Holtmann 
35240493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
35252a611692SJohan Hedberg 	if (!conn)
35262a611692SJohan Hedberg 		goto unlock;
35272a611692SJohan Hedberg 
35282a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
35292a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
35302a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
35312a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
35322a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3533fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3534bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3535bab73cb6SJohan Hedberg 				 ev->status);
35362a611692SJohan Hedberg 
353776a68ba0SDavid Herrmann 	hci_conn_drop(conn);
35380493684eSMarcel Holtmann 
35392a611692SJohan Hedberg unlock:
35400493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
35410493684eSMarcel Holtmann }
35420493684eSMarcel Holtmann 
35436039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3544807deac2SGustavo Padovan 					 struct sk_buff *skb)
354541a96212SMarcel Holtmann {
354641a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
354741a96212SMarcel Holtmann 	struct inquiry_entry *ie;
3548cad718edSJohan Hedberg 	struct hci_conn *conn;
354941a96212SMarcel Holtmann 
355041a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
355141a96212SMarcel Holtmann 
355241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
355341a96212SMarcel Holtmann 
3554cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3555cad718edSJohan Hedberg 	if (conn)
3556cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
3557cad718edSJohan Hedberg 
3558cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3559cc11b9c1SAndrei Emeltchenko 	if (ie)
356002b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
356141a96212SMarcel Holtmann 
356241a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
356341a96212SMarcel Holtmann }
356441a96212SMarcel Holtmann 
35656039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
35662763eda6SSzymon Janc 					    struct sk_buff *skb)
35672763eda6SSzymon Janc {
35682763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
35692763eda6SSzymon Janc 	struct oob_data *data;
35702763eda6SSzymon Janc 
35712763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
35722763eda6SSzymon Janc 
35732763eda6SSzymon Janc 	hci_dev_lock(hdev);
35742763eda6SSzymon Janc 
3575a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3576e1ba1f15SSzymon Janc 		goto unlock;
3577e1ba1f15SSzymon Janc 
35782763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
35792763eda6SSzymon Janc 	if (data) {
3580519ca9d0SMarcel Holtmann 		if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
3581519ca9d0SMarcel Holtmann 			struct hci_cp_remote_oob_ext_data_reply cp;
3582519ca9d0SMarcel Holtmann 
3583519ca9d0SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
3584519ca9d0SMarcel Holtmann 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
3585519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer192, data->randomizer192,
3586519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer192));
3587519ca9d0SMarcel Holtmann 			memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
3588519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer256, data->randomizer256,
3589519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer256));
3590519ca9d0SMarcel Holtmann 
3591519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
3592519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3593519ca9d0SMarcel Holtmann 		} else {
35942763eda6SSzymon Janc 			struct hci_cp_remote_oob_data_reply cp;
35952763eda6SSzymon Janc 
35962763eda6SSzymon Janc 			bacpy(&cp.bdaddr, &ev->bdaddr);
3597519ca9d0SMarcel Holtmann 			memcpy(cp.hash, data->hash192, sizeof(cp.hash));
3598519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer, data->randomizer192,
3599519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer));
36002763eda6SSzymon Janc 
3601519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
3602519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3603519ca9d0SMarcel Holtmann 		}
36042763eda6SSzymon Janc 	} else {
36052763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
36062763eda6SSzymon Janc 
36072763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
3608519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
3609519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
36102763eda6SSzymon Janc 	}
36112763eda6SSzymon Janc 
3612e1ba1f15SSzymon Janc unlock:
36132763eda6SSzymon Janc 	hci_dev_unlock(hdev);
36142763eda6SSzymon Janc }
36152763eda6SSzymon Janc 
3616d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3617d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3618d5e91192SAndrei Emeltchenko {
3619d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3620d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3621d5e91192SAndrei Emeltchenko 
3622d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3623d5e91192SAndrei Emeltchenko 	       ev->status);
3624d5e91192SAndrei Emeltchenko 
3625d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3626d5e91192SAndrei Emeltchenko 
3627d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3628d5e91192SAndrei Emeltchenko 	if (!hcon) {
3629d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3630d5e91192SAndrei Emeltchenko 		return;
3631d5e91192SAndrei Emeltchenko 	}
3632d5e91192SAndrei Emeltchenko 
3633d5e91192SAndrei Emeltchenko 	if (ev->status) {
3634d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3635d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3636d5e91192SAndrei Emeltchenko 		return;
3637d5e91192SAndrei Emeltchenko 	}
3638d5e91192SAndrei Emeltchenko 
3639d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3640d5e91192SAndrei Emeltchenko 
3641d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3642d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3643d5e91192SAndrei Emeltchenko 
3644d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3645d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
364676a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
3647d5e91192SAndrei Emeltchenko 
3648d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3649d5e91192SAndrei Emeltchenko 
3650cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
3651cf70ff22SAndrei Emeltchenko 
3652d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3653d5e91192SAndrei Emeltchenko }
3654d5e91192SAndrei Emeltchenko 
365527695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
365627695fb4SAndrei Emeltchenko {
365727695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
365827695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
365927695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
366027695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
366127695fb4SAndrei Emeltchenko 
366227695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
366327695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
366427695fb4SAndrei Emeltchenko 	       ev->status);
366527695fb4SAndrei Emeltchenko 
366627695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
366727695fb4SAndrei Emeltchenko 	if (!hcon)
366827695fb4SAndrei Emeltchenko 		return;
366927695fb4SAndrei Emeltchenko 
367027695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
367127695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
367227695fb4SAndrei Emeltchenko 	if (!hchan)
367327695fb4SAndrei Emeltchenko 		return;
367427695fb4SAndrei Emeltchenko 
367527695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
367627695fb4SAndrei Emeltchenko 
367727695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
367827695fb4SAndrei Emeltchenko 
367927695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
368027695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
368127695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
368227695fb4SAndrei Emeltchenko 
368327695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
368427695fb4SAndrei Emeltchenko 
368527695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
368627695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
368727695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
368827695fb4SAndrei Emeltchenko 
368927695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
369027695fb4SAndrei Emeltchenko 	}
369127695fb4SAndrei Emeltchenko }
369227695fb4SAndrei Emeltchenko 
3693606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3694606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3695606e2a10SAndrei Emeltchenko {
3696606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3697606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3698606e2a10SAndrei Emeltchenko 
3699606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3700606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3701606e2a10SAndrei Emeltchenko 
3702606e2a10SAndrei Emeltchenko 	if (ev->status)
3703606e2a10SAndrei Emeltchenko 		return;
3704606e2a10SAndrei Emeltchenko 
3705606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3706606e2a10SAndrei Emeltchenko 
3707606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3708606e2a10SAndrei Emeltchenko 	if (!hchan)
3709606e2a10SAndrei Emeltchenko 		goto unlock;
3710606e2a10SAndrei Emeltchenko 
3711606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3712606e2a10SAndrei Emeltchenko 
3713606e2a10SAndrei Emeltchenko unlock:
3714606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3715606e2a10SAndrei Emeltchenko }
3716606e2a10SAndrei Emeltchenko 
37179eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
37189eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
37199eef6b3aSAndrei Emeltchenko {
37209eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
37219eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
37229eef6b3aSAndrei Emeltchenko 
37239eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
37249eef6b3aSAndrei Emeltchenko 
37259eef6b3aSAndrei Emeltchenko 	if (ev->status)
37269eef6b3aSAndrei Emeltchenko 		return;
37279eef6b3aSAndrei Emeltchenko 
37289eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
37299eef6b3aSAndrei Emeltchenko 
37309eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
37319eef6b3aSAndrei Emeltchenko 	if (hcon) {
37329eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
37339eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
37349eef6b3aSAndrei Emeltchenko 	}
37359eef6b3aSAndrei Emeltchenko 
37369eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
37379eef6b3aSAndrei Emeltchenko }
37389eef6b3aSAndrei Emeltchenko 
37396039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3740fcd89c09SVille Tervo {
3741fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3742fcd89c09SVille Tervo 	struct hci_conn *conn;
374368d6f6deSJohan Hedberg 	struct smp_irk *irk;
3744fcd89c09SVille Tervo 
37459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3746fcd89c09SVille Tervo 
3747fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3748fcd89c09SVille Tervo 
37494f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3750b62f328bSVille Tervo 	if (!conn) {
3751b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3752b62f328bSVille Tervo 		if (!conn) {
3753b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3754230fd16aSAndre Guedes 			goto unlock;
3755b62f328bSVille Tervo 		}
375629b7988aSAndre Guedes 
375729b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3758b9b343d2SAndre Guedes 
3759880be4e8SMarcel Holtmann 		/* The advertising parameters for own address type
3760880be4e8SMarcel Holtmann 		 * define which source address and source address
3761880be4e8SMarcel Holtmann 		 * type this connections has.
3762880be4e8SMarcel Holtmann 		 */
3763880be4e8SMarcel Holtmann 		if (bacmp(&conn->src, BDADDR_ANY)) {
3764880be4e8SMarcel Holtmann 			conn->src_type = ADDR_LE_DEV_PUBLIC;
3765880be4e8SMarcel Holtmann 		} else {
3766880be4e8SMarcel Holtmann 			bacpy(&conn->src, &hdev->static_addr);
3767880be4e8SMarcel Holtmann 			conn->src_type = ADDR_LE_DEV_RANDOM;
3768880be4e8SMarcel Holtmann 		}
3769880be4e8SMarcel Holtmann 
3770b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3771b9b343d2SAndre Guedes 			conn->out = true;
3772b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3773b9b343d2SAndre Guedes 		}
3774cb1d68f7SJohan Hedberg 
3775cb1d68f7SJohan Hedberg 		/* If we didn't have a hci_conn object previously
3776cb1d68f7SJohan Hedberg 		 * but we're in master role this must be something
3777cb1d68f7SJohan Hedberg 		 * initiated using a white list. Since white list based
3778cb1d68f7SJohan Hedberg 		 * connections are not "first class citizens" we don't
3779cb1d68f7SJohan Hedberg 		 * have full tracking of them. Therefore, we go ahead
3780cb1d68f7SJohan Hedberg 		 * with a "best effort" approach of determining the
3781cb1d68f7SJohan Hedberg 		 * initiator address based on the HCI_PRIVACY flag.
3782cb1d68f7SJohan Hedberg 		 */
3783cb1d68f7SJohan Hedberg 		if (conn->out) {
3784cb1d68f7SJohan Hedberg 			conn->resp_addr_type = ev->bdaddr_type;
3785cb1d68f7SJohan Hedberg 			bacpy(&conn->resp_addr, &ev->bdaddr);
3786cb1d68f7SJohan Hedberg 			if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) {
3787cb1d68f7SJohan Hedberg 				conn->init_addr_type = ADDR_LE_DEV_RANDOM;
3788cb1d68f7SJohan Hedberg 				bacpy(&conn->init_addr, &hdev->rpa);
3789cb1d68f7SJohan Hedberg 			} else {
3790cb1d68f7SJohan Hedberg 				hci_copy_identity_address(hdev,
3791cb1d68f7SJohan Hedberg 							  &conn->init_addr,
3792cb1d68f7SJohan Hedberg 							  &conn->init_addr_type);
3793cb1d68f7SJohan Hedberg 			}
3794cb1d68f7SJohan Hedberg 		} else {
3795cb1d68f7SJohan Hedberg 			/* Set the responder (our side) address type based on
3796cb1d68f7SJohan Hedberg 			 * the advertising address type.
3797cb1d68f7SJohan Hedberg 			 */
3798cb1d68f7SJohan Hedberg 			conn->resp_addr_type = hdev->adv_addr_type;
3799cb1d68f7SJohan Hedberg 			if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM)
3800cb1d68f7SJohan Hedberg 				bacpy(&conn->resp_addr, &hdev->random_addr);
3801cb1d68f7SJohan Hedberg 			else
3802cb1d68f7SJohan Hedberg 				bacpy(&conn->resp_addr, &hdev->bdaddr);
3803cb1d68f7SJohan Hedberg 
3804cb1d68f7SJohan Hedberg 			conn->init_addr_type = ev->bdaddr_type;
3805cb1d68f7SJohan Hedberg 			bacpy(&conn->init_addr, &ev->bdaddr);
3806cb1d68f7SJohan Hedberg 		}
38079489eca4SJohan Hedberg 	} else {
38089489eca4SJohan Hedberg 		cancel_delayed_work(&conn->le_conn_timeout);
3809b62f328bSVille Tervo 	}
3810fcd89c09SVille Tervo 
38117be2edbbSJohan Hedberg 	/* Ensure that the hci_conn contains the identity address type
38127be2edbbSJohan Hedberg 	 * regardless of which address the connection was made with.
38137be2edbbSJohan Hedberg 	 */
3814a1f4c318SJohan Hedberg 	hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
38157be2edbbSJohan Hedberg 
3816edb4b466SMarcel Holtmann 	/* Lookup the identity address from the stored connection
3817edb4b466SMarcel Holtmann 	 * address and address type.
3818edb4b466SMarcel Holtmann 	 *
3819edb4b466SMarcel Holtmann 	 * When establishing connections to an identity address, the
3820edb4b466SMarcel Holtmann 	 * connection procedure will store the resolvable random
3821edb4b466SMarcel Holtmann 	 * address first. Now if it can be converted back into the
3822edb4b466SMarcel Holtmann 	 * identity address, start using the identity address from
3823edb4b466SMarcel Holtmann 	 * now on.
3824edb4b466SMarcel Holtmann 	 */
3825edb4b466SMarcel Holtmann 	irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
382668d6f6deSJohan Hedberg 	if (irk) {
382768d6f6deSJohan Hedberg 		bacpy(&conn->dst, &irk->bdaddr);
382868d6f6deSJohan Hedberg 		conn->dst_type = irk->addr_type;
382968d6f6deSJohan Hedberg 	}
383068d6f6deSJohan Hedberg 
3831cd17decbSAndre Guedes 	if (ev->status) {
383206c053fbSAndre Guedes 		hci_le_conn_failed(conn, ev->status);
3833cd17decbSAndre Guedes 		goto unlock;
3834cd17decbSAndre Guedes 	}
3835cd17decbSAndre Guedes 
3836b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
383701fdb0fcSMarcel Holtmann 		mgmt_device_connected(hdev, &conn->dst, conn->type,
383895b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
383983bc71b4SVinicius Costa Gomes 
38407b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3841fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3842fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3843fcd89c09SVille Tervo 
384418722c24SJukka Rissanen 	if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
384518722c24SJukka Rissanen 		set_bit(HCI_CONN_6LOWPAN, &conn->flags);
384618722c24SJukka Rissanen 
3847fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3848fcd89c09SVille Tervo 
3849fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3850fcd89c09SVille Tervo 
3851a4790dbdSAndre Guedes 	hci_pend_le_conn_del(hdev, &conn->dst, conn->dst_type);
3852a4790dbdSAndre Guedes 
3853fcd89c09SVille Tervo unlock:
3854fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3855fcd89c09SVille Tervo }
3856fcd89c09SVille Tervo 
3857a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */
3858a4790dbdSAndre Guedes static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
3859a4790dbdSAndre Guedes 				  u8 addr_type)
3860a4790dbdSAndre Guedes {
3861a4790dbdSAndre Guedes 	struct hci_conn *conn;
38625b906a84SAndre Guedes 	struct smp_irk *irk;
38635b906a84SAndre Guedes 
38645b906a84SAndre Guedes 	/* If this is a resolvable address, we should resolve it and then
38655b906a84SAndre Guedes 	 * update address and address type variables.
38665b906a84SAndre Guedes 	 */
38675b906a84SAndre Guedes 	irk = hci_get_irk(hdev, addr, addr_type);
38685b906a84SAndre Guedes 	if (irk) {
38695b906a84SAndre Guedes 		addr = &irk->bdaddr;
38705b906a84SAndre Guedes 		addr_type = irk->addr_type;
38715b906a84SAndre Guedes 	}
3872a4790dbdSAndre Guedes 
3873a4790dbdSAndre Guedes 	if (!hci_pend_le_conn_lookup(hdev, addr, addr_type))
3874a4790dbdSAndre Guedes 		return;
3875a4790dbdSAndre Guedes 
3876a4790dbdSAndre Guedes 	conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
3877a4790dbdSAndre Guedes 			      HCI_AT_NO_BONDING);
3878a4790dbdSAndre Guedes 	if (!IS_ERR(conn))
3879a4790dbdSAndre Guedes 		return;
3880a4790dbdSAndre Guedes 
3881a4790dbdSAndre Guedes 	switch (PTR_ERR(conn)) {
3882a4790dbdSAndre Guedes 	case -EBUSY:
3883a4790dbdSAndre Guedes 		/* If hci_connect() returns -EBUSY it means there is already
3884a4790dbdSAndre Guedes 		 * an LE connection attempt going on. Since controllers don't
3885a4790dbdSAndre Guedes 		 * support more than one connection attempt at the time, we
3886a4790dbdSAndre Guedes 		 * don't consider this an error case.
3887a4790dbdSAndre Guedes 		 */
3888a4790dbdSAndre Guedes 		break;
3889a4790dbdSAndre Guedes 	default:
3890a4790dbdSAndre Guedes 		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
3891a4790dbdSAndre Guedes 	}
3892a4790dbdSAndre Guedes }
3893a4790dbdSAndre Guedes 
38946039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
38959aa04c91SAndre Guedes {
3896e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3897e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
38983c9e9195SAndre Guedes 	s8 rssi;
38999aa04c91SAndre Guedes 
3900a4790dbdSAndre Guedes 	hci_dev_lock(hdev);
3901a4790dbdSAndre Guedes 
3902e95beb41SAndre Guedes 	while (num_reports--) {
3903e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3904e95beb41SAndre Guedes 
3905a4790dbdSAndre Guedes 		if (ev->evt_type == LE_ADV_IND ||
3906a4790dbdSAndre Guedes 		    ev->evt_type == LE_ADV_DIRECT_IND)
3907a4790dbdSAndre Guedes 			check_pending_le_conn(hdev, &ev->bdaddr,
3908a4790dbdSAndre Guedes 					      ev->bdaddr_type);
3909a4790dbdSAndre Guedes 
39103c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
39113c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
391204124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
39133c9e9195SAndre Guedes 
3914e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
39159aa04c91SAndre Guedes 	}
3916a4790dbdSAndre Guedes 
3917a4790dbdSAndre Guedes 	hci_dev_unlock(hdev);
39189aa04c91SAndre Guedes }
39199aa04c91SAndre Guedes 
39206039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3921a7a595f6SVinicius Costa Gomes {
3922a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3923a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3924bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3925a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3926c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3927a7a595f6SVinicius Costa Gomes 
39289f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3929a7a595f6SVinicius Costa Gomes 
3930a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3931a7a595f6SVinicius Costa Gomes 
3932a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3933bea710feSVinicius Costa Gomes 	if (conn == NULL)
3934bea710feSVinicius Costa Gomes 		goto not_found;
3935a7a595f6SVinicius Costa Gomes 
3936fe39c7b2SMarcel Holtmann 	ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->out);
3937bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3938bea710feSVinicius Costa Gomes 		goto not_found;
3939bea710feSVinicius Costa Gomes 
3940bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3941a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3942c9839a11SVinicius Costa Gomes 
3943c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3944f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_HIGH;
3945f8776218SAndre Guedes 	else
3946f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_MEDIUM;
3947a7a595f6SVinicius Costa Gomes 
394889cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
3949a7a595f6SVinicius Costa Gomes 
3950a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3951a7a595f6SVinicius Costa Gomes 
3952c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3953c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3954c9839a11SVinicius Costa Gomes 		kfree(ltk);
3955c9839a11SVinicius Costa Gomes 	}
3956c9839a11SVinicius Costa Gomes 
3957a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3958bea710feSVinicius Costa Gomes 
3959bea710feSVinicius Costa Gomes 	return;
3960bea710feSVinicius Costa Gomes 
3961bea710feSVinicius Costa Gomes not_found:
3962bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3963bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3964bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3965a7a595f6SVinicius Costa Gomes }
3966a7a595f6SVinicius Costa Gomes 
39676039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3968fcd89c09SVille Tervo {
3969fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3970fcd89c09SVille Tervo 
3971fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3972fcd89c09SVille Tervo 
3973fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3974fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3975fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3976fcd89c09SVille Tervo 		break;
3977fcd89c09SVille Tervo 
39789aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
39799aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
39809aa04c91SAndre Guedes 		break;
39819aa04c91SAndre Guedes 
3982a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3983a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3984a7a595f6SVinicius Costa Gomes 		break;
3985a7a595f6SVinicius Costa Gomes 
3986fcd89c09SVille Tervo 	default:
3987fcd89c09SVille Tervo 		break;
3988fcd89c09SVille Tervo 	}
3989fcd89c09SVille Tervo }
3990fcd89c09SVille Tervo 
39919495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
39929495b2eeSAndrei Emeltchenko {
39939495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
39949495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
39959495b2eeSAndrei Emeltchenko 
39969495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
39979495b2eeSAndrei Emeltchenko 
39989495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
39999495b2eeSAndrei Emeltchenko 
40009495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
40019495b2eeSAndrei Emeltchenko 	if (!hcon)
40029495b2eeSAndrei Emeltchenko 		return;
40039495b2eeSAndrei Emeltchenko 
40049495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
40059495b2eeSAndrei Emeltchenko }
40069495b2eeSAndrei Emeltchenko 
40071da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
40081da177e4SLinus Torvalds {
4009a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
4010a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
40111da177e4SLinus Torvalds 
4012b6ddb638SJohan Hedberg 	hci_dev_lock(hdev);
4013b6ddb638SJohan Hedberg 
4014b6ddb638SJohan Hedberg 	/* Received events are (currently) only needed when a request is
4015b6ddb638SJohan Hedberg 	 * ongoing so avoid unnecessary memory allocation.
4016b6ddb638SJohan Hedberg 	 */
4017b6ddb638SJohan Hedberg 	if (hdev->req_status == HCI_REQ_PEND) {
4018b6ddb638SJohan Hedberg 		kfree_skb(hdev->recv_evt);
4019b6ddb638SJohan Hedberg 		hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
4020b6ddb638SJohan Hedberg 	}
4021b6ddb638SJohan Hedberg 
4022b6ddb638SJohan Hedberg 	hci_dev_unlock(hdev);
4023b6ddb638SJohan Hedberg 
40241da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
40251da177e4SLinus Torvalds 
402602350a72SJohan Hedberg 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
4027c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
4028c1f23a2bSJohannes Berg 		u16 opcode = __le16_to_cpu(cmd_hdr->opcode);
402902350a72SJohan Hedberg 
403002350a72SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, 0);
403102350a72SJohan Hedberg 	}
403202350a72SJohan Hedberg 
4033a9de9248SMarcel Holtmann 	switch (event) {
40341da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
40351da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
40361da177e4SLinus Torvalds 		break;
40371da177e4SLinus Torvalds 
40381da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
40391da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
40401da177e4SLinus Torvalds 		break;
40411da177e4SLinus Torvalds 
4042a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
4043a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
404421d9e30eSMarcel Holtmann 		break;
404521d9e30eSMarcel Holtmann 
40461da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
40471da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
40481da177e4SLinus Torvalds 		break;
40491da177e4SLinus Torvalds 
40501da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
40511da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
40521da177e4SLinus Torvalds 		break;
40531da177e4SLinus Torvalds 
40541da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
40551da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
40561da177e4SLinus Torvalds 		break;
40571da177e4SLinus Torvalds 
4058a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
4059a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
4060a9de9248SMarcel Holtmann 		break;
4061a9de9248SMarcel Holtmann 
40621da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
40631da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
40641da177e4SLinus Torvalds 		break;
40651da177e4SLinus Torvalds 
4066a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
4067a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
4068a9de9248SMarcel Holtmann 		break;
4069a9de9248SMarcel Holtmann 
4070a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
4071a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
4072a9de9248SMarcel Holtmann 		break;
4073a9de9248SMarcel Holtmann 
4074a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
4075a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
4076a9de9248SMarcel Holtmann 		break;
4077a9de9248SMarcel Holtmann 
4078a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
4079a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
4080a9de9248SMarcel Holtmann 		break;
4081a9de9248SMarcel Holtmann 
4082a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
4083a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
4084a9de9248SMarcel Holtmann 		break;
4085a9de9248SMarcel Holtmann 
4086a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
4087a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
4088a9de9248SMarcel Holtmann 		break;
4089a9de9248SMarcel Holtmann 
4090a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
4091a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
40921da177e4SLinus Torvalds 		break;
40931da177e4SLinus Torvalds 
40941da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
40951da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
40961da177e4SLinus Torvalds 		break;
40971da177e4SLinus Torvalds 
40981da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
40991da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
41001da177e4SLinus Torvalds 		break;
41011da177e4SLinus Torvalds 
41021da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
41031da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
41041da177e4SLinus Torvalds 		break;
41051da177e4SLinus Torvalds 
41061da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
41071da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
41081da177e4SLinus Torvalds 		break;
41091da177e4SLinus Torvalds 
4110a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
4111a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
4112a8746417SMarcel Holtmann 		break;
4113a8746417SMarcel Holtmann 
411485a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
411585a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
411685a1e930SMarcel Holtmann 		break;
411785a1e930SMarcel Holtmann 
4118a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4119a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
4120a9de9248SMarcel Holtmann 		break;
4121a9de9248SMarcel Holtmann 
4122a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
4123a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
4124a9de9248SMarcel Holtmann 		break;
4125a9de9248SMarcel Holtmann 
4126a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
4127a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
4128a9de9248SMarcel Holtmann 		break;
4129a9de9248SMarcel Holtmann 
4130a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
4131a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
41321da177e4SLinus Torvalds 		break;
41331da177e4SLinus Torvalds 
41341c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
41351c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
41361c2e0041SJohan Hedberg 		break;
41371c2e0041SJohan Hedberg 
41380493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
41390493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
41400493684eSMarcel Holtmann 		break;
41410493684eSMarcel Holtmann 
414203b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
414303b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
414403b555e1SJohan Hedberg 		break;
414503b555e1SJohan Hedberg 
4146a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
4147a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
4148a5c29683SJohan Hedberg 		break;
4149a5c29683SJohan Hedberg 
41501143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
41511143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
41521143d458SBrian Gix 		break;
41531143d458SBrian Gix 
415492a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
415592a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
415692a25256SJohan Hedberg 		break;
415792a25256SJohan Hedberg 
415892a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
415992a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
416092a25256SJohan Hedberg 		break;
416192a25256SJohan Hedberg 
41620493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
41630493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
41640493684eSMarcel Holtmann 		break;
41650493684eSMarcel Holtmann 
416641a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
416741a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
416841a96212SMarcel Holtmann 		break;
416941a96212SMarcel Holtmann 
4170fcd89c09SVille Tervo 	case HCI_EV_LE_META:
4171fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
4172fcd89c09SVille Tervo 		break;
4173fcd89c09SVille Tervo 
41749495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
41759495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
41769495b2eeSAndrei Emeltchenko 		break;
41779495b2eeSAndrei Emeltchenko 
41782763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
41792763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
41802763eda6SSzymon Janc 		break;
41812763eda6SSzymon Janc 
4182d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
4183d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
4184d5e91192SAndrei Emeltchenko 		break;
4185d5e91192SAndrei Emeltchenko 
418627695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
418727695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
418827695fb4SAndrei Emeltchenko 		break;
418927695fb4SAndrei Emeltchenko 
4190606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4191606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
4192606e2a10SAndrei Emeltchenko 		break;
4193606e2a10SAndrei Emeltchenko 
41949eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
41959eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
41969eef6b3aSAndrei Emeltchenko 		break;
41979eef6b3aSAndrei Emeltchenko 
419825e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
419925e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
420025e89e99SAndrei Emeltchenko 		break;
420125e89e99SAndrei Emeltchenko 
42021da177e4SLinus Torvalds 	default:
42039f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
42041da177e4SLinus Torvalds 		break;
42051da177e4SLinus Torvalds 	}
42061da177e4SLinus Torvalds 
42071da177e4SLinus Torvalds 	kfree_skb(skb);
42081da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
42091da177e4SLinus Torvalds }
4210