xref: /openbmc/linux/net/bluetooth/hci_event.c (revision a1f4c318)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds    BlueZ - Bluetooth protocol stack for Linux
32d0a0346SRon Shaffer    Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds    This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds    it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds    published by the Free Software Foundation;
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
121da177e4SLinus Torvalds    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131da177e4SLinus Torvalds    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
141da177e4SLinus Torvalds    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
151da177e4SLinus Torvalds    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
161da177e4SLinus Torvalds    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
171da177e4SLinus Torvalds    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
181da177e4SLinus Torvalds    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
211da177e4SLinus Torvalds    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
221da177e4SLinus Torvalds    SOFTWARE IS DISCLAIMED.
231da177e4SLinus Torvalds */
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds #include <asm/unaligned.h>
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
31f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h>
327ef9fbf0SMarcel Holtmann 
337024728eSMarcel Holtmann #include "a2mp.h"
347ef9fbf0SMarcel Holtmann #include "amp.h"
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds /* Handle HCI Event packets */
371da177e4SLinus Torvalds 
38a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
391da177e4SLinus Torvalds {
40a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
411da177e4SLinus Torvalds 
429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
431da177e4SLinus Torvalds 
4482f4785cSAndre Guedes 	if (status)
45a9de9248SMarcel Holtmann 		return;
461da177e4SLinus Torvalds 
4789352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
483e13fa1eSAndre Guedes 	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
493e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
5089352e7dSAndre Guedes 
51a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
521da177e4SLinus Torvalds }
536bd57416SMarcel Holtmann 
544d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
554d93483bSAndre Guedes {
564d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
574d93483bSAndre Guedes 
589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
59ae854a70SAndre Guedes 
60ae854a70SAndre Guedes 	if (status)
61ae854a70SAndre Guedes 		return;
62ae854a70SAndre Guedes 
63ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
644d93483bSAndre Guedes }
654d93483bSAndre Guedes 
66a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
671da177e4SLinus Torvalds {
68a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
69a9de9248SMarcel Holtmann 
709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
71a9de9248SMarcel Holtmann 
72a9de9248SMarcel Holtmann 	if (status)
73a9de9248SMarcel Holtmann 		return;
74a9de9248SMarcel Holtmann 
75ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
76ae854a70SAndre Guedes 
77a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
78a9de9248SMarcel Holtmann }
79a9de9248SMarcel Holtmann 
80807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
81807deac2SGustavo Padovan 					  struct sk_buff *skb)
82a9de9248SMarcel Holtmann {
83a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
84a9de9248SMarcel Holtmann }
85a9de9248SMarcel Holtmann 
86a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
87a9de9248SMarcel Holtmann {
88a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
891da177e4SLinus Torvalds 	struct hci_conn *conn;
901da177e4SLinus Torvalds 
919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
921da177e4SLinus Torvalds 
93a9de9248SMarcel Holtmann 	if (rp->status)
94a9de9248SMarcel Holtmann 		return;
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds 	hci_dev_lock(hdev);
971da177e4SLinus Torvalds 
98a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
991da177e4SLinus Torvalds 	if (conn) {
100a9de9248SMarcel Holtmann 		if (rp->role)
1011da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1021da177e4SLinus Torvalds 		else
1031da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1041da177e4SLinus Torvalds 	}
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
107a9de9248SMarcel Holtmann }
1081da177e4SLinus Torvalds 
109e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
110e4e8e37cSMarcel Holtmann {
111e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
112e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
113e4e8e37cSMarcel Holtmann 
1149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
115e4e8e37cSMarcel Holtmann 
116e4e8e37cSMarcel Holtmann 	if (rp->status)
117e4e8e37cSMarcel Holtmann 		return;
118e4e8e37cSMarcel Holtmann 
119e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
120e4e8e37cSMarcel Holtmann 
121e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
122e4e8e37cSMarcel Holtmann 	if (conn)
123e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
124e4e8e37cSMarcel Holtmann 
125e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
126e4e8e37cSMarcel Holtmann }
127e4e8e37cSMarcel Holtmann 
128a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
129a9de9248SMarcel Holtmann {
130a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
131a9de9248SMarcel Holtmann 	struct hci_conn *conn;
132a9de9248SMarcel Holtmann 	void *sent;
133a9de9248SMarcel Holtmann 
1349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
135a9de9248SMarcel Holtmann 
136a9de9248SMarcel Holtmann 	if (rp->status)
137a9de9248SMarcel Holtmann 		return;
138a9de9248SMarcel Holtmann 
139a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14004837f64SMarcel Holtmann 	if (!sent)
141a9de9248SMarcel Holtmann 		return;
14204837f64SMarcel Holtmann 
14304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
14404837f64SMarcel Holtmann 
145a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
146e4e8e37cSMarcel Holtmann 	if (conn)
14783985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
14804837f64SMarcel Holtmann 
14904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1501da177e4SLinus Torvalds }
1511da177e4SLinus Torvalds 
152807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
153807deac2SGustavo Padovan 					struct sk_buff *skb)
154e4e8e37cSMarcel Holtmann {
155e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
156e4e8e37cSMarcel Holtmann 
1579f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
158e4e8e37cSMarcel Holtmann 
159e4e8e37cSMarcel Holtmann 	if (rp->status)
160e4e8e37cSMarcel Holtmann 		return;
161e4e8e37cSMarcel Holtmann 
162e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
163e4e8e37cSMarcel Holtmann }
164e4e8e37cSMarcel Holtmann 
165807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
166807deac2SGustavo Padovan 					 struct sk_buff *skb)
167e4e8e37cSMarcel Holtmann {
168e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
169e4e8e37cSMarcel Holtmann 	void *sent;
170e4e8e37cSMarcel Holtmann 
1719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
172e4e8e37cSMarcel Holtmann 
173e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
174e4e8e37cSMarcel Holtmann 	if (!sent)
175e4e8e37cSMarcel Holtmann 		return;
176e4e8e37cSMarcel Holtmann 
177e4e8e37cSMarcel Holtmann 	if (!status)
178e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
179e4e8e37cSMarcel Holtmann }
180e4e8e37cSMarcel Holtmann 
181a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1821da177e4SLinus Torvalds {
183a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
184a9de9248SMarcel Holtmann 
1859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
186a9de9248SMarcel Holtmann 
18710572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
18810572132SGustavo F. Padovan 
189a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
1902cc6fb00SJohan Hedberg 	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
19169775ff6SAndre Guedes 
19269775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
193bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
194bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
1953f0f524bSJohan Hedberg 
1963f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
1973f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
198f8e808bdSMarcel Holtmann 
199f8e808bdSMarcel Holtmann 	memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data));
200f8e808bdSMarcel Holtmann 	hdev->scan_rsp_data_len = 0;
20106f5b778SMarcel Holtmann 
20206f5b778SMarcel Holtmann 	hdev->ssp_debug_mode = 0;
203a9de9248SMarcel Holtmann }
204a9de9248SMarcel Holtmann 
205a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
206a9de9248SMarcel Holtmann {
207a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2081da177e4SLinus Torvalds 	void *sent;
2091da177e4SLinus Torvalds 
2109f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2111da177e4SLinus Torvalds 
212a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2131da177e4SLinus Torvalds 	if (!sent)
214a9de9248SMarcel Holtmann 		return;
2151da177e4SLinus Torvalds 
21656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21756e5cb86SJohan Hedberg 
218f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
219f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
22028cc7bdeSJohan Hedberg 	else if (!status)
22128cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
222f51d5b24SJohan Hedberg 
22356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
224a9de9248SMarcel Holtmann }
225a9de9248SMarcel Holtmann 
226a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
227a9de9248SMarcel Holtmann {
228a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
229a9de9248SMarcel Holtmann 
2309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
231a9de9248SMarcel Holtmann 
232a9de9248SMarcel Holtmann 	if (rp->status)
233a9de9248SMarcel Holtmann 		return;
234a9de9248SMarcel Holtmann 
235db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2361f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
237a9de9248SMarcel Holtmann }
238a9de9248SMarcel Holtmann 
239a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
240a9de9248SMarcel Holtmann {
241a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
242a9de9248SMarcel Holtmann 	void *sent;
243a9de9248SMarcel Holtmann 
2449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
245a9de9248SMarcel Holtmann 
246a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
247a9de9248SMarcel Holtmann 	if (!sent)
248a9de9248SMarcel Holtmann 		return;
2491da177e4SLinus Torvalds 
2501da177e4SLinus Torvalds 	if (!status) {
251a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
252a9de9248SMarcel Holtmann 
2531da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2541da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2551da177e4SLinus Torvalds 		else
2561da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2571da177e4SLinus Torvalds 	}
258a9de9248SMarcel Holtmann 
25933ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
26033ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
261a9de9248SMarcel Holtmann }
2621da177e4SLinus Torvalds 
263a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
264a9de9248SMarcel Holtmann {
265a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
266a9de9248SMarcel Holtmann 	void *sent;
267a9de9248SMarcel Holtmann 
2689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
269a9de9248SMarcel Holtmann 
270a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2711da177e4SLinus Torvalds 	if (!sent)
272a9de9248SMarcel Holtmann 		return;
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 	if (!status) {
275a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
276a9de9248SMarcel Holtmann 
2771da177e4SLinus Torvalds 		if (param)
2781da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2791da177e4SLinus Torvalds 		else
2801da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2811da177e4SLinus Torvalds 	}
2821da177e4SLinus Torvalds }
2831da177e4SLinus Torvalds 
284a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
285a9de9248SMarcel Holtmann {
28636f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28736f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
288a9de9248SMarcel Holtmann 	void *sent;
2891da177e4SLinus Torvalds 
2909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
291a9de9248SMarcel Holtmann 
292a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2931da177e4SLinus Torvalds 	if (!sent)
294a9de9248SMarcel Holtmann 		return;
2951da177e4SLinus Torvalds 
29636f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
297a9de9248SMarcel Holtmann 
29856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29956e5cb86SJohan Hedberg 
300fa1bd918SMikel Astiz 	if (status) {
301744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3022d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3032d7cee58SJohan Hedberg 		goto done;
3042d7cee58SJohan Hedberg 	}
3052d7cee58SJohan Hedberg 
3060663ca2aSJohan Hedberg 	/* We need to ensure that we set this back on if someone changed
3070663ca2aSJohan Hedberg 	 * the scan mode through a raw HCI socket.
3080663ca2aSJohan Hedberg 	 */
3090663ca2aSJohan Hedberg 	set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
3100663ca2aSJohan Hedberg 
3119fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3129fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
313a9de9248SMarcel Holtmann 
31473f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3151da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3169fbcbb45SJohan Hedberg 		if (!old_iscan)
317744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
3189fbcbb45SJohan Hedberg 	} else if (old_iscan)
319744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3201da177e4SLinus Torvalds 
3219fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3221da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3239fbcbb45SJohan Hedberg 		if (!old_pscan)
324744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3259fbcbb45SJohan Hedberg 	} else if (old_pscan)
326744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
327a9de9248SMarcel Holtmann 
32836f7fc7eSJohan Hedberg done:
32956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
332a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
333a9de9248SMarcel Holtmann {
334a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
335a9de9248SMarcel Holtmann 
3369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
337a9de9248SMarcel Holtmann 
338a9de9248SMarcel Holtmann 	if (rp->status)
339a9de9248SMarcel Holtmann 		return;
340a9de9248SMarcel Holtmann 
341a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
342a9de9248SMarcel Holtmann 
343a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
344a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
345a9de9248SMarcel Holtmann }
346a9de9248SMarcel Holtmann 
347a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
348a9de9248SMarcel Holtmann {
349a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
350a9de9248SMarcel Holtmann 	void *sent;
351a9de9248SMarcel Holtmann 
3529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
353a9de9248SMarcel Holtmann 
354a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
355a9de9248SMarcel Holtmann 	if (!sent)
356a9de9248SMarcel Holtmann 		return;
357a9de9248SMarcel Holtmann 
3587f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3597f9a903cSMarcel Holtmann 
3607f9a903cSMarcel Holtmann 	if (status == 0)
361a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3627f9a903cSMarcel Holtmann 
3637f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3647f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3657f9a903cSMarcel Holtmann 
3667f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
367a9de9248SMarcel Holtmann }
368a9de9248SMarcel Holtmann 
369a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
370a9de9248SMarcel Holtmann {
371a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
372a9de9248SMarcel Holtmann 	__u16 setting;
373a9de9248SMarcel Holtmann 
3749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
375a9de9248SMarcel Holtmann 
376a9de9248SMarcel Holtmann 	if (rp->status)
377a9de9248SMarcel Holtmann 		return;
378a9de9248SMarcel Holtmann 
379a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
380a9de9248SMarcel Holtmann 
381a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
382a9de9248SMarcel Holtmann 		return;
383a9de9248SMarcel Holtmann 
384a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
385a9de9248SMarcel Holtmann 
3869f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
387a9de9248SMarcel Holtmann 
3883c54711cSGustavo F. Padovan 	if (hdev->notify)
389a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
390a9de9248SMarcel Holtmann }
391a9de9248SMarcel Holtmann 
3928fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
3938fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
394a9de9248SMarcel Holtmann {
395a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
396f383f275SMarcel Holtmann 	__u16 setting;
397a9de9248SMarcel Holtmann 	void *sent;
398a9de9248SMarcel Holtmann 
3999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
400a9de9248SMarcel Holtmann 
401f383f275SMarcel Holtmann 	if (status)
402f383f275SMarcel Holtmann 		return;
403f383f275SMarcel Holtmann 
404a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
405a9de9248SMarcel Holtmann 	if (!sent)
406a9de9248SMarcel Holtmann 		return;
407a9de9248SMarcel Holtmann 
408f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4091da177e4SLinus Torvalds 
410f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
411f383f275SMarcel Holtmann 		return;
412f383f275SMarcel Holtmann 
4131da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4141da177e4SLinus Torvalds 
4159f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4161da177e4SLinus Torvalds 
4173c54711cSGustavo F. Padovan 	if (hdev->notify)
4181da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4191da177e4SLinus Torvalds }
4201da177e4SLinus Torvalds 
421b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev,
422b4cb9fb2SMarcel Holtmann 					  struct sk_buff *skb)
423b4cb9fb2SMarcel Holtmann {
424b4cb9fb2SMarcel Holtmann 	struct hci_rp_read_num_supported_iac *rp = (void *) skb->data;
425b4cb9fb2SMarcel Holtmann 
426b4cb9fb2SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
427b4cb9fb2SMarcel Holtmann 
428b4cb9fb2SMarcel Holtmann 	if (rp->status)
429b4cb9fb2SMarcel Holtmann 		return;
430b4cb9fb2SMarcel Holtmann 
431b4cb9fb2SMarcel Holtmann 	hdev->num_iac = rp->num_iac;
432b4cb9fb2SMarcel Holtmann 
433b4cb9fb2SMarcel Holtmann 	BT_DBG("%s num iac %d", hdev->name, hdev->num_iac);
434b4cb9fb2SMarcel Holtmann }
435b4cb9fb2SMarcel Holtmann 
436333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
437333140b5SMarcel Holtmann {
438333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4395ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
440333140b5SMarcel Holtmann 
4419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
442333140b5SMarcel Holtmann 
443333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
444333140b5SMarcel Holtmann 	if (!sent)
445333140b5SMarcel Holtmann 		return;
446333140b5SMarcel Holtmann 
4475ed8eb2fSJohan Hedberg 	if (!status) {
4485ed8eb2fSJohan Hedberg 		if (sent->mode)
449cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_SSP;
4505ed8eb2fSJohan Hedberg 		else
451cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_SSP;
4525ed8eb2fSJohan Hedberg 	}
4535ed8eb2fSJohan Hedberg 
454c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4555ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
456c0ecddc2SJohan Hedberg 	else if (!status) {
4575ed8eb2fSJohan Hedberg 		if (sent->mode)
45884bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
45984bde9d6SJohan Hedberg 		else
46084bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
461c0ecddc2SJohan Hedberg 	}
462333140b5SMarcel Holtmann }
463333140b5SMarcel Holtmann 
464eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
465eac83dc6SMarcel Holtmann {
466eac83dc6SMarcel Holtmann 	u8 status = *((u8 *) skb->data);
467eac83dc6SMarcel Holtmann 	struct hci_cp_write_sc_support *sent;
468eac83dc6SMarcel Holtmann 
469eac83dc6SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
470eac83dc6SMarcel Holtmann 
471eac83dc6SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
472eac83dc6SMarcel Holtmann 	if (!sent)
473eac83dc6SMarcel Holtmann 		return;
474eac83dc6SMarcel Holtmann 
475eac83dc6SMarcel Holtmann 	if (!status) {
476eac83dc6SMarcel Holtmann 		if (sent->support)
477eac83dc6SMarcel Holtmann 			hdev->features[1][0] |= LMP_HOST_SC;
478eac83dc6SMarcel Holtmann 		else
479eac83dc6SMarcel Holtmann 			hdev->features[1][0] &= ~LMP_HOST_SC;
480eac83dc6SMarcel Holtmann 	}
481eac83dc6SMarcel Holtmann 
482eac83dc6SMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
483eac83dc6SMarcel Holtmann 		mgmt_sc_enable_complete(hdev, sent->support, status);
484eac83dc6SMarcel Holtmann 	else if (!status) {
485eac83dc6SMarcel Holtmann 		if (sent->support)
486eac83dc6SMarcel Holtmann 			set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
487eac83dc6SMarcel Holtmann 		else
488eac83dc6SMarcel Holtmann 			clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
489eac83dc6SMarcel Holtmann 	}
490eac83dc6SMarcel Holtmann }
491eac83dc6SMarcel Holtmann 
492a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
493a9de9248SMarcel Holtmann {
494a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
4951143e5a6SMarcel Holtmann 
4969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
4971143e5a6SMarcel Holtmann 
498a9de9248SMarcel Holtmann 	if (rp->status)
49942c6b129SJohan Hedberg 		return;
5001143e5a6SMarcel Holtmann 
5010d5551f5SMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
502a9de9248SMarcel Holtmann 		hdev->hci_ver = rp->hci_ver;
503e4e8e37cSMarcel Holtmann 		hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
504d5859e22SJohan Hedberg 		hdev->lmp_ver = rp->lmp_ver;
505e4e8e37cSMarcel Holtmann 		hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
506d5859e22SJohan Hedberg 		hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
5070d5551f5SMarcel Holtmann 	}
508d5859e22SJohan Hedberg }
509d5859e22SJohan Hedberg 
5108fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
5118fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
512a9de9248SMarcel Holtmann {
513a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
514a9de9248SMarcel Holtmann 
5159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
516a9de9248SMarcel Holtmann 
5176a070e6eSMarcel Holtmann 	if (rp->status)
5186a070e6eSMarcel Holtmann 		return;
5196a070e6eSMarcel Holtmann 
5206a070e6eSMarcel Holtmann 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
521a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
522a9de9248SMarcel Holtmann }
523a9de9248SMarcel Holtmann 
5248fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
5258fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
526a9de9248SMarcel Holtmann {
527a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
528a9de9248SMarcel Holtmann 
5299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
530a9de9248SMarcel Holtmann 
531a9de9248SMarcel Holtmann 	if (rp->status)
532a9de9248SMarcel Holtmann 		return;
533a9de9248SMarcel Holtmann 
534a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
5351da177e4SLinus Torvalds 
5361da177e4SLinus Torvalds 	/* Adjust default settings according to features
5371da177e4SLinus Torvalds 	 * supported by device. */
538a9de9248SMarcel Holtmann 
539cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_3SLOT)
5401da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
5411da177e4SLinus Torvalds 
542cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_5SLOT)
5431da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
5441da177e4SLinus Torvalds 
545cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV2) {
5461da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
5475b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
5485b7f9909SMarcel Holtmann 	}
5491da177e4SLinus Torvalds 
550cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV3) {
5511da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
5525b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
5535b7f9909SMarcel Holtmann 	}
5545b7f9909SMarcel Holtmann 
55545db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
5565b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
5575b7f9909SMarcel Holtmann 
558cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV4)
5595b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
5605b7f9909SMarcel Holtmann 
561cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV5)
5625b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
5631da177e4SLinus Torvalds 
564cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
565efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
566efc7688bSMarcel Holtmann 
567cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
568efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
569efc7688bSMarcel Holtmann 
570cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
571efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
5721da177e4SLinus Torvalds }
5731da177e4SLinus Torvalds 
574971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
575971e3a4bSAndre Guedes 					   struct sk_buff *skb)
576971e3a4bSAndre Guedes {
577971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
578971e3a4bSAndre Guedes 
5799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
580971e3a4bSAndre Guedes 
581971e3a4bSAndre Guedes 	if (rp->status)
58242c6b129SJohan Hedberg 		return;
583971e3a4bSAndre Guedes 
58457af75a8SMarcel Holtmann 	if (hdev->max_page < rp->max_page)
585d2c5d77fSJohan Hedberg 		hdev->max_page = rp->max_page;
586d2c5d77fSJohan Hedberg 
587cad718edSJohan Hedberg 	if (rp->page < HCI_MAX_PAGES)
588cad718edSJohan Hedberg 		memcpy(hdev->features[rp->page], rp->features, 8);
589971e3a4bSAndre Guedes }
590971e3a4bSAndre Guedes 
5911e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
5921e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
5931e89cffbSAndrei Emeltchenko {
5941e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
5951e89cffbSAndrei Emeltchenko 
5969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5971e89cffbSAndrei Emeltchenko 
59842c6b129SJohan Hedberg 	if (!rp->status)
5991e89cffbSAndrei Emeltchenko 		hdev->flow_ctl_mode = rp->mode;
6001e89cffbSAndrei Emeltchenko }
6011e89cffbSAndrei Emeltchenko 
602a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
603a9de9248SMarcel Holtmann {
604a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
605a9de9248SMarcel Holtmann 
6069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
607a9de9248SMarcel Holtmann 
608a9de9248SMarcel Holtmann 	if (rp->status)
609a9de9248SMarcel Holtmann 		return;
610a9de9248SMarcel Holtmann 
611a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
612a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
613a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
614a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
615da1f5198SMarcel Holtmann 
616da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
617da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
618da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
619da1f5198SMarcel Holtmann 	}
620da1f5198SMarcel Holtmann 
621da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
622da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
6231da177e4SLinus Torvalds 
624807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
625807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
6261da177e4SLinus Torvalds }
6271da177e4SLinus Torvalds 
628a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
629a9de9248SMarcel Holtmann {
630a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6311da177e4SLinus Torvalds 
6329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
633a9de9248SMarcel Holtmann 
634a9de9248SMarcel Holtmann 	if (!rp->status)
635a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
63623bb5763SJohan Hedberg }
63723bb5763SJohan Hedberg 
638f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
639f332ec66SJohan Hedberg 					   struct sk_buff *skb)
640f332ec66SJohan Hedberg {
641f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
642f332ec66SJohan Hedberg 
643f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
644f332ec66SJohan Hedberg 
645f332ec66SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) {
646f332ec66SJohan Hedberg 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
647f332ec66SJohan Hedberg 		hdev->page_scan_window = __le16_to_cpu(rp->window);
648f332ec66SJohan Hedberg 	}
649f332ec66SJohan Hedberg }
650f332ec66SJohan Hedberg 
6514a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
6524a3ee763SJohan Hedberg 					    struct sk_buff *skb)
6534a3ee763SJohan Hedberg {
6544a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6554a3ee763SJohan Hedberg 	struct hci_cp_write_page_scan_activity *sent;
6564a3ee763SJohan Hedberg 
6574a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6584a3ee763SJohan Hedberg 
6594a3ee763SJohan Hedberg 	if (status)
6604a3ee763SJohan Hedberg 		return;
6614a3ee763SJohan Hedberg 
6624a3ee763SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
6634a3ee763SJohan Hedberg 	if (!sent)
6644a3ee763SJohan Hedberg 		return;
6654a3ee763SJohan Hedberg 
6664a3ee763SJohan Hedberg 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
6674a3ee763SJohan Hedberg 	hdev->page_scan_window = __le16_to_cpu(sent->window);
6684a3ee763SJohan Hedberg }
6694a3ee763SJohan Hedberg 
670f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
671f332ec66SJohan Hedberg 					   struct sk_buff *skb)
672f332ec66SJohan Hedberg {
673f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
674f332ec66SJohan Hedberg 
675f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
676f332ec66SJohan Hedberg 
677f332ec66SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status)
678f332ec66SJohan Hedberg 		hdev->page_scan_type = rp->type;
679f332ec66SJohan Hedberg }
680f332ec66SJohan Hedberg 
6814a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
6824a3ee763SJohan Hedberg 					struct sk_buff *skb)
6834a3ee763SJohan Hedberg {
6844a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6854a3ee763SJohan Hedberg 	u8 *type;
6864a3ee763SJohan Hedberg 
6874a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6884a3ee763SJohan Hedberg 
6894a3ee763SJohan Hedberg 	if (status)
6904a3ee763SJohan Hedberg 		return;
6914a3ee763SJohan Hedberg 
6924a3ee763SJohan Hedberg 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
6934a3ee763SJohan Hedberg 	if (type)
6944a3ee763SJohan Hedberg 		hdev->page_scan_type = *type;
6954a3ee763SJohan Hedberg }
6964a3ee763SJohan Hedberg 
697350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
698350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
699350ee4cfSAndrei Emeltchenko {
700350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
701350ee4cfSAndrei Emeltchenko 
7029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
703350ee4cfSAndrei Emeltchenko 
704350ee4cfSAndrei Emeltchenko 	if (rp->status)
705350ee4cfSAndrei Emeltchenko 		return;
706350ee4cfSAndrei Emeltchenko 
707350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
708350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
709350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
710350ee4cfSAndrei Emeltchenko 
711350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
712350ee4cfSAndrei Emeltchenko 
713350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
714350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
715350ee4cfSAndrei Emeltchenko }
716350ee4cfSAndrei Emeltchenko 
717928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
718928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
719928abaa7SAndrei Emeltchenko {
720928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
721928abaa7SAndrei Emeltchenko 
7229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
723928abaa7SAndrei Emeltchenko 
724928abaa7SAndrei Emeltchenko 	if (rp->status)
7258e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
726928abaa7SAndrei Emeltchenko 
727928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
728928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
729928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
730928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
731928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
732928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
733928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
734928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
735928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
736928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
737928abaa7SAndrei Emeltchenko 
7388e2a0d92SAndrei Emeltchenko a2mp_rsp:
7398e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
740928abaa7SAndrei Emeltchenko }
741928abaa7SAndrei Emeltchenko 
742903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
743903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
744903e4541SAndrei Emeltchenko {
745903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
746903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
747903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
748903e4541SAndrei Emeltchenko 
749903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
750903e4541SAndrei Emeltchenko 
751903e4541SAndrei Emeltchenko 	if (rp->status)
752903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
753903e4541SAndrei Emeltchenko 
754903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
755903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
756903e4541SAndrei Emeltchenko 
757903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
7582e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
759903e4541SAndrei Emeltchenko 
760903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
761903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
762903e4541SAndrei Emeltchenko 
763903e4541SAndrei Emeltchenko 		/* Read other fragments */
764903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
765903e4541SAndrei Emeltchenko 
766903e4541SAndrei Emeltchenko 		return;
767903e4541SAndrei Emeltchenko 	}
768903e4541SAndrei Emeltchenko 
769903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
770903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
771903e4541SAndrei Emeltchenko 	assoc->offset = 0;
772903e4541SAndrei Emeltchenko 
773903e4541SAndrei Emeltchenko a2mp_rsp:
774903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
775903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
7769495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
777903e4541SAndrei Emeltchenko }
778903e4541SAndrei Emeltchenko 
779d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
780d5859e22SJohan Hedberg 					 struct sk_buff *skb)
781d5859e22SJohan Hedberg {
78291c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
783d5859e22SJohan Hedberg 
7849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
785d5859e22SJohan Hedberg 
78691c4e9b1SMarcel Holtmann 	if (!rp->status)
78791c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
788d5859e22SJohan Hedberg }
789d5859e22SJohan Hedberg 
790980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
791980e1a53SJohan Hedberg {
792980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
793980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
794980e1a53SJohan Hedberg 	struct hci_conn *conn;
795980e1a53SJohan Hedberg 
7969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
797980e1a53SJohan Hedberg 
79856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
79956e5cb86SJohan Hedberg 
800a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
801744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
802980e1a53SJohan Hedberg 
803fa1bd918SMikel Astiz 	if (rp->status)
80456e5cb86SJohan Hedberg 		goto unlock;
805980e1a53SJohan Hedberg 
806980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
807980e1a53SJohan Hedberg 	if (!cp)
80856e5cb86SJohan Hedberg 		goto unlock;
809980e1a53SJohan Hedberg 
810980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
811980e1a53SJohan Hedberg 	if (conn)
812980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
81356e5cb86SJohan Hedberg 
81456e5cb86SJohan Hedberg unlock:
81556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
816980e1a53SJohan Hedberg }
817980e1a53SJohan Hedberg 
818980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
819980e1a53SJohan Hedberg {
820980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
821980e1a53SJohan Hedberg 
8229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
823980e1a53SJohan Hedberg 
82456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
82556e5cb86SJohan Hedberg 
826a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
827744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
828980e1a53SJohan Hedberg 						 rp->status);
82956e5cb86SJohan Hedberg 
83056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
831980e1a53SJohan Hedberg }
83256e5cb86SJohan Hedberg 
8336ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8346ed58ec5SVille Tervo 				       struct sk_buff *skb)
8356ed58ec5SVille Tervo {
8366ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
8376ed58ec5SVille Tervo 
8389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8396ed58ec5SVille Tervo 
8406ed58ec5SVille Tervo 	if (rp->status)
8416ed58ec5SVille Tervo 		return;
8426ed58ec5SVille Tervo 
8436ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
8446ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8456ed58ec5SVille Tervo 
8466ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8476ed58ec5SVille Tervo 
8486ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8496ed58ec5SVille Tervo }
850980e1a53SJohan Hedberg 
85160e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
85260e77321SJohan Hedberg 					  struct sk_buff *skb)
85360e77321SJohan Hedberg {
85460e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
85560e77321SJohan Hedberg 
85660e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
85760e77321SJohan Hedberg 
85860e77321SJohan Hedberg 	if (!rp->status)
85960e77321SJohan Hedberg 		memcpy(hdev->le_features, rp->features, 8);
86060e77321SJohan Hedberg }
86160e77321SJohan Hedberg 
8628fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
8638fa19098SJohan Hedberg 					struct sk_buff *skb)
8648fa19098SJohan Hedberg {
8658fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
8668fa19098SJohan Hedberg 
8678fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8688fa19098SJohan Hedberg 
86904b4edcbSJohan Hedberg 	if (!rp->status)
8708fa19098SJohan Hedberg 		hdev->adv_tx_power = rp->tx_power;
8718fa19098SJohan Hedberg }
8728fa19098SJohan Hedberg 
873a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
874a5c29683SJohan Hedberg {
875a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
876a5c29683SJohan Hedberg 
8779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
878a5c29683SJohan Hedberg 
87956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
88056e5cb86SJohan Hedberg 
881a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
88204124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
88304124681SGustavo F. Padovan 						 rp->status);
88456e5cb86SJohan Hedberg 
88556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
886a5c29683SJohan Hedberg }
887a5c29683SJohan Hedberg 
888a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
889a5c29683SJohan Hedberg 					  struct sk_buff *skb)
890a5c29683SJohan Hedberg {
891a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
892a5c29683SJohan Hedberg 
8939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
894a5c29683SJohan Hedberg 
89556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
89656e5cb86SJohan Hedberg 
897a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
898744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
89904124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
90056e5cb86SJohan Hedberg 
90156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
902a5c29683SJohan Hedberg }
903a5c29683SJohan Hedberg 
9041143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9051143d458SBrian Gix {
9061143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9071143d458SBrian Gix 
9089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9091143d458SBrian Gix 
9101143d458SBrian Gix 	hci_dev_lock(hdev);
9111143d458SBrian Gix 
912a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
913272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
914272d90dfSJohan Hedberg 						 0, rp->status);
9151143d458SBrian Gix 
9161143d458SBrian Gix 	hci_dev_unlock(hdev);
9171143d458SBrian Gix }
9181143d458SBrian Gix 
9191143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9201143d458SBrian Gix 					  struct sk_buff *skb)
9211143d458SBrian Gix {
9221143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9231143d458SBrian Gix 
9249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9251143d458SBrian Gix 
9261143d458SBrian Gix 	hci_dev_lock(hdev);
9271143d458SBrian Gix 
928a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9291143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
93004124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
9311143d458SBrian Gix 
9321143d458SBrian Gix 	hci_dev_unlock(hdev);
9331143d458SBrian Gix }
9341143d458SBrian Gix 
9354d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
936c35938b2SSzymon Janc 				       struct sk_buff *skb)
937c35938b2SSzymon Janc {
938c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
939c35938b2SSzymon Janc 
9409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
941c35938b2SSzymon Janc 
94256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
9434d2d2796SMarcel Holtmann 	mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer,
9444d2d2796SMarcel Holtmann 					  NULL, NULL, rp->status);
9454d2d2796SMarcel Holtmann 	hci_dev_unlock(hdev);
9464d2d2796SMarcel Holtmann }
9474d2d2796SMarcel Holtmann 
9484d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
9494d2d2796SMarcel Holtmann 					   struct sk_buff *skb)
9504d2d2796SMarcel Holtmann {
9514d2d2796SMarcel Holtmann 	struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
9524d2d2796SMarcel Holtmann 
9534d2d2796SMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9544d2d2796SMarcel Holtmann 
9554d2d2796SMarcel Holtmann 	hci_dev_lock(hdev);
9564d2d2796SMarcel Holtmann 	mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192,
9574d2d2796SMarcel Holtmann 					  rp->hash256, rp->randomizer256,
9584d2d2796SMarcel Holtmann 					  rp->status);
95956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
960c35938b2SSzymon Janc }
961c35938b2SSzymon Janc 
9627a4cd51dSMarcel Holtmann 
9637a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
9647a4cd51dSMarcel Holtmann {
9657a4cd51dSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
9667a4cd51dSMarcel Holtmann 	bdaddr_t *sent;
9677a4cd51dSMarcel Holtmann 
9687a4cd51dSMarcel Holtmann 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
9697a4cd51dSMarcel Holtmann 
9707a4cd51dSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
9717a4cd51dSMarcel Holtmann 	if (!sent)
9727a4cd51dSMarcel Holtmann 		return;
9737a4cd51dSMarcel Holtmann 
9747a4cd51dSMarcel Holtmann 	hci_dev_lock(hdev);
9757a4cd51dSMarcel Holtmann 
9767a4cd51dSMarcel Holtmann 	if (!status)
9777a4cd51dSMarcel Holtmann 		bacpy(&hdev->random_addr, sent);
9787a4cd51dSMarcel Holtmann 
9797a4cd51dSMarcel Holtmann 	hci_dev_unlock(hdev);
9807a4cd51dSMarcel Holtmann }
9817a4cd51dSMarcel Holtmann 
982c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
983c1d5dc4aSJohan Hedberg {
984c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
985c1d5dc4aSJohan Hedberg 
986c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
987c1d5dc4aSJohan Hedberg 
988c1d5dc4aSJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
989c1d5dc4aSJohan Hedberg 	if (!sent)
990c1d5dc4aSJohan Hedberg 		return;
991c1d5dc4aSJohan Hedberg 
992c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
993c1d5dc4aSJohan Hedberg 
994778b235aSJohan Hedberg 	if (!status)
995778b235aSJohan Hedberg 		mgmt_advertising(hdev, *sent);
996c1d5dc4aSJohan Hedberg 
99704b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
998c1d5dc4aSJohan Hedberg }
999c1d5dc4aSJohan Hedberg 
1000eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1001eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1002eb9d91f5SAndre Guedes {
1003eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1004eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1005eb9d91f5SAndre Guedes 
10069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1007eb9d91f5SAndre Guedes 
1008eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1009eb9d91f5SAndre Guedes 	if (!cp)
1010eb9d91f5SAndre Guedes 		return;
1011eb9d91f5SAndre Guedes 
1012fef5234aSAndre Guedes 	if (status)
10137ba8b4beSAndre Guedes 		return;
10147ba8b4beSAndre Guedes 
10153fd319b8SAndre Guedes 	switch (cp->enable) {
10163fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
1017d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
101868a8aea4SAndrei Emeltchenko 		break;
101968a8aea4SAndrei Emeltchenko 
102076a388beSAndre Guedes 	case LE_SCAN_DISABLE:
1021d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
102268a8aea4SAndrei Emeltchenko 		break;
102368a8aea4SAndrei Emeltchenko 
102468a8aea4SAndrei Emeltchenko 	default:
102568a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
102668a8aea4SAndrei Emeltchenko 		break;
102735815085SAndre Guedes 	}
1028eb9d91f5SAndre Guedes }
1029eb9d91f5SAndre Guedes 
1030cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1031cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
1032cf1d081fSJohan Hedberg {
1033cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1034cf1d081fSJohan Hedberg 
1035cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1036cf1d081fSJohan Hedberg 
1037cf1d081fSJohan Hedberg 	if (!rp->status)
1038cf1d081fSJohan Hedberg 		hdev->le_white_list_size = rp->size;
1039cf1d081fSJohan Hedberg }
1040cf1d081fSJohan Hedberg 
10419b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
10429b008c04SJohan Hedberg 					    struct sk_buff *skb)
10439b008c04SJohan Hedberg {
10449b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
10459b008c04SJohan Hedberg 
10469b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10479b008c04SJohan Hedberg 
10489b008c04SJohan Hedberg 	if (!rp->status)
10499b008c04SJohan Hedberg 		memcpy(hdev->le_states, rp->le_states, 8);
10509b008c04SJohan Hedberg }
10519b008c04SJohan Hedberg 
10526039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1053f9b49306SAndre Guedes 					   struct sk_buff *skb)
1054f9b49306SAndre Guedes {
105506199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1056f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1057f9b49306SAndre Guedes 
10589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1059f9b49306SAndre Guedes 
106006199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
10618f984dfaSJohan Hedberg 	if (!sent)
1062f9b49306SAndre Guedes 		return;
1063f9b49306SAndre Guedes 
10648f984dfaSJohan Hedberg 	if (!status) {
1065416a4ae5SJohan Hedberg 		if (sent->le) {
1066cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE;
1067416a4ae5SJohan Hedberg 			set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1068416a4ae5SJohan Hedberg 		} else {
1069cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE;
1070416a4ae5SJohan Hedberg 			clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1071f3d3444aSJohan Hedberg 			clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1072416a4ae5SJohan Hedberg 		}
107353b2caabSJohan Hedberg 
107453b2caabSJohan Hedberg 		if (sent->simul)
1075cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE_BREDR;
107653b2caabSJohan Hedberg 		else
1077cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
10788f984dfaSJohan Hedberg 	}
1079f9b49306SAndre Guedes }
1080f9b49306SAndre Guedes 
108156ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
108256ed2cb8SJohan Hedberg {
108356ed2cb8SJohan Hedberg 	struct hci_cp_le_set_adv_param *cp;
108456ed2cb8SJohan Hedberg 	u8 status = *((u8 *) skb->data);
108556ed2cb8SJohan Hedberg 
108656ed2cb8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
108756ed2cb8SJohan Hedberg 
108856ed2cb8SJohan Hedberg 	if (status)
108956ed2cb8SJohan Hedberg 		return;
109056ed2cb8SJohan Hedberg 
109156ed2cb8SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
109256ed2cb8SJohan Hedberg 	if (!cp)
109356ed2cb8SJohan Hedberg 		return;
109456ed2cb8SJohan Hedberg 
109556ed2cb8SJohan Hedberg 	hci_dev_lock(hdev);
109656ed2cb8SJohan Hedberg 	hdev->adv_addr_type = cp->own_address_type;
109756ed2cb8SJohan Hedberg 	hci_dev_unlock(hdev);
109856ed2cb8SJohan Hedberg }
109956ed2cb8SJohan Hedberg 
110093c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
110193c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
110293c284eeSAndrei Emeltchenko {
110393c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
110493c284eeSAndrei Emeltchenko 
110593c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
110693c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
110793c284eeSAndrei Emeltchenko 
110893c284eeSAndrei Emeltchenko 	if (rp->status)
110993c284eeSAndrei Emeltchenko 		return;
111093c284eeSAndrei Emeltchenko 
111193c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
111293c284eeSAndrei Emeltchenko }
111393c284eeSAndrei Emeltchenko 
11146039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1115a9de9248SMarcel Holtmann {
11169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1117a9de9248SMarcel Holtmann 
1118a9de9248SMarcel Holtmann 	if (status) {
1119a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1120314b2381SJohan Hedberg 		return;
1121314b2381SJohan Hedberg 	}
1122314b2381SJohan Hedberg 
112389352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1124a9de9248SMarcel Holtmann }
1125a9de9248SMarcel Holtmann 
11266039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11271da177e4SLinus Torvalds {
1128a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11291da177e4SLinus Torvalds 	struct hci_conn *conn;
11301da177e4SLinus Torvalds 
11319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1132a9de9248SMarcel Holtmann 
1133a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11341da177e4SLinus Torvalds 	if (!cp)
11351da177e4SLinus Torvalds 		return;
11361da177e4SLinus Torvalds 
11371da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11381da177e4SLinus Torvalds 
11391da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11401da177e4SLinus Torvalds 
11416ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
11421da177e4SLinus Torvalds 
11431da177e4SLinus Torvalds 	if (status) {
11441da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11454c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
11461da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
11471da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
11481da177e4SLinus Torvalds 				hci_conn_del(conn);
11494c67bc74SMarcel Holtmann 			} else
11504c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
11511da177e4SLinus Torvalds 		}
11521da177e4SLinus Torvalds 	} else {
11531da177e4SLinus Torvalds 		if (!conn) {
11541da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
11551da177e4SLinus Torvalds 			if (conn) {
1156a0c808b3SJohan Hedberg 				conn->out = true;
11571da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
11581da177e4SLinus Torvalds 			} else
1159893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
11601da177e4SLinus Torvalds 		}
11611da177e4SLinus Torvalds 	}
11621da177e4SLinus Torvalds 
11631da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11641da177e4SLinus Torvalds }
11651da177e4SLinus Torvalds 
1166a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
11671da177e4SLinus Torvalds {
1168a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
11691da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
11701da177e4SLinus Torvalds 	__u16 handle;
11711da177e4SLinus Torvalds 
11729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1173b6a0dc82SMarcel Holtmann 
1174a9de9248SMarcel Holtmann 	if (!status)
1175a9de9248SMarcel Holtmann 		return;
1176a9de9248SMarcel Holtmann 
1177a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
11781da177e4SLinus Torvalds 	if (!cp)
1179a9de9248SMarcel Holtmann 		return;
11801da177e4SLinus Torvalds 
11811da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11821da177e4SLinus Torvalds 
11839f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
11841da177e4SLinus Torvalds 
11851da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11861da177e4SLinus Torvalds 
11871da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11885a08ecceSAndrei Emeltchenko 	if (acl) {
11895a08ecceSAndrei Emeltchenko 		sco = acl->link;
11905a08ecceSAndrei Emeltchenko 		if (sco) {
11911da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11941da177e4SLinus Torvalds 			hci_conn_del(sco);
11951da177e4SLinus Torvalds 		}
11965a08ecceSAndrei Emeltchenko 	}
11971da177e4SLinus Torvalds 
11981da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11991da177e4SLinus Torvalds }
12001da177e4SLinus Torvalds 
1201f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1202f8558555SMarcel Holtmann {
1203f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1204f8558555SMarcel Holtmann 	struct hci_conn *conn;
1205f8558555SMarcel Holtmann 
12069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1207f8558555SMarcel Holtmann 
1208f8558555SMarcel Holtmann 	if (!status)
1209f8558555SMarcel Holtmann 		return;
1210f8558555SMarcel Holtmann 
1211f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1212f8558555SMarcel Holtmann 	if (!cp)
1213f8558555SMarcel Holtmann 		return;
1214f8558555SMarcel Holtmann 
1215f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1216f8558555SMarcel Holtmann 
1217f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1218f8558555SMarcel Holtmann 	if (conn) {
1219f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1220f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
122176a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1222f8558555SMarcel Holtmann 		}
1223f8558555SMarcel Holtmann 	}
1224f8558555SMarcel Holtmann 
1225f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1226f8558555SMarcel Holtmann }
1227f8558555SMarcel Holtmann 
1228f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1229f8558555SMarcel Holtmann {
1230f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1231f8558555SMarcel Holtmann 	struct hci_conn *conn;
1232f8558555SMarcel Holtmann 
12339f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1234f8558555SMarcel Holtmann 
1235f8558555SMarcel Holtmann 	if (!status)
1236f8558555SMarcel Holtmann 		return;
1237f8558555SMarcel Holtmann 
1238f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1239f8558555SMarcel Holtmann 	if (!cp)
1240f8558555SMarcel Holtmann 		return;
1241f8558555SMarcel Holtmann 
1242f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1243f8558555SMarcel Holtmann 
1244f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1245f8558555SMarcel Holtmann 	if (conn) {
1246f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1247f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
124876a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1249f8558555SMarcel Holtmann 		}
1250f8558555SMarcel Holtmann 	}
1251f8558555SMarcel Holtmann 
1252f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1253f8558555SMarcel Holtmann }
1254f8558555SMarcel Holtmann 
1255127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1256392599b9SJohan Hedberg 				    struct hci_conn *conn)
1257392599b9SJohan Hedberg {
1258392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1259392599b9SJohan Hedberg 		return 0;
1260392599b9SJohan Hedberg 
1261765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1262392599b9SJohan Hedberg 		return 0;
1263392599b9SJohan Hedberg 
1264392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1265264b8b4eSJohan Hedberg 	 * devices with sec_level MEDIUM or HIGH or if MITM protection
1266264b8b4eSJohan Hedberg 	 * is requested.
1267264b8b4eSJohan Hedberg 	 */
1268807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1269264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
1270264b8b4eSJohan Hedberg 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
1271392599b9SJohan Hedberg 		return 0;
1272392599b9SJohan Hedberg 
1273392599b9SJohan Hedberg 	return 1;
1274392599b9SJohan Hedberg }
1275392599b9SJohan Hedberg 
12766039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
127700abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
127830dc78e1SJohan Hedberg {
127930dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
128030dc78e1SJohan Hedberg 
128130dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
128230dc78e1SJohan Hedberg 
128330dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
128430dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
128530dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
128630dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
128730dc78e1SJohan Hedberg 
128830dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
128930dc78e1SJohan Hedberg }
129030dc78e1SJohan Hedberg 
1291b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
129230dc78e1SJohan Hedberg {
129330dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
129430dc78e1SJohan Hedberg 	struct inquiry_entry *e;
129530dc78e1SJohan Hedberg 
1296b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1297b644ba33SJohan Hedberg 		return false;
1298b644ba33SJohan Hedberg 
1299b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1300c810089cSRam Malovany 	if (!e)
1301c810089cSRam Malovany 		return false;
1302c810089cSRam Malovany 
1303b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1304b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1305b644ba33SJohan Hedberg 		return true;
1306b644ba33SJohan Hedberg 	}
1307b644ba33SJohan Hedberg 
1308b644ba33SJohan Hedberg 	return false;
1309b644ba33SJohan Hedberg }
1310b644ba33SJohan Hedberg 
1311b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1312b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1313b644ba33SJohan Hedberg {
1314b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1315b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1316b644ba33SJohan Hedberg 
1317b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
131804124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
131904124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1320b644ba33SJohan Hedberg 
1321b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1322b644ba33SJohan Hedberg 		return;
1323b644ba33SJohan Hedberg 
132430dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
132530dc78e1SJohan Hedberg 		goto discov_complete;
132630dc78e1SJohan Hedberg 
132730dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
132830dc78e1SJohan Hedberg 		return;
132930dc78e1SJohan Hedberg 
133030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
13317cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
13327cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
13337cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
13347cc8380eSRam Malovany 	 * Event */
13357cc8380eSRam Malovany 	if (!e)
13367cc8380eSRam Malovany 		return;
13377cc8380eSRam Malovany 
133830dc78e1SJohan Hedberg 	list_del(&e->list);
13397cc8380eSRam Malovany 	if (name) {
13407cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1341b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1342b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1343c3e7c0d9SRam Malovany 	} else {
1344c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
134530dc78e1SJohan Hedberg 	}
134630dc78e1SJohan Hedberg 
1347b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
134830dc78e1SJohan Hedberg 		return;
134930dc78e1SJohan Hedberg 
135030dc78e1SJohan Hedberg discov_complete:
135130dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
135230dc78e1SJohan Hedberg }
135330dc78e1SJohan Hedberg 
1354a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
13551da177e4SLinus Torvalds {
1356127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1357127178d2SJohan Hedberg 	struct hci_conn *conn;
1358127178d2SJohan Hedberg 
13599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1360127178d2SJohan Hedberg 
1361127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1362127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1363127178d2SJohan Hedberg 	if (!status)
1364127178d2SJohan Hedberg 		return;
1365127178d2SJohan Hedberg 
1366127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1367127178d2SJohan Hedberg 	if (!cp)
1368127178d2SJohan Hedberg 		return;
1369127178d2SJohan Hedberg 
1370127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1371127178d2SJohan Hedberg 
1372127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1373b644ba33SJohan Hedberg 
1374b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1375b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1376b644ba33SJohan Hedberg 
137779c6c70cSJohan Hedberg 	if (!conn)
137879c6c70cSJohan Hedberg 		goto unlock;
137979c6c70cSJohan Hedberg 
138079c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
138179c6c70cSJohan Hedberg 		goto unlock;
138279c6c70cSJohan Hedberg 
138351a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1384c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
1385c1f23a2bSJohannes Berg 
1386c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
1387c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1388c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
1389127178d2SJohan Hedberg 	}
1390127178d2SJohan Hedberg 
139179c6c70cSJohan Hedberg unlock:
1392127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1393a9de9248SMarcel Holtmann }
13941da177e4SLinus Torvalds 
1395769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1396769be974SMarcel Holtmann {
1397769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1398769be974SMarcel Holtmann 	struct hci_conn *conn;
1399769be974SMarcel Holtmann 
14009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1401769be974SMarcel Holtmann 
1402769be974SMarcel Holtmann 	if (!status)
1403769be974SMarcel Holtmann 		return;
1404769be974SMarcel Holtmann 
1405769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1406769be974SMarcel Holtmann 	if (!cp)
1407769be974SMarcel Holtmann 		return;
1408769be974SMarcel Holtmann 
1409769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1410769be974SMarcel Holtmann 
1411769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1412769be974SMarcel Holtmann 	if (conn) {
1413769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1414769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
141576a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1416769be974SMarcel Holtmann 		}
1417769be974SMarcel Holtmann 	}
1418769be974SMarcel Holtmann 
1419769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1420769be974SMarcel Holtmann }
1421769be974SMarcel Holtmann 
1422769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1423769be974SMarcel Holtmann {
1424769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1425769be974SMarcel Holtmann 	struct hci_conn *conn;
1426769be974SMarcel Holtmann 
14279f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1428769be974SMarcel Holtmann 
1429769be974SMarcel Holtmann 	if (!status)
1430769be974SMarcel Holtmann 		return;
1431769be974SMarcel Holtmann 
1432769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1433769be974SMarcel Holtmann 	if (!cp)
1434769be974SMarcel Holtmann 		return;
1435769be974SMarcel Holtmann 
1436769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1437769be974SMarcel Holtmann 
1438769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1439769be974SMarcel Holtmann 	if (conn) {
1440769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1441769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
144276a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1443769be974SMarcel Holtmann 		}
1444769be974SMarcel Holtmann 	}
1445769be974SMarcel Holtmann 
1446769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1447769be974SMarcel Holtmann }
1448769be974SMarcel Holtmann 
1449a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1450a9de9248SMarcel Holtmann {
1451b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1452b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1453b6a0dc82SMarcel Holtmann 	__u16 handle;
1454b6a0dc82SMarcel Holtmann 
14559f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1456b6a0dc82SMarcel Holtmann 
1457b6a0dc82SMarcel Holtmann 	if (!status)
1458b6a0dc82SMarcel Holtmann 		return;
1459b6a0dc82SMarcel Holtmann 
1460b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1461b6a0dc82SMarcel Holtmann 	if (!cp)
1462b6a0dc82SMarcel Holtmann 		return;
1463b6a0dc82SMarcel Holtmann 
1464b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1465b6a0dc82SMarcel Holtmann 
14669f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1467b6a0dc82SMarcel Holtmann 
1468b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1469b6a0dc82SMarcel Holtmann 
1470b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14715a08ecceSAndrei Emeltchenko 	if (acl) {
14725a08ecceSAndrei Emeltchenko 		sco = acl->link;
14735a08ecceSAndrei Emeltchenko 		if (sco) {
1474b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1475b6a0dc82SMarcel Holtmann 
1476b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1477b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1478b6a0dc82SMarcel Holtmann 		}
14795a08ecceSAndrei Emeltchenko 	}
1480b6a0dc82SMarcel Holtmann 
1481b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1482a9de9248SMarcel Holtmann }
1483a9de9248SMarcel Holtmann 
1484a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1485a9de9248SMarcel Holtmann {
1486a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
148704837f64SMarcel Holtmann 	struct hci_conn *conn;
148804837f64SMarcel Holtmann 
14899f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1490a9de9248SMarcel Holtmann 
1491a9de9248SMarcel Holtmann 	if (!status)
1492a9de9248SMarcel Holtmann 		return;
1493a9de9248SMarcel Holtmann 
1494a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
149504837f64SMarcel Holtmann 	if (!cp)
1496a9de9248SMarcel Holtmann 		return;
149704837f64SMarcel Holtmann 
149804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
149904837f64SMarcel Holtmann 
150004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1501e73439d8SMarcel Holtmann 	if (conn) {
150251a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
150304837f64SMarcel Holtmann 
150451a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1505e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1506e73439d8SMarcel Holtmann 	}
1507e73439d8SMarcel Holtmann 
150804837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
150904837f64SMarcel Holtmann }
151004837f64SMarcel Holtmann 
1511a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1512a9de9248SMarcel Holtmann {
1513a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
151404837f64SMarcel Holtmann 	struct hci_conn *conn;
151504837f64SMarcel Holtmann 
15169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1517a9de9248SMarcel Holtmann 
1518a9de9248SMarcel Holtmann 	if (!status)
1519a9de9248SMarcel Holtmann 		return;
1520a9de9248SMarcel Holtmann 
1521a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
152204837f64SMarcel Holtmann 	if (!cp)
1523a9de9248SMarcel Holtmann 		return;
152404837f64SMarcel Holtmann 
152504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
152604837f64SMarcel Holtmann 
152704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1528e73439d8SMarcel Holtmann 	if (conn) {
152951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
153004837f64SMarcel Holtmann 
153151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1532e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1533e73439d8SMarcel Holtmann 	}
1534e73439d8SMarcel Holtmann 
153504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
153604837f64SMarcel Holtmann }
153704837f64SMarcel Holtmann 
153888c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
153988c3df13SJohan Hedberg {
154088c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
154188c3df13SJohan Hedberg 	struct hci_conn *conn;
154288c3df13SJohan Hedberg 
154388c3df13SJohan Hedberg 	if (!status)
154488c3df13SJohan Hedberg 		return;
154588c3df13SJohan Hedberg 
154688c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
154788c3df13SJohan Hedberg 	if (!cp)
154888c3df13SJohan Hedberg 		return;
154988c3df13SJohan Hedberg 
155088c3df13SJohan Hedberg 	hci_dev_lock(hdev);
155188c3df13SJohan Hedberg 
155288c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
155388c3df13SJohan Hedberg 	if (conn)
155488c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
155588c3df13SJohan Hedberg 				       conn->dst_type, status);
155688c3df13SJohan Hedberg 
155788c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
155888c3df13SJohan Hedberg }
155988c3df13SJohan Hedberg 
1560a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1561a02226d6SAndrei Emeltchenko {
156293c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
156393c284eeSAndrei Emeltchenko 
1564a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
156593c284eeSAndrei Emeltchenko 
156693c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
156793c284eeSAndrei Emeltchenko 	if (!cp)
156893c284eeSAndrei Emeltchenko 		return;
156993c284eeSAndrei Emeltchenko 
1570e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1571e58917b9SAndrei Emeltchenko 
1572e58917b9SAndrei Emeltchenko 	if (status) {
1573e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1574e58917b9SAndrei Emeltchenko 
1575e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1576e58917b9SAndrei Emeltchenko 		if (hcon)
1577e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1578e58917b9SAndrei Emeltchenko 	} else {
157993c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1580a02226d6SAndrei Emeltchenko 	}
1581a02226d6SAndrei Emeltchenko 
1582e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1583e58917b9SAndrei Emeltchenko }
1584e58917b9SAndrei Emeltchenko 
15850b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
15860b26ab9dSAndrei Emeltchenko {
15870b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
15880b26ab9dSAndrei Emeltchenko 
15890b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15900b26ab9dSAndrei Emeltchenko 
15910b26ab9dSAndrei Emeltchenko 	if (status)
15920b26ab9dSAndrei Emeltchenko 		return;
15930b26ab9dSAndrei Emeltchenko 
15940b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
15950b26ab9dSAndrei Emeltchenko 	if (!cp)
15960b26ab9dSAndrei Emeltchenko 		return;
15970b26ab9dSAndrei Emeltchenko 
15980b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
15990b26ab9dSAndrei Emeltchenko }
16000b26ab9dSAndrei Emeltchenko 
16016039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16021da177e4SLinus Torvalds {
16031da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
160430dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
160530dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16061da177e4SLinus Torvalds 
16079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
16081da177e4SLinus Torvalds 
1609a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
161089352e7dSAndre Guedes 
161189352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
161289352e7dSAndre Guedes 		return;
161389352e7dSAndre Guedes 
16143e13fa1eSAndre Guedes 	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
16153e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
16163e13fa1eSAndre Guedes 
1617a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
161830dc78e1SJohan Hedberg 		return;
161930dc78e1SJohan Hedberg 
162056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
162130dc78e1SJohan Hedberg 
1622343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
162330dc78e1SJohan Hedberg 		goto unlock;
162430dc78e1SJohan Hedberg 
162530dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1626ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
162730dc78e1SJohan Hedberg 		goto unlock;
162830dc78e1SJohan Hedberg 	}
162930dc78e1SJohan Hedberg 
163030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
163130dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
163230dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
163330dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
163430dc78e1SJohan Hedberg 	} else {
163530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
163630dc78e1SJohan Hedberg 	}
163730dc78e1SJohan Hedberg 
163830dc78e1SJohan Hedberg unlock:
163956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
16401da177e4SLinus Torvalds }
16411da177e4SLinus Torvalds 
16426039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
16431da177e4SLinus Torvalds {
164445bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1645a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
16461da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
16471da177e4SLinus Torvalds 
16481da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
16491da177e4SLinus Torvalds 
165045bb4bf0SMarcel Holtmann 	if (!num_rsp)
165145bb4bf0SMarcel Holtmann 		return;
165245bb4bf0SMarcel Holtmann 
16531519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
16541519cc17SAndre Guedes 		return;
16551519cc17SAndre Guedes 
16561da177e4SLinus Torvalds 	hci_dev_lock(hdev);
165745bb4bf0SMarcel Holtmann 
1658e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1659388fc8faSJohan Hedberg 		bool name_known, ssp;
16603175405bSJohan Hedberg 
16611da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
16621da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
16631da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
16641da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
16651da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
16661da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
16671da177e4SLinus Torvalds 		data.rssi		= 0x00;
166841a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
16693175405bSJohan Hedberg 
1670388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
167148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
167204124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
167304124681SGustavo F. Padovan 				  0);
16741da177e4SLinus Torvalds 	}
167545bb4bf0SMarcel Holtmann 
16761da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
16771da177e4SLinus Torvalds }
16781da177e4SLinus Torvalds 
16796039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16801da177e4SLinus Torvalds {
1681a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1682a9de9248SMarcel Holtmann 	struct hci_conn *conn;
16831da177e4SLinus Torvalds 
1684a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
168545bb4bf0SMarcel Holtmann 
16861da177e4SLinus Torvalds 	hci_dev_lock(hdev);
168745bb4bf0SMarcel Holtmann 
1688a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16899499237aSMarcel Holtmann 	if (!conn) {
16909499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16919499237aSMarcel Holtmann 			goto unlock;
16929499237aSMarcel Holtmann 
16939499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1694a9de9248SMarcel Holtmann 		if (!conn)
1695a9de9248SMarcel Holtmann 			goto unlock;
169645bb4bf0SMarcel Holtmann 
16979499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16989499237aSMarcel Holtmann 	}
16999499237aSMarcel Holtmann 
1700a9de9248SMarcel Holtmann 	if (!ev->status) {
1701a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1702769be974SMarcel Holtmann 
1703769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1704769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1705769be974SMarcel Holtmann 			hci_conn_hold(conn);
1706a9ea3ed9SSzymon Janc 
1707a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1708a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1709a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1710a9ea3ed9SSzymon Janc 			else
1711052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1712769be974SMarcel Holtmann 		} else
1713a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1714a9de9248SMarcel Holtmann 
17157d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17167d0db0a3SMarcel Holtmann 
1717a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1718a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1719a9de9248SMarcel Holtmann 
1720a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1721a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1722a9de9248SMarcel Holtmann 
1723a9de9248SMarcel Holtmann 		/* Get remote features */
1724a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1725a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1726a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1727769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1728769be974SMarcel Holtmann 				     sizeof(cp), &cp);
172945bb4bf0SMarcel Holtmann 		}
1730a9de9248SMarcel Holtmann 
1731a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1732d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1733a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1734a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1735a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
173604124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
173704124681SGustavo F. Padovan 				     &cp);
1738a9de9248SMarcel Holtmann 		}
173917d5c04cSJohan Hedberg 	} else {
1740a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
174117d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
174264c7b77cSMarcel Holtmann 			mgmt_connect_failed(hdev, &conn->dst, conn->type,
174348264f06SJohan Hedberg 					    conn->dst_type, ev->status);
174417d5c04cSJohan Hedberg 	}
174545bb4bf0SMarcel Holtmann 
1746e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1747e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
174845bb4bf0SMarcel Holtmann 
1749769be974SMarcel Holtmann 	if (ev->status) {
1750a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1751a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1752c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1753c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1754a9de9248SMarcel Holtmann 
1755a9de9248SMarcel Holtmann unlock:
17561da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1757a9de9248SMarcel Holtmann 
1758a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
17591da177e4SLinus Torvalds }
17601da177e4SLinus Torvalds 
17616039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
17621da177e4SLinus Torvalds {
1763a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
17641da177e4SLinus Torvalds 	int mask = hdev->link_mode;
176520714bfeSFrédéric Dalleau 	__u8 flags = 0;
17661da177e4SLinus Torvalds 
17676ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
1768807deac2SGustavo Padovan 	       ev->link_type);
17691da177e4SLinus Torvalds 
177020714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
177120714bfeSFrédéric Dalleau 				      &flags);
17721da177e4SLinus Torvalds 
1773138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1774b9ee0a78SMarcel Holtmann 	    !hci_blacklist_lookup(hdev, &ev->bdaddr, BDADDR_BREDR)) {
17751da177e4SLinus Torvalds 		/* Connection accepted */
1776c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
17771da177e4SLinus Torvalds 		struct hci_conn *conn;
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1780b6a0dc82SMarcel Holtmann 
1781cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1782cc11b9c1SAndrei Emeltchenko 		if (ie)
1783c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1784c7bdd502SMarcel Holtmann 
17858fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
17868fc9ced3SGustavo Padovan 					       &ev->bdaddr);
17871da177e4SLinus Torvalds 		if (!conn) {
1788cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1789cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1790893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17911da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17921da177e4SLinus Torvalds 				return;
17931da177e4SLinus Torvalds 			}
17941da177e4SLinus Torvalds 		}
1795b6a0dc82SMarcel Holtmann 
17961da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
1797b6a0dc82SMarcel Holtmann 
17981da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17991da177e4SLinus Torvalds 
180020714bfeSFrédéric Dalleau 		if (ev->link_type == ACL_LINK ||
180120714bfeSFrédéric Dalleau 		    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
1802b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
180320714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1804b6a0dc82SMarcel Holtmann 
18051da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
18061da177e4SLinus Torvalds 
18071da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
18081da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
18091da177e4SLinus Torvalds 			else
18101da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
18111da177e4SLinus Torvalds 
181204124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
181304124681SGustavo F. Padovan 				     &cp);
181420714bfeSFrédéric Dalleau 		} else if (!(flags & HCI_PROTO_DEFER)) {
1815b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
181620714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1817b6a0dc82SMarcel Holtmann 
1818b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1819a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1820b6a0dc82SMarcel Holtmann 
182182781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
182282781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
182382781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1824b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1825b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1826b6a0dc82SMarcel Holtmann 
1827b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1828b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
182920714bfeSFrédéric Dalleau 		} else {
183020714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT2;
183120714bfeSFrédéric Dalleau 			hci_proto_connect_cfm(conn, 0);
1832b6a0dc82SMarcel Holtmann 		}
18331da177e4SLinus Torvalds 	} else {
18341da177e4SLinus Torvalds 		/* Connection rejected */
18351da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18361da177e4SLinus Torvalds 
18371da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18389f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1839a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18401da177e4SLinus Torvalds 	}
18411da177e4SLinus Torvalds }
18421da177e4SLinus Torvalds 
1843f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
1844f0d6a0eaSMikel Astiz {
1845f0d6a0eaSMikel Astiz 	switch (err) {
1846f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
1847f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
1848f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
1849f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
1850f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
1851f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
1852f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
1853f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
1854f0d6a0eaSMikel Astiz 	default:
1855f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
1856f0d6a0eaSMikel Astiz 	}
1857f0d6a0eaSMikel Astiz }
1858f0d6a0eaSMikel Astiz 
18596039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18601da177e4SLinus Torvalds {
1861a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
1862abf54a50SAndre Guedes 	u8 reason = hci_to_mgmt_reason(ev->reason);
18639fcb18efSAndre Guedes 	struct hci_conn_params *params;
186404837f64SMarcel Holtmann 	struct hci_conn *conn;
186512d4a3b2SJohan Hedberg 	bool mgmt_connected;
18663846220bSAndre Guedes 	u8 type;
18671da177e4SLinus Torvalds 
18689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
18691da177e4SLinus Torvalds 
18701da177e4SLinus Torvalds 	hci_dev_lock(hdev);
18711da177e4SLinus Torvalds 
187204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1873f7520543SJohan Hedberg 	if (!conn)
1874f7520543SJohan Hedberg 		goto unlock;
1875f7520543SJohan Hedberg 
1876f0d6a0eaSMikel Astiz 	if (ev->status) {
187788c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
187888c3df13SJohan Hedberg 				       conn->dst_type, ev->status);
1879abf54a50SAndre Guedes 		goto unlock;
1880abf54a50SAndre Guedes 	}
1881f0d6a0eaSMikel Astiz 
18823846220bSAndre Guedes 	conn->state = BT_CLOSED;
18833846220bSAndre Guedes 
188412d4a3b2SJohan Hedberg 	mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
188512d4a3b2SJohan Hedberg 	mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
188612d4a3b2SJohan Hedberg 				reason, mgmt_connected);
1887f7520543SJohan Hedberg 
18883846220bSAndre Guedes 	if (conn->type == ACL_LINK && conn->flush_key)
18896ec5bcadSVishal Agarwal 		hci_remove_link_key(hdev, &conn->dst);
18903846220bSAndre Guedes 
18919fcb18efSAndre Guedes 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
18929fcb18efSAndre Guedes 	if (params) {
18939fcb18efSAndre Guedes 		switch (params->auto_connect) {
18949fcb18efSAndre Guedes 		case HCI_AUTO_CONN_LINK_LOSS:
18959fcb18efSAndre Guedes 			if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
18969fcb18efSAndre Guedes 				break;
18979fcb18efSAndre Guedes 			/* Fall through */
18989fcb18efSAndre Guedes 
18999fcb18efSAndre Guedes 		case HCI_AUTO_CONN_ALWAYS:
19009fcb18efSAndre Guedes 			hci_pend_le_conn_add(hdev, &conn->dst, conn->dst_type);
19019fcb18efSAndre Guedes 			break;
19029fcb18efSAndre Guedes 
19039fcb18efSAndre Guedes 		default:
19049fcb18efSAndre Guedes 			break;
19059fcb18efSAndre Guedes 		}
19069fcb18efSAndre Guedes 	}
19079fcb18efSAndre Guedes 
19083846220bSAndre Guedes 	type = conn->type;
19093846220bSAndre Guedes 
19102950f21aSMarcel Holtmann 	hci_proto_disconn_cfm(conn, ev->reason);
19111da177e4SLinus Torvalds 	hci_conn_del(conn);
19122210246cSJohan Hedberg 
19132210246cSJohan Hedberg 	/* Re-enable advertising if necessary, since it might
19142210246cSJohan Hedberg 	 * have been disabled by the connection. From the
19152210246cSJohan Hedberg 	 * HCI_LE_Set_Advertise_Enable command description in
19162210246cSJohan Hedberg 	 * the core specification (v4.0):
19172210246cSJohan Hedberg 	 * "The Controller shall continue advertising until the Host
19182210246cSJohan Hedberg 	 * issues an LE_Set_Advertise_Enable command with
19192210246cSJohan Hedberg 	 * Advertising_Enable set to 0x00 (Advertising is disabled)
19202210246cSJohan Hedberg 	 * or until a connection is created or until the Advertising
19212210246cSJohan Hedberg 	 * is timed out due to Directed Advertising."
19222210246cSJohan Hedberg 	 */
19232210246cSJohan Hedberg 	if (type == LE_LINK)
19245976e608SMarcel Holtmann 		mgmt_reenable_advertising(hdev);
19251da177e4SLinus Torvalds 
1926f7520543SJohan Hedberg unlock:
19271da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19281da177e4SLinus Torvalds }
19291da177e4SLinus Torvalds 
19306039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1931a9de9248SMarcel Holtmann {
1932a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1933a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1934a9de9248SMarcel Holtmann 
19359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1936a9de9248SMarcel Holtmann 
1937a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1938a9de9248SMarcel Holtmann 
1939a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1940d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1941d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1942d7556e20SWaldemar Rymarkiewicz 
1943765c2a96SJohan Hedberg 	if (!ev->status) {
1944aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
194551a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1946d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
194719f8def0SWaldemar Rymarkiewicz 		} else {
1948a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1949765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
195019f8def0SWaldemar Rymarkiewicz 		}
19512a611692SJohan Hedberg 	} else {
1952bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1953bab73cb6SJohan Hedberg 				 ev->status);
19542a611692SJohan Hedberg 	}
1955a9de9248SMarcel Holtmann 
195651a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
195751a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1958a9de9248SMarcel Holtmann 
1959f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1960aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1961f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1962f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1963f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1964d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1965d7556e20SWaldemar Rymarkiewicz 				     &cp);
1966f8558555SMarcel Holtmann 		} else {
1967f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1968f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
196976a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1970f8558555SMarcel Holtmann 		}
1971052b30b0SMarcel Holtmann 	} else {
1972a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1973a9de9248SMarcel Holtmann 
1974052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1975052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
197676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
1977052b30b0SMarcel Holtmann 	}
1978052b30b0SMarcel Holtmann 
197951a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1980a9de9248SMarcel Holtmann 		if (!ev->status) {
1981a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1982f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1983f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1984d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1985d7556e20SWaldemar Rymarkiewicz 				     &cp);
1986a9de9248SMarcel Holtmann 		} else {
198751a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1988a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1989a9de9248SMarcel Holtmann 		}
1990a9de9248SMarcel Holtmann 	}
1991a9de9248SMarcel Holtmann 
1992d7556e20SWaldemar Rymarkiewicz unlock:
1993a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1994a9de9248SMarcel Holtmann }
1995a9de9248SMarcel Holtmann 
19966039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1997a9de9248SMarcel Holtmann {
1998127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1999127178d2SJohan Hedberg 	struct hci_conn *conn;
2000127178d2SJohan Hedberg 
2001a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2002a9de9248SMarcel Holtmann 
2003a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2004127178d2SJohan Hedberg 
2005127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2006127178d2SJohan Hedberg 
2007127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2008b644ba33SJohan Hedberg 
2009b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2010b644ba33SJohan Hedberg 		goto check_auth;
2011b644ba33SJohan Hedberg 
2012b644ba33SJohan Hedberg 	if (ev->status == 0)
2013b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2014b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2015b644ba33SJohan Hedberg 	else
2016b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2017b644ba33SJohan Hedberg 
2018b644ba33SJohan Hedberg check_auth:
201979c6c70cSJohan Hedberg 	if (!conn)
202079c6c70cSJohan Hedberg 		goto unlock;
202179c6c70cSJohan Hedberg 
202279c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
202379c6c70cSJohan Hedberg 		goto unlock;
202479c6c70cSJohan Hedberg 
202551a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2026127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2027127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2028127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2029127178d2SJohan Hedberg 	}
2030127178d2SJohan Hedberg 
203179c6c70cSJohan Hedberg unlock:
2032127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2033a9de9248SMarcel Holtmann }
2034a9de9248SMarcel Holtmann 
20356039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2036a9de9248SMarcel Holtmann {
2037a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2038a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2039a9de9248SMarcel Holtmann 
20409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2041a9de9248SMarcel Holtmann 
2042a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2043a9de9248SMarcel Holtmann 
2044a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2045dc8357ccSMarcel Holtmann 	if (!conn)
2046dc8357ccSMarcel Holtmann 		goto unlock;
2047dc8357ccSMarcel Holtmann 
2048a9de9248SMarcel Holtmann 	if (!ev->status) {
2049ae293196SMarcel Holtmann 		if (ev->encrypt) {
2050ae293196SMarcel Holtmann 			/* Encryption implies authentication */
2051ae293196SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2052a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
2053da85e5e5SVinicius Costa Gomes 			conn->sec_level = conn->pending_sec_level;
2054abf76badSMarcel Holtmann 
2055914a6ffeSMarcel Holtmann 			/* P-256 authentication key implies FIPS */
2056914a6ffeSMarcel Holtmann 			if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
2057914a6ffeSMarcel Holtmann 				conn->link_mode |= HCI_LM_FIPS;
2058914a6ffeSMarcel Holtmann 
2059abf76badSMarcel Holtmann 			if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
2060abf76badSMarcel Holtmann 			    conn->type == LE_LINK)
2061abf76badSMarcel Holtmann 				set_bit(HCI_CONN_AES_CCM, &conn->flags);
2062abf76badSMarcel Holtmann 		} else {
2063a9de9248SMarcel Holtmann 			conn->link_mode &= ~HCI_LM_ENCRYPT;
2064abf76badSMarcel Holtmann 			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
2065abf76badSMarcel Holtmann 		}
2066a9de9248SMarcel Holtmann 	}
2067a9de9248SMarcel Holtmann 
206851a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2069a9de9248SMarcel Holtmann 
2070a7d7723aSGustavo Padovan 	if (ev->status && conn->state == BT_CONNECTED) {
2071bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
207276a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2073a7d7723aSGustavo Padovan 		goto unlock;
2074a7d7723aSGustavo Padovan 	}
2075a7d7723aSGustavo Padovan 
2076f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2077f8558555SMarcel Holtmann 		if (!ev->status)
2078f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2079f8558555SMarcel Holtmann 
2080f8558555SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
208176a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2082f8558555SMarcel Holtmann 	} else
2083a9de9248SMarcel Holtmann 		hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2084a9de9248SMarcel Holtmann 
2085a7d7723aSGustavo Padovan unlock:
2086a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2087a9de9248SMarcel Holtmann }
2088a9de9248SMarcel Holtmann 
20896039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2090807deac2SGustavo Padovan 					     struct sk_buff *skb)
2091a9de9248SMarcel Holtmann {
2092a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2093a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2094a9de9248SMarcel Holtmann 
20959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2096a9de9248SMarcel Holtmann 
2097a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2098a9de9248SMarcel Holtmann 
2099a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2100a9de9248SMarcel Holtmann 	if (conn) {
2101a9de9248SMarcel Holtmann 		if (!ev->status)
2102a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2103a9de9248SMarcel Holtmann 
210451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2105a9de9248SMarcel Holtmann 
2106a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2107a9de9248SMarcel Holtmann 	}
2108a9de9248SMarcel Holtmann 
2109a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2110a9de9248SMarcel Holtmann }
2111a9de9248SMarcel Holtmann 
21126039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2113807deac2SGustavo Padovan 				    struct sk_buff *skb)
2114a9de9248SMarcel Holtmann {
2115a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2116a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2117a9de9248SMarcel Holtmann 
21189f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2119a9de9248SMarcel Holtmann 
2120a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2121a9de9248SMarcel Holtmann 
2122a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2123ccd556feSJohan Hedberg 	if (!conn)
2124ccd556feSJohan Hedberg 		goto unlock;
2125ccd556feSJohan Hedberg 
2126769be974SMarcel Holtmann 	if (!ev->status)
2127cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
2128a9de9248SMarcel Holtmann 
2129ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2130ccd556feSJohan Hedberg 		goto unlock;
2131ccd556feSJohan Hedberg 
2132ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2133769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2134769be974SMarcel Holtmann 		cp.handle = ev->handle;
2135769be974SMarcel Holtmann 		cp.page = 0x01;
2136ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2137769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2138392599b9SJohan Hedberg 		goto unlock;
2139392599b9SJohan Hedberg 	}
2140392599b9SJohan Hedberg 
2141671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2142127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2143127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2144127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2145127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2146127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2147b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2148b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
214908c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2150b644ba33SJohan Hedberg 				      conn->dev_class);
2151392599b9SJohan Hedberg 
2152127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2153769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2154769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
215576a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2156769be974SMarcel Holtmann 	}
2157769be974SMarcel Holtmann 
2158ccd556feSJohan Hedberg unlock:
2159a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2160a9de9248SMarcel Holtmann }
2161a9de9248SMarcel Holtmann 
21626039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2163a9de9248SMarcel Holtmann {
2164a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
21659238f36aSJohan Hedberg 	u8 status = skb->data[sizeof(*ev)];
2166a9de9248SMarcel Holtmann 	__u16 opcode;
2167a9de9248SMarcel Holtmann 
2168a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2169a9de9248SMarcel Holtmann 
2170a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2171a9de9248SMarcel Holtmann 
2172a9de9248SMarcel Holtmann 	switch (opcode) {
2173a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2174a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2175a9de9248SMarcel Holtmann 		break;
2176a9de9248SMarcel Holtmann 
21774d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
21784d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
21794d93483bSAndre Guedes 		break;
21804d93483bSAndre Guedes 
2181a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2182a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2183a9de9248SMarcel Holtmann 		break;
2184a9de9248SMarcel Holtmann 
2185a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2186a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2187a9de9248SMarcel Holtmann 		break;
2188a9de9248SMarcel Holtmann 
2189a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2190a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2191a9de9248SMarcel Holtmann 		break;
2192a9de9248SMarcel Holtmann 
2193e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2194e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2195e4e8e37cSMarcel Holtmann 		break;
2196e4e8e37cSMarcel Holtmann 
2197a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2198a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2199a9de9248SMarcel Holtmann 		break;
2200a9de9248SMarcel Holtmann 
2201e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2202e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2203e4e8e37cSMarcel Holtmann 		break;
2204e4e8e37cSMarcel Holtmann 
2205e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2206e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2207e4e8e37cSMarcel Holtmann 		break;
2208e4e8e37cSMarcel Holtmann 
2209a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2210a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2211a9de9248SMarcel Holtmann 		break;
2212a9de9248SMarcel Holtmann 
2213a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2214a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2215a9de9248SMarcel Holtmann 		break;
2216a9de9248SMarcel Holtmann 
2217a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2218a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2219a9de9248SMarcel Holtmann 		break;
2220a9de9248SMarcel Holtmann 
2221a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2222a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2223a9de9248SMarcel Holtmann 		break;
2224a9de9248SMarcel Holtmann 
2225a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2226a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2227a9de9248SMarcel Holtmann 		break;
2228a9de9248SMarcel Holtmann 
2229a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2230a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2231a9de9248SMarcel Holtmann 		break;
2232a9de9248SMarcel Holtmann 
2233a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2234a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2235a9de9248SMarcel Holtmann 		break;
2236a9de9248SMarcel Holtmann 
2237a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2238a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2239a9de9248SMarcel Holtmann 		break;
2240a9de9248SMarcel Holtmann 
2241a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2242a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2243a9de9248SMarcel Holtmann 		break;
2244a9de9248SMarcel Holtmann 
2245a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2246a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2247a9de9248SMarcel Holtmann 		break;
2248a9de9248SMarcel Holtmann 
2249b4cb9fb2SMarcel Holtmann 	case HCI_OP_READ_NUM_SUPPORTED_IAC:
2250b4cb9fb2SMarcel Holtmann 		hci_cc_read_num_supported_iac(hdev, skb);
2251b4cb9fb2SMarcel Holtmann 		break;
2252b4cb9fb2SMarcel Holtmann 
2253333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2254333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2255333140b5SMarcel Holtmann 		break;
2256333140b5SMarcel Holtmann 
2257eac83dc6SMarcel Holtmann 	case HCI_OP_WRITE_SC_SUPPORT:
2258eac83dc6SMarcel Holtmann 		hci_cc_write_sc_support(hdev, skb);
2259eac83dc6SMarcel Holtmann 		break;
2260eac83dc6SMarcel Holtmann 
2261a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2262a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2263a9de9248SMarcel Holtmann 		break;
2264a9de9248SMarcel Holtmann 
2265a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2266a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2267a9de9248SMarcel Holtmann 		break;
2268a9de9248SMarcel Holtmann 
2269a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2270a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2271a9de9248SMarcel Holtmann 		break;
2272a9de9248SMarcel Holtmann 
2273971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2274971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2275971e3a4bSAndre Guedes 		break;
2276971e3a4bSAndre Guedes 
2277a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2278a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2279a9de9248SMarcel Holtmann 		break;
2280a9de9248SMarcel Holtmann 
2281a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2282a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2283a9de9248SMarcel Holtmann 		break;
2284a9de9248SMarcel Holtmann 
2285f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2286f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
2287f332ec66SJohan Hedberg 		break;
2288f332ec66SJohan Hedberg 
22894a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
22904a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
22914a3ee763SJohan Hedberg 		break;
22924a3ee763SJohan Hedberg 
2293f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
2294f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
2295f332ec66SJohan Hedberg 		break;
2296f332ec66SJohan Hedberg 
22974a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
22984a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
22994a3ee763SJohan Hedberg 		break;
23004a3ee763SJohan Hedberg 
2301350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2302350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2303350ee4cfSAndrei Emeltchenko 		break;
2304350ee4cfSAndrei Emeltchenko 
23051e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
23061e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
23071e89cffbSAndrei Emeltchenko 		break;
23081e89cffbSAndrei Emeltchenko 
2309928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2310928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2311928abaa7SAndrei Emeltchenko 		break;
2312928abaa7SAndrei Emeltchenko 
2313903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2314903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2315903e4541SAndrei Emeltchenko 		break;
2316903e4541SAndrei Emeltchenko 
2317d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2318d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2319d5859e22SJohan Hedberg 		break;
2320d5859e22SJohan Hedberg 
2321980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2322980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2323980e1a53SJohan Hedberg 		break;
2324980e1a53SJohan Hedberg 
2325980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2326980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2327980e1a53SJohan Hedberg 		break;
2328980e1a53SJohan Hedberg 
2329c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
23304d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_data(hdev, skb);
23314d2d2796SMarcel Holtmann 		break;
23324d2d2796SMarcel Holtmann 
23334d2d2796SMarcel Holtmann 	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
23344d2d2796SMarcel Holtmann 		hci_cc_read_local_oob_ext_data(hdev, skb);
2335c35938b2SSzymon Janc 		break;
2336c35938b2SSzymon Janc 
23376ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
23386ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
23396ed58ec5SVille Tervo 		break;
23406ed58ec5SVille Tervo 
234160e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
234260e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
234360e77321SJohan Hedberg 		break;
234460e77321SJohan Hedberg 
23458fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
23468fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
23478fa19098SJohan Hedberg 		break;
23488fa19098SJohan Hedberg 
2349a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2350a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2351a5c29683SJohan Hedberg 		break;
2352a5c29683SJohan Hedberg 
2353a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2354a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2355a5c29683SJohan Hedberg 		break;
2356a5c29683SJohan Hedberg 
23571143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
23581143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
23591143d458SBrian Gix 		break;
23601143d458SBrian Gix 
23611143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23621143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
236316cde993SSzymon Janc 		break;
236407f7fa5dSAndre Guedes 
23657a4cd51dSMarcel Holtmann 	case HCI_OP_LE_SET_RANDOM_ADDR:
23667a4cd51dSMarcel Holtmann 		hci_cc_le_set_random_addr(hdev, skb);
23677a4cd51dSMarcel Holtmann 		break;
23687a4cd51dSMarcel Holtmann 
2369c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2370c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2371c1d5dc4aSJohan Hedberg 		break;
2372c1d5dc4aSJohan Hedberg 
2373eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2374eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2375eb9d91f5SAndre Guedes 		break;
2376eb9d91f5SAndre Guedes 
2377cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2378cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2379cf1d081fSJohan Hedberg 		break;
2380cf1d081fSJohan Hedberg 
23819b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
23829b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
23839b008c04SJohan Hedberg 		break;
23849b008c04SJohan Hedberg 
2385f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2386f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2387f9b49306SAndre Guedes 		break;
2388f9b49306SAndre Guedes 
238956ed2cb8SJohan Hedberg 	case HCI_OP_LE_SET_ADV_PARAM:
239056ed2cb8SJohan Hedberg 		hci_cc_set_adv_param(hdev, skb);
239156ed2cb8SJohan Hedberg 		break;
239256ed2cb8SJohan Hedberg 
239393c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
239493c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
239593c284eeSAndrei Emeltchenko 		break;
239693c284eeSAndrei Emeltchenko 
2397a9de9248SMarcel Holtmann 	default:
23989f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2399a9de9248SMarcel Holtmann 		break;
2400a9de9248SMarcel Holtmann 	}
2401a9de9248SMarcel Holtmann 
2402ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
24036bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24046bd32326SVille Tervo 
2405ad82cdd1SJohan Hedberg 	hci_req_cmd_complete(hdev, opcode, status);
24069238f36aSJohan Hedberg 
2407dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2408a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2409a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2410c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2411a9de9248SMarcel Holtmann 	}
2412a9de9248SMarcel Holtmann }
2413a9de9248SMarcel Holtmann 
24146039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2415a9de9248SMarcel Holtmann {
2416a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2417a9de9248SMarcel Holtmann 	__u16 opcode;
2418a9de9248SMarcel Holtmann 
2419a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2420a9de9248SMarcel Holtmann 
2421a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2422a9de9248SMarcel Holtmann 
2423a9de9248SMarcel Holtmann 	switch (opcode) {
2424a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2425a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2426a9de9248SMarcel Holtmann 		break;
2427a9de9248SMarcel Holtmann 
2428a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2429a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2430a9de9248SMarcel Holtmann 		break;
2431a9de9248SMarcel Holtmann 
2432a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2433a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2434a9de9248SMarcel Holtmann 		break;
2435a9de9248SMarcel Holtmann 
2436f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2437f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2438f8558555SMarcel Holtmann 		break;
2439f8558555SMarcel Holtmann 
2440f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2441f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2442f8558555SMarcel Holtmann 		break;
2443f8558555SMarcel Holtmann 
2444a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2445a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2446a9de9248SMarcel Holtmann 		break;
2447a9de9248SMarcel Holtmann 
2448769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2449769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2450769be974SMarcel Holtmann 		break;
2451769be974SMarcel Holtmann 
2452769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2453769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2454769be974SMarcel Holtmann 		break;
2455769be974SMarcel Holtmann 
2456a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2457a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2458a9de9248SMarcel Holtmann 		break;
2459a9de9248SMarcel Holtmann 
2460a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2461a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2462a9de9248SMarcel Holtmann 		break;
2463a9de9248SMarcel Holtmann 
2464a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2465a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2466a9de9248SMarcel Holtmann 		break;
2467a9de9248SMarcel Holtmann 
24688962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
246988c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
24708962ee74SJohan Hedberg 		break;
24718962ee74SJohan Hedberg 
2472a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2473a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2474a02226d6SAndrei Emeltchenko 		break;
2475a02226d6SAndrei Emeltchenko 
24760b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
24770b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
24780b26ab9dSAndrei Emeltchenko 		break;
24790b26ab9dSAndrei Emeltchenko 
2480a9de9248SMarcel Holtmann 	default:
24819f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2482a9de9248SMarcel Holtmann 		break;
2483a9de9248SMarcel Holtmann 	}
2484a9de9248SMarcel Holtmann 
2485ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
24866bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24876bd32326SVille Tervo 
248802350a72SJohan Hedberg 	if (ev->status ||
248902350a72SJohan Hedberg 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
249033720450SAndre Guedes 		hci_req_cmd_complete(hdev, opcode, ev->status);
24919238f36aSJohan Hedberg 
249210572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2493a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2494a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2495c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2496a9de9248SMarcel Holtmann 	}
2497a9de9248SMarcel Holtmann }
2498a9de9248SMarcel Holtmann 
24996039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2500a9de9248SMarcel Holtmann {
2501a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2502a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2503a9de9248SMarcel Holtmann 
25049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2505a9de9248SMarcel Holtmann 
2506a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2507a9de9248SMarcel Holtmann 
2508a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2509a9de9248SMarcel Holtmann 	if (conn) {
2510a9de9248SMarcel Holtmann 		if (!ev->status) {
2511a9de9248SMarcel Holtmann 			if (ev->role)
2512a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2513a9de9248SMarcel Holtmann 			else
2514a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2515a9de9248SMarcel Holtmann 		}
2516a9de9248SMarcel Holtmann 
251751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2518a9de9248SMarcel Holtmann 
2519a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2520a9de9248SMarcel Holtmann 	}
2521a9de9248SMarcel Holtmann 
2522a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2523a9de9248SMarcel Holtmann }
2524a9de9248SMarcel Holtmann 
25256039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
25261da177e4SLinus Torvalds {
2527a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
25281da177e4SLinus Torvalds 	int i;
25291da177e4SLinus Torvalds 
253032ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
253132ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
253232ac5b9bSAndrei Emeltchenko 		return;
253332ac5b9bSAndrei Emeltchenko 	}
253432ac5b9bSAndrei Emeltchenko 
2535c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2536c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
25371da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
25381da177e4SLinus Torvalds 		return;
25391da177e4SLinus Torvalds 	}
25401da177e4SLinus Torvalds 
2541c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2542c5993de8SAndrei Emeltchenko 
2543613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2544613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
25451da177e4SLinus Torvalds 		struct hci_conn *conn;
25461da177e4SLinus Torvalds 		__u16  handle, count;
25471da177e4SLinus Torvalds 
2548613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2549613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
25501da177e4SLinus Torvalds 
25511da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2552f4280918SAndrei Emeltchenko 		if (!conn)
2553f4280918SAndrei Emeltchenko 			continue;
2554f4280918SAndrei Emeltchenko 
25551da177e4SLinus Torvalds 		conn->sent -= count;
25561da177e4SLinus Torvalds 
2557f4280918SAndrei Emeltchenko 		switch (conn->type) {
2558f4280918SAndrei Emeltchenko 		case ACL_LINK:
255970f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
256070f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
25611da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2562f4280918SAndrei Emeltchenko 			break;
2563f4280918SAndrei Emeltchenko 
2564f4280918SAndrei Emeltchenko 		case LE_LINK:
25656ed58ec5SVille Tervo 			if (hdev->le_pkts) {
25666ed58ec5SVille Tervo 				hdev->le_cnt += count;
25676ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
25686ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
25696ed58ec5SVille Tervo 			} else {
25706ed58ec5SVille Tervo 				hdev->acl_cnt += count;
25716ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
25726ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
25736ed58ec5SVille Tervo 			}
2574f4280918SAndrei Emeltchenko 			break;
2575f4280918SAndrei Emeltchenko 
2576f4280918SAndrei Emeltchenko 		case SCO_LINK:
257770f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
257870f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
25795b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2580f4280918SAndrei Emeltchenko 			break;
2581f4280918SAndrei Emeltchenko 
2582f4280918SAndrei Emeltchenko 		default:
2583f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2584f4280918SAndrei Emeltchenko 			break;
25851da177e4SLinus Torvalds 		}
25861da177e4SLinus Torvalds 	}
2587a9de9248SMarcel Holtmann 
25883eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25891da177e4SLinus Torvalds }
25901da177e4SLinus Torvalds 
259176ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
259276ef7cf7SAndrei Emeltchenko 						 __u16 handle)
259376ef7cf7SAndrei Emeltchenko {
259476ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
259576ef7cf7SAndrei Emeltchenko 
259676ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
259776ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
259876ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
259976ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
260076ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
260176ef7cf7SAndrei Emeltchenko 		if (chan)
260276ef7cf7SAndrei Emeltchenko 			return chan->conn;
260376ef7cf7SAndrei Emeltchenko 		break;
260476ef7cf7SAndrei Emeltchenko 	default:
260576ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
260676ef7cf7SAndrei Emeltchenko 		break;
260776ef7cf7SAndrei Emeltchenko 	}
260876ef7cf7SAndrei Emeltchenko 
260976ef7cf7SAndrei Emeltchenko 	return NULL;
261076ef7cf7SAndrei Emeltchenko }
261176ef7cf7SAndrei Emeltchenko 
26126039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
261325e89e99SAndrei Emeltchenko {
261425e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
261525e89e99SAndrei Emeltchenko 	int i;
261625e89e99SAndrei Emeltchenko 
261725e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
261825e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
261925e89e99SAndrei Emeltchenko 		return;
262025e89e99SAndrei Emeltchenko 	}
262125e89e99SAndrei Emeltchenko 
262225e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
262325e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
262425e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
262525e89e99SAndrei Emeltchenko 		return;
262625e89e99SAndrei Emeltchenko 	}
262725e89e99SAndrei Emeltchenko 
262825e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
262925e89e99SAndrei Emeltchenko 	       ev->num_hndl);
263025e89e99SAndrei Emeltchenko 
263125e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
263225e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
263376ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
263425e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
263525e89e99SAndrei Emeltchenko 
263625e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
263725e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
263825e89e99SAndrei Emeltchenko 
263976ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
264025e89e99SAndrei Emeltchenko 		if (!conn)
264125e89e99SAndrei Emeltchenko 			continue;
264225e89e99SAndrei Emeltchenko 
264325e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
264425e89e99SAndrei Emeltchenko 
264525e89e99SAndrei Emeltchenko 		switch (conn->type) {
264625e89e99SAndrei Emeltchenko 		case ACL_LINK:
2647bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
264825e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
264925e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
265025e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
265125e89e99SAndrei Emeltchenko 			break;
265225e89e99SAndrei Emeltchenko 
265325e89e99SAndrei Emeltchenko 		default:
265425e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
265525e89e99SAndrei Emeltchenko 			break;
265625e89e99SAndrei Emeltchenko 		}
265725e89e99SAndrei Emeltchenko 	}
265825e89e99SAndrei Emeltchenko 
265925e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
266025e89e99SAndrei Emeltchenko }
266125e89e99SAndrei Emeltchenko 
26626039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
26631da177e4SLinus Torvalds {
2664a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
266504837f64SMarcel Holtmann 	struct hci_conn *conn;
26661da177e4SLinus Torvalds 
26679f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
26681da177e4SLinus Torvalds 
26691da177e4SLinus Torvalds 	hci_dev_lock(hdev);
26701da177e4SLinus Torvalds 
267104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
267204837f64SMarcel Holtmann 	if (conn) {
267304837f64SMarcel Holtmann 		conn->mode = ev->mode;
267404837f64SMarcel Holtmann 
26758fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
26768fc9ced3SGustavo Padovan 					&conn->flags)) {
267704837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
267858a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
267904837f64SMarcel Holtmann 			else
268058a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
268104837f64SMarcel Holtmann 		}
2682e73439d8SMarcel Holtmann 
268351a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2684e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
268504837f64SMarcel Holtmann 	}
268604837f64SMarcel Holtmann 
268704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
268804837f64SMarcel Holtmann }
268904837f64SMarcel Holtmann 
26906039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26911da177e4SLinus Torvalds {
2692052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2693052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2694052b30b0SMarcel Holtmann 
2695a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2696052b30b0SMarcel Holtmann 
2697052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2698052b30b0SMarcel Holtmann 
2699052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2700b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2701b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2702b6f98044SWaldemar Rymarkiewicz 
2703b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2704052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2705052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
270676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2707052b30b0SMarcel Holtmann 	}
2708052b30b0SMarcel Holtmann 
2709a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
271003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
271103b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2712a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2713a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2714a770bb5aSWaldemar Rymarkiewicz 
2715a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2716a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2717a770bb5aSWaldemar Rymarkiewicz 		else
2718a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2719a770bb5aSWaldemar Rymarkiewicz 
2720744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2721a770bb5aSWaldemar Rymarkiewicz 	}
2722980e1a53SJohan Hedberg 
2723b6f98044SWaldemar Rymarkiewicz unlock:
2724052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27251da177e4SLinus Torvalds }
27261da177e4SLinus Torvalds 
27276039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
27281da177e4SLinus Torvalds {
272955ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
273055ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
273155ed8ca1SJohan Hedberg 	struct hci_conn *conn;
273255ed8ca1SJohan Hedberg 	struct link_key *key;
273355ed8ca1SJohan Hedberg 
2734a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
273555ed8ca1SJohan Hedberg 
2736034cbea0SAndrei Emeltchenko 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
273755ed8ca1SJohan Hedberg 		return;
273855ed8ca1SJohan Hedberg 
273955ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
274055ed8ca1SJohan Hedberg 
274155ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
274255ed8ca1SJohan Hedberg 	if (!key) {
27436ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
27446ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
274555ed8ca1SJohan Hedberg 		goto not_found;
274655ed8ca1SJohan Hedberg 	}
274755ed8ca1SJohan Hedberg 
27486ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
27496ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
275055ed8ca1SJohan Hedberg 
2751a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2752b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
275355ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
275455ed8ca1SJohan Hedberg 		goto not_found;
275555ed8ca1SJohan Hedberg 	}
275655ed8ca1SJohan Hedberg 
275755ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
275860b83f57SWaldemar Rymarkiewicz 	if (conn) {
275966138ce8SMarcel Holtmann 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
276066138ce8SMarcel Holtmann 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
2761807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
276255ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
276355ed8ca1SJohan Hedberg 			goto not_found;
276455ed8ca1SJohan Hedberg 		}
276555ed8ca1SJohan Hedberg 
276660b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
276760b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
27688fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
27698fc9ced3SGustavo Padovan 			       hdev->name);
277060b83f57SWaldemar Rymarkiewicz 			goto not_found;
277160b83f57SWaldemar Rymarkiewicz 		}
277260b83f57SWaldemar Rymarkiewicz 
277360b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
277460b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
277560b83f57SWaldemar Rymarkiewicz 	}
277660b83f57SWaldemar Rymarkiewicz 
277755ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
27789b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
277955ed8ca1SJohan Hedberg 
278055ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
278155ed8ca1SJohan Hedberg 
278255ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
278355ed8ca1SJohan Hedberg 
278455ed8ca1SJohan Hedberg 	return;
278555ed8ca1SJohan Hedberg 
278655ed8ca1SJohan Hedberg not_found:
278755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
278855ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
27891da177e4SLinus Torvalds }
27901da177e4SLinus Torvalds 
27916039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
27921da177e4SLinus Torvalds {
2793052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2794052b30b0SMarcel Holtmann 	struct hci_conn *conn;
279555ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2796052b30b0SMarcel Holtmann 
2797a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2798052b30b0SMarcel Holtmann 
2799052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2800052b30b0SMarcel Holtmann 
2801052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2802052b30b0SMarcel Holtmann 	if (conn) {
2803052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2804052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2805980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
280613d39315SWaldemar Rymarkiewicz 
280713d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
280813d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
280913d39315SWaldemar Rymarkiewicz 
281076a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2811052b30b0SMarcel Holtmann 	}
2812052b30b0SMarcel Holtmann 
2813034cbea0SAndrei Emeltchenko 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
2814d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
281555ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
281655ed8ca1SJohan Hedberg 
2817052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
28181da177e4SLinus Torvalds }
28191da177e4SLinus Torvalds 
28206039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
282104837f64SMarcel Holtmann {
2822a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
282304837f64SMarcel Holtmann 	struct hci_conn *conn;
282404837f64SMarcel Holtmann 
28259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
282604837f64SMarcel Holtmann 
282704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
282804837f64SMarcel Holtmann 
282904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
28301da177e4SLinus Torvalds 	if (conn && !ev->status) {
28311da177e4SLinus Torvalds 		struct inquiry_entry *ie;
28321da177e4SLinus Torvalds 
2833cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2834cc11b9c1SAndrei Emeltchenko 		if (ie) {
28351da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
28361da177e4SLinus Torvalds 			ie->timestamp = jiffies;
28371da177e4SLinus Torvalds 		}
28381da177e4SLinus Torvalds 	}
28391da177e4SLinus Torvalds 
28401da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
28411da177e4SLinus Torvalds }
28421da177e4SLinus Torvalds 
28436039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2844a8746417SMarcel Holtmann {
2845a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2846a8746417SMarcel Holtmann 	struct hci_conn *conn;
2847a8746417SMarcel Holtmann 
28489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2849a8746417SMarcel Holtmann 
2850a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2851a8746417SMarcel Holtmann 
2852a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2853a8746417SMarcel Holtmann 	if (conn && !ev->status)
2854a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2855a8746417SMarcel Holtmann 
2856a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2857a8746417SMarcel Holtmann }
2858a8746417SMarcel Holtmann 
28596039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
286085a1e930SMarcel Holtmann {
2861a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
286285a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
286385a1e930SMarcel Holtmann 
286485a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
286585a1e930SMarcel Holtmann 
286685a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
286785a1e930SMarcel Holtmann 
2868cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2869cc11b9c1SAndrei Emeltchenko 	if (ie) {
287085a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
287185a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
287285a1e930SMarcel Holtmann 	}
287385a1e930SMarcel Holtmann 
287485a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
287585a1e930SMarcel Holtmann }
287685a1e930SMarcel Holtmann 
28776039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2878807deac2SGustavo Padovan 					     struct sk_buff *skb)
2879a9de9248SMarcel Holtmann {
2880a9de9248SMarcel Holtmann 	struct inquiry_data data;
2881a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2882388fc8faSJohan Hedberg 	bool name_known, ssp;
2883a9de9248SMarcel Holtmann 
2884a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2885a9de9248SMarcel Holtmann 
2886a9de9248SMarcel Holtmann 	if (!num_rsp)
2887a9de9248SMarcel Holtmann 		return;
2888a9de9248SMarcel Holtmann 
28891519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
28901519cc17SAndre Guedes 		return;
28911519cc17SAndre Guedes 
2892a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2893a9de9248SMarcel Holtmann 
2894a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2895138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2896138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2897a9de9248SMarcel Holtmann 
2898e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2899a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2900a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2901a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2902a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2903a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2904a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2905a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
290641a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
29073175405bSJohan Hedberg 
29083175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2909388fc8faSJohan Hedberg 							      false, &ssp);
291048264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2911e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2912388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2913a9de9248SMarcel Holtmann 		}
2914a9de9248SMarcel Holtmann 	} else {
2915a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2916a9de9248SMarcel Holtmann 
2917e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2918a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2919a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2920a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2921a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2922a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2923a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2924a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
292541a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
29263175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2927388fc8faSJohan Hedberg 							      false, &ssp);
292848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2929e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2930388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2931a9de9248SMarcel Holtmann 		}
2932a9de9248SMarcel Holtmann 	}
2933a9de9248SMarcel Holtmann 
2934a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2935a9de9248SMarcel Holtmann }
2936a9de9248SMarcel Holtmann 
29376039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2938807deac2SGustavo Padovan 					struct sk_buff *skb)
2939a9de9248SMarcel Holtmann {
294041a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
294141a96212SMarcel Holtmann 	struct hci_conn *conn;
294241a96212SMarcel Holtmann 
2943a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
294441a96212SMarcel Holtmann 
294541a96212SMarcel Holtmann 	hci_dev_lock(hdev);
294641a96212SMarcel Holtmann 
294741a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2948ccd556feSJohan Hedberg 	if (!conn)
2949ccd556feSJohan Hedberg 		goto unlock;
2950ccd556feSJohan Hedberg 
2951cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
2952cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
2953cad718edSJohan Hedberg 
2954769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
295541a96212SMarcel Holtmann 		struct inquiry_entry *ie;
295641a96212SMarcel Holtmann 
2957cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2958cc11b9c1SAndrei Emeltchenko 		if (ie)
295902b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
296041a96212SMarcel Holtmann 
2961bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
296258a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
2963bbb0eadaSJaganath Kanakkassery 		} else {
2964bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
2965bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
2966bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
2967bbb0eadaSJaganath Kanakkassery 			 * this.
2968bbb0eadaSJaganath Kanakkassery 			 *
2969bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
2970bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
2971bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
2972bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
2973bbb0eadaSJaganath Kanakkassery 		}
2974eb9a8f3fSMarcel Holtmann 
2975eb9a8f3fSMarcel Holtmann 		if (ev->features[0] & LMP_HOST_SC)
2976eb9a8f3fSMarcel Holtmann 			set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
297741a96212SMarcel Holtmann 	}
297841a96212SMarcel Holtmann 
2979ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2980ccd556feSJohan Hedberg 		goto unlock;
2981ccd556feSJohan Hedberg 
2982671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2983127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2984127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2985127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2986127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2987127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2988b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2989b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
299008c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2991b644ba33SJohan Hedberg 				      conn->dev_class);
2992392599b9SJohan Hedberg 
2993127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2994769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2995769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
299676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2997769be974SMarcel Holtmann 	}
2998769be974SMarcel Holtmann 
2999ccd556feSJohan Hedberg unlock:
300041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3001a9de9248SMarcel Holtmann }
3002a9de9248SMarcel Holtmann 
30036039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3004807deac2SGustavo Padovan 				       struct sk_buff *skb)
3005a9de9248SMarcel Holtmann {
3006b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3007b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3008b6a0dc82SMarcel Holtmann 
30099f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3010b6a0dc82SMarcel Holtmann 
3011b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3012b6a0dc82SMarcel Holtmann 
3013b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
30149dc0a3afSMarcel Holtmann 	if (!conn) {
30159dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
30169dc0a3afSMarcel Holtmann 			goto unlock;
30179dc0a3afSMarcel Holtmann 
30189dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3019b6a0dc82SMarcel Holtmann 		if (!conn)
3020b6a0dc82SMarcel Holtmann 			goto unlock;
3021b6a0dc82SMarcel Holtmann 
30229dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
30239dc0a3afSMarcel Holtmann 	}
30249dc0a3afSMarcel Holtmann 
3025732547f9SMarcel Holtmann 	switch (ev->status) {
3026732547f9SMarcel Holtmann 	case 0x00:
3027732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3028732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3029732547f9SMarcel Holtmann 
3030732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3031732547f9SMarcel Holtmann 		break;
3032732547f9SMarcel Holtmann 
30331a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
3034705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3035732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
30361038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3037732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
30382dea632fSFrédéric Dalleau 		if (conn->out) {
3039efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3040efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
30412dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
3042efc7688bSMarcel Holtmann 				goto unlock;
3043efc7688bSMarcel Holtmann 		}
3044732547f9SMarcel Holtmann 		/* fall through */
3045efc7688bSMarcel Holtmann 
3046732547f9SMarcel Holtmann 	default:
3047b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3048732547f9SMarcel Holtmann 		break;
3049732547f9SMarcel Holtmann 	}
3050b6a0dc82SMarcel Holtmann 
3051b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3052b6a0dc82SMarcel Holtmann 	if (ev->status)
3053b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3054b6a0dc82SMarcel Holtmann 
3055b6a0dc82SMarcel Holtmann unlock:
3056b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3057a9de9248SMarcel Holtmann }
3058a9de9248SMarcel Holtmann 
3059efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len)
3060efdcf8e3SMarcel Holtmann {
3061efdcf8e3SMarcel Holtmann 	size_t parsed = 0;
3062efdcf8e3SMarcel Holtmann 
3063efdcf8e3SMarcel Holtmann 	while (parsed < eir_len) {
3064efdcf8e3SMarcel Holtmann 		u8 field_len = eir[0];
3065efdcf8e3SMarcel Holtmann 
3066efdcf8e3SMarcel Holtmann 		if (field_len == 0)
3067efdcf8e3SMarcel Holtmann 			return parsed;
3068efdcf8e3SMarcel Holtmann 
3069efdcf8e3SMarcel Holtmann 		parsed += field_len + 1;
3070efdcf8e3SMarcel Holtmann 		eir += field_len + 1;
3071efdcf8e3SMarcel Holtmann 	}
3072efdcf8e3SMarcel Holtmann 
3073efdcf8e3SMarcel Holtmann 	return eir_len;
3074efdcf8e3SMarcel Holtmann }
3075efdcf8e3SMarcel Holtmann 
30766039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3077807deac2SGustavo Padovan 					    struct sk_buff *skb)
3078a9de9248SMarcel Holtmann {
3079a9de9248SMarcel Holtmann 	struct inquiry_data data;
3080a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3081a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
30829d939d94SVishal Agarwal 	size_t eir_len;
3083a9de9248SMarcel Holtmann 
3084a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3085a9de9248SMarcel Holtmann 
3086a9de9248SMarcel Holtmann 	if (!num_rsp)
3087a9de9248SMarcel Holtmann 		return;
3088a9de9248SMarcel Holtmann 
30891519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30901519cc17SAndre Guedes 		return;
30911519cc17SAndre Guedes 
3092a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3093a9de9248SMarcel Holtmann 
3094e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3095388fc8faSJohan Hedberg 		bool name_known, ssp;
3096561aafbcSJohan Hedberg 
3097a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3098a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3099a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3100a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3101a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3102a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3103a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
310441a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3105561aafbcSJohan Hedberg 
3106a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
31074ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
31084ddb1930SJohan Hedberg 						       sizeof(info->data),
31094ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3110561aafbcSJohan Hedberg 		else
3111561aafbcSJohan Hedberg 			name_known = true;
3112561aafbcSJohan Hedberg 
3113388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3114388fc8faSJohan Hedberg 						      &ssp);
31159d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
311648264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
311704124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
31189d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3119a9de9248SMarcel Holtmann 	}
3120a9de9248SMarcel Holtmann 
3121a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3122a9de9248SMarcel Holtmann }
3123a9de9248SMarcel Holtmann 
31241c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
31251c2e0041SJohan Hedberg 					 struct sk_buff *skb)
31261c2e0041SJohan Hedberg {
31271c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
31281c2e0041SJohan Hedberg 	struct hci_conn *conn;
31291c2e0041SJohan Hedberg 
31309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
31311c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
31321c2e0041SJohan Hedberg 
31331c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
31341c2e0041SJohan Hedberg 
31351c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
31361c2e0041SJohan Hedberg 	if (!conn)
31371c2e0041SJohan Hedberg 		goto unlock;
31381c2e0041SJohan Hedberg 
31391c2e0041SJohan Hedberg 	if (!ev->status)
31401c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
31411c2e0041SJohan Hedberg 
31421c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
31431c2e0041SJohan Hedberg 
31441c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3145bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
314676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
31471c2e0041SJohan Hedberg 		goto unlock;
31481c2e0041SJohan Hedberg 	}
31491c2e0041SJohan Hedberg 
31501c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
31511c2e0041SJohan Hedberg 		if (!ev->status)
31521c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
31531c2e0041SJohan Hedberg 
31541c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
315576a68ba0SDavid Herrmann 		hci_conn_drop(conn);
31561c2e0041SJohan Hedberg 	} else {
31571c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
31581c2e0041SJohan Hedberg 
31591c2e0041SJohan Hedberg 		hci_conn_hold(conn);
31601c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
316176a68ba0SDavid Herrmann 		hci_conn_drop(conn);
31621c2e0041SJohan Hedberg 	}
31631c2e0041SJohan Hedberg 
31641c2e0041SJohan Hedberg unlock:
31651c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
31661c2e0041SJohan Hedberg }
31671c2e0041SJohan Hedberg 
31686039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
316917fa4b9dSJohan Hedberg {
317017fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
3171acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_DEDICATED_BONDING ||
3172acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_DEDICATED_BONDING_MITM) {
317317fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
317417fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
3175acabae96SMikel Astiz 		if (conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT ||
3176acabae96SMikel Astiz 		    conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)
3177acabae96SMikel Astiz 			return HCI_AT_DEDICATED_BONDING;
317817fa4b9dSJohan Hedberg 		else
3179acabae96SMikel Astiz 			return HCI_AT_DEDICATED_BONDING_MITM;
318017fa4b9dSJohan Hedberg 	}
318117fa4b9dSJohan Hedberg 
318217fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
3183acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
3184acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
318558797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
318617fa4b9dSJohan Hedberg 
318717fa4b9dSJohan Hedberg 	return conn->auth_type;
318817fa4b9dSJohan Hedberg }
318917fa4b9dSJohan Hedberg 
31906039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
31910493684eSMarcel Holtmann {
31920493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
31930493684eSMarcel Holtmann 	struct hci_conn *conn;
31940493684eSMarcel Holtmann 
31950493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31960493684eSMarcel Holtmann 
31970493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31980493684eSMarcel Holtmann 
31990493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
320003b555e1SJohan Hedberg 	if (!conn)
320103b555e1SJohan Hedberg 		goto unlock;
320203b555e1SJohan Hedberg 
32030493684eSMarcel Holtmann 	hci_conn_hold(conn);
32040493684eSMarcel Holtmann 
3205a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
320603b555e1SJohan Hedberg 		goto unlock;
320703b555e1SJohan Hedberg 
3208a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
320903b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
321017fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
321117fa4b9dSJohan Hedberg 
321217fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
32137a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
32147a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
32157a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
3216a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
32177cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
32187cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
321917fa4b9dSJohan Hedberg 
32208fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
32218fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3222ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3223ce85ee13SSzymon Janc 		else
3224ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3225ce85ee13SSzymon Janc 
322617fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
322717fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
322803b555e1SJohan Hedberg 	} else {
322903b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
323003b555e1SJohan Hedberg 
323103b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
32329f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
323303b555e1SJohan Hedberg 
323403b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
323503b555e1SJohan Hedberg 			     sizeof(cp), &cp);
323603b555e1SJohan Hedberg 	}
323703b555e1SJohan Hedberg 
323803b555e1SJohan Hedberg unlock:
323903b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
324003b555e1SJohan Hedberg }
324103b555e1SJohan Hedberg 
32426039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
324303b555e1SJohan Hedberg {
324403b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
324503b555e1SJohan Hedberg 	struct hci_conn *conn;
324603b555e1SJohan Hedberg 
324703b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
324803b555e1SJohan Hedberg 
324903b555e1SJohan Hedberg 	hci_dev_lock(hdev);
325003b555e1SJohan Hedberg 
325103b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
325203b555e1SJohan Hedberg 	if (!conn)
325303b555e1SJohan Hedberg 		goto unlock;
325403b555e1SJohan Hedberg 
325503b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
325603b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
325758a681efSJohan Hedberg 	if (ev->oob_data)
325858a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
325903b555e1SJohan Hedberg 
326003b555e1SJohan Hedberg unlock:
32610493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32620493684eSMarcel Holtmann }
32630493684eSMarcel Holtmann 
32646039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3265a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3266a5c29683SJohan Hedberg {
3267a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
326855bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
32697a828908SJohan Hedberg 	struct hci_conn *conn;
3270a5c29683SJohan Hedberg 
3271a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3272a5c29683SJohan Hedberg 
3273a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3274a5c29683SJohan Hedberg 
3275a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
32767a828908SJohan Hedberg 		goto unlock;
32777a828908SJohan Hedberg 
32787a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32797a828908SJohan Hedberg 	if (!conn)
32807a828908SJohan Hedberg 		goto unlock;
32817a828908SJohan Hedberg 
32827a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
32837a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
32847a828908SJohan Hedberg 
32857a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
32867a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
32877a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
32887a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
32897a828908SJohan Hedberg 	 * bit set. */
3290a767631aSMikel Astiz 	if (!conn->connect_cfm_cb && loc_mitm &&
3291a767631aSMikel Astiz 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
32927a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
32937a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
32947a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
32957a828908SJohan Hedberg 		goto unlock;
32967a828908SJohan Hedberg 	}
32977a828908SJohan Hedberg 
32987a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
3299a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
3300a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
330155bc1a37SJohan Hedberg 
330255bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
330355bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
330455bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
330551a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
330655bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
330755bc1a37SJohan Hedberg 			confirm_hint = 1;
330855bc1a37SJohan Hedberg 			goto confirm;
330955bc1a37SJohan Hedberg 		}
331055bc1a37SJohan Hedberg 
33119f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
33129f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
33139f61656aSJohan Hedberg 
33149f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
33159f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
33167bc18d9dSJohan Hedberg 			queue_delayed_work(conn->hdev->workqueue,
33177bc18d9dSJohan Hedberg 					   &conn->auto_accept_work, delay);
33189f61656aSJohan Hedberg 			goto unlock;
33199f61656aSJohan Hedberg 		}
33209f61656aSJohan Hedberg 
33217a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
33227a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
33237a828908SJohan Hedberg 		goto unlock;
33247a828908SJohan Hedberg 	}
33257a828908SJohan Hedberg 
332655bc1a37SJohan Hedberg confirm:
3327272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
332855bc1a37SJohan Hedberg 				  confirm_hint);
3329a5c29683SJohan Hedberg 
33307a828908SJohan Hedberg unlock:
3331a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3332a5c29683SJohan Hedberg }
3333a5c29683SJohan Hedberg 
33346039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
33351143d458SBrian Gix 					 struct sk_buff *skb)
33361143d458SBrian Gix {
33371143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
33381143d458SBrian Gix 
33391143d458SBrian Gix 	BT_DBG("%s", hdev->name);
33401143d458SBrian Gix 
3341a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3342272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
33431143d458SBrian Gix }
33441143d458SBrian Gix 
334592a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
334692a25256SJohan Hedberg 					struct sk_buff *skb)
334792a25256SJohan Hedberg {
334892a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
334992a25256SJohan Hedberg 	struct hci_conn *conn;
335092a25256SJohan Hedberg 
335192a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
335292a25256SJohan Hedberg 
335392a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
335492a25256SJohan Hedberg 	if (!conn)
335592a25256SJohan Hedberg 		return;
335692a25256SJohan Hedberg 
335792a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
335892a25256SJohan Hedberg 	conn->passkey_entered = 0;
335992a25256SJohan Hedberg 
336092a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
336192a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
336292a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
336392a25256SJohan Hedberg 					 conn->passkey_entered);
336492a25256SJohan Hedberg }
336592a25256SJohan Hedberg 
336692a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
336792a25256SJohan Hedberg {
336892a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
336992a25256SJohan Hedberg 	struct hci_conn *conn;
337092a25256SJohan Hedberg 
337192a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
337292a25256SJohan Hedberg 
337392a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
337492a25256SJohan Hedberg 	if (!conn)
337592a25256SJohan Hedberg 		return;
337692a25256SJohan Hedberg 
337792a25256SJohan Hedberg 	switch (ev->type) {
337892a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
337992a25256SJohan Hedberg 		conn->passkey_entered = 0;
338092a25256SJohan Hedberg 		return;
338192a25256SJohan Hedberg 
338292a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
338392a25256SJohan Hedberg 		conn->passkey_entered++;
338492a25256SJohan Hedberg 		break;
338592a25256SJohan Hedberg 
338692a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
338792a25256SJohan Hedberg 		conn->passkey_entered--;
338892a25256SJohan Hedberg 		break;
338992a25256SJohan Hedberg 
339092a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
339192a25256SJohan Hedberg 		conn->passkey_entered = 0;
339292a25256SJohan Hedberg 		break;
339392a25256SJohan Hedberg 
339492a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
339592a25256SJohan Hedberg 		return;
339692a25256SJohan Hedberg 	}
339792a25256SJohan Hedberg 
339892a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
339992a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
340092a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
340192a25256SJohan Hedberg 					 conn->passkey_entered);
340292a25256SJohan Hedberg }
340392a25256SJohan Hedberg 
34046039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3405807deac2SGustavo Padovan 					 struct sk_buff *skb)
34060493684eSMarcel Holtmann {
34070493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
34080493684eSMarcel Holtmann 	struct hci_conn *conn;
34090493684eSMarcel Holtmann 
34100493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
34110493684eSMarcel Holtmann 
34120493684eSMarcel Holtmann 	hci_dev_lock(hdev);
34130493684eSMarcel Holtmann 
34140493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
34152a611692SJohan Hedberg 	if (!conn)
34162a611692SJohan Hedberg 		goto unlock;
34172a611692SJohan Hedberg 
34182a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
34192a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
34202a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
34212a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
34222a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3423fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3424bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3425bab73cb6SJohan Hedberg 				 ev->status);
34262a611692SJohan Hedberg 
342776a68ba0SDavid Herrmann 	hci_conn_drop(conn);
34280493684eSMarcel Holtmann 
34292a611692SJohan Hedberg unlock:
34300493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
34310493684eSMarcel Holtmann }
34320493684eSMarcel Holtmann 
34336039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3434807deac2SGustavo Padovan 					 struct sk_buff *skb)
343541a96212SMarcel Holtmann {
343641a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
343741a96212SMarcel Holtmann 	struct inquiry_entry *ie;
3438cad718edSJohan Hedberg 	struct hci_conn *conn;
343941a96212SMarcel Holtmann 
344041a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
344141a96212SMarcel Holtmann 
344241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
344341a96212SMarcel Holtmann 
3444cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3445cad718edSJohan Hedberg 	if (conn)
3446cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
3447cad718edSJohan Hedberg 
3448cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3449cc11b9c1SAndrei Emeltchenko 	if (ie)
345002b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
345141a96212SMarcel Holtmann 
345241a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
345341a96212SMarcel Holtmann }
345441a96212SMarcel Holtmann 
34556039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
34562763eda6SSzymon Janc 					    struct sk_buff *skb)
34572763eda6SSzymon Janc {
34582763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
34592763eda6SSzymon Janc 	struct oob_data *data;
34602763eda6SSzymon Janc 
34612763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
34622763eda6SSzymon Janc 
34632763eda6SSzymon Janc 	hci_dev_lock(hdev);
34642763eda6SSzymon Janc 
3465a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3466e1ba1f15SSzymon Janc 		goto unlock;
3467e1ba1f15SSzymon Janc 
34682763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
34692763eda6SSzymon Janc 	if (data) {
3470519ca9d0SMarcel Holtmann 		if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
3471519ca9d0SMarcel Holtmann 			struct hci_cp_remote_oob_ext_data_reply cp;
3472519ca9d0SMarcel Holtmann 
3473519ca9d0SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
3474519ca9d0SMarcel Holtmann 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
3475519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer192, data->randomizer192,
3476519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer192));
3477519ca9d0SMarcel Holtmann 			memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
3478519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer256, data->randomizer256,
3479519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer256));
3480519ca9d0SMarcel Holtmann 
3481519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
3482519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3483519ca9d0SMarcel Holtmann 		} else {
34842763eda6SSzymon Janc 			struct hci_cp_remote_oob_data_reply cp;
34852763eda6SSzymon Janc 
34862763eda6SSzymon Janc 			bacpy(&cp.bdaddr, &ev->bdaddr);
3487519ca9d0SMarcel Holtmann 			memcpy(cp.hash, data->hash192, sizeof(cp.hash));
3488519ca9d0SMarcel Holtmann 			memcpy(cp.randomizer, data->randomizer192,
3489519ca9d0SMarcel Holtmann 			       sizeof(cp.randomizer));
34902763eda6SSzymon Janc 
3491519ca9d0SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
3492519ca9d0SMarcel Holtmann 				     sizeof(cp), &cp);
3493519ca9d0SMarcel Holtmann 		}
34942763eda6SSzymon Janc 	} else {
34952763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
34962763eda6SSzymon Janc 
34972763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
3498519ca9d0SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
3499519ca9d0SMarcel Holtmann 			     sizeof(cp), &cp);
35002763eda6SSzymon Janc 	}
35012763eda6SSzymon Janc 
3502e1ba1f15SSzymon Janc unlock:
35032763eda6SSzymon Janc 	hci_dev_unlock(hdev);
35042763eda6SSzymon Janc }
35052763eda6SSzymon Janc 
3506d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3507d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3508d5e91192SAndrei Emeltchenko {
3509d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3510d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3511d5e91192SAndrei Emeltchenko 
3512d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3513d5e91192SAndrei Emeltchenko 	       ev->status);
3514d5e91192SAndrei Emeltchenko 
3515d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3516d5e91192SAndrei Emeltchenko 
3517d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3518d5e91192SAndrei Emeltchenko 	if (!hcon) {
3519d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3520d5e91192SAndrei Emeltchenko 		return;
3521d5e91192SAndrei Emeltchenko 	}
3522d5e91192SAndrei Emeltchenko 
3523d5e91192SAndrei Emeltchenko 	if (ev->status) {
3524d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3525d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3526d5e91192SAndrei Emeltchenko 		return;
3527d5e91192SAndrei Emeltchenko 	}
3528d5e91192SAndrei Emeltchenko 
3529d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3530d5e91192SAndrei Emeltchenko 
3531d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3532d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3533d5e91192SAndrei Emeltchenko 
3534d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3535d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
353676a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
3537d5e91192SAndrei Emeltchenko 
3538d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3539d5e91192SAndrei Emeltchenko 
3540cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
3541cf70ff22SAndrei Emeltchenko 
3542d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3543d5e91192SAndrei Emeltchenko }
3544d5e91192SAndrei Emeltchenko 
354527695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
354627695fb4SAndrei Emeltchenko {
354727695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
354827695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
354927695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
355027695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
355127695fb4SAndrei Emeltchenko 
355227695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
355327695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
355427695fb4SAndrei Emeltchenko 	       ev->status);
355527695fb4SAndrei Emeltchenko 
355627695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
355727695fb4SAndrei Emeltchenko 	if (!hcon)
355827695fb4SAndrei Emeltchenko 		return;
355927695fb4SAndrei Emeltchenko 
356027695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
356127695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
356227695fb4SAndrei Emeltchenko 	if (!hchan)
356327695fb4SAndrei Emeltchenko 		return;
356427695fb4SAndrei Emeltchenko 
356527695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
356627695fb4SAndrei Emeltchenko 
356727695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
356827695fb4SAndrei Emeltchenko 
356927695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
357027695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
357127695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
357227695fb4SAndrei Emeltchenko 
357327695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
357427695fb4SAndrei Emeltchenko 
357527695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
357627695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
357727695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
357827695fb4SAndrei Emeltchenko 
357927695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
358027695fb4SAndrei Emeltchenko 	}
358127695fb4SAndrei Emeltchenko }
358227695fb4SAndrei Emeltchenko 
3583606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3584606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3585606e2a10SAndrei Emeltchenko {
3586606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3587606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3588606e2a10SAndrei Emeltchenko 
3589606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3590606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3591606e2a10SAndrei Emeltchenko 
3592606e2a10SAndrei Emeltchenko 	if (ev->status)
3593606e2a10SAndrei Emeltchenko 		return;
3594606e2a10SAndrei Emeltchenko 
3595606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3596606e2a10SAndrei Emeltchenko 
3597606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3598606e2a10SAndrei Emeltchenko 	if (!hchan)
3599606e2a10SAndrei Emeltchenko 		goto unlock;
3600606e2a10SAndrei Emeltchenko 
3601606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3602606e2a10SAndrei Emeltchenko 
3603606e2a10SAndrei Emeltchenko unlock:
3604606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3605606e2a10SAndrei Emeltchenko }
3606606e2a10SAndrei Emeltchenko 
36079eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
36089eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
36099eef6b3aSAndrei Emeltchenko {
36109eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
36119eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
36129eef6b3aSAndrei Emeltchenko 
36139eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
36149eef6b3aSAndrei Emeltchenko 
36159eef6b3aSAndrei Emeltchenko 	if (ev->status)
36169eef6b3aSAndrei Emeltchenko 		return;
36179eef6b3aSAndrei Emeltchenko 
36189eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
36199eef6b3aSAndrei Emeltchenko 
36209eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
36219eef6b3aSAndrei Emeltchenko 	if (hcon) {
36229eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
36239eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
36249eef6b3aSAndrei Emeltchenko 	}
36259eef6b3aSAndrei Emeltchenko 
36269eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
36279eef6b3aSAndrei Emeltchenko }
36289eef6b3aSAndrei Emeltchenko 
36296039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3630fcd89c09SVille Tervo {
3631fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3632fcd89c09SVille Tervo 	struct hci_conn *conn;
363368d6f6deSJohan Hedberg 	struct smp_irk *irk;
3634fcd89c09SVille Tervo 
36359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3636fcd89c09SVille Tervo 
3637fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3638fcd89c09SVille Tervo 
36394f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3640b62f328bSVille Tervo 	if (!conn) {
3641b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3642b62f328bSVille Tervo 		if (!conn) {
3643b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3644230fd16aSAndre Guedes 			goto unlock;
3645b62f328bSVille Tervo 		}
364629b7988aSAndre Guedes 
364729b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3648b9b343d2SAndre Guedes 
3649880be4e8SMarcel Holtmann 		/* The advertising parameters for own address type
3650880be4e8SMarcel Holtmann 		 * define which source address and source address
3651880be4e8SMarcel Holtmann 		 * type this connections has.
3652880be4e8SMarcel Holtmann 		 */
3653880be4e8SMarcel Holtmann 		if (bacmp(&conn->src, BDADDR_ANY)) {
3654880be4e8SMarcel Holtmann 			conn->src_type = ADDR_LE_DEV_PUBLIC;
3655880be4e8SMarcel Holtmann 		} else {
3656880be4e8SMarcel Holtmann 			bacpy(&conn->src, &hdev->static_addr);
3657880be4e8SMarcel Holtmann 			conn->src_type = ADDR_LE_DEV_RANDOM;
3658880be4e8SMarcel Holtmann 		}
3659880be4e8SMarcel Holtmann 
3660b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3661b9b343d2SAndre Guedes 			conn->out = true;
3662b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3663b9b343d2SAndre Guedes 		}
3664b62f328bSVille Tervo 	}
3665fcd89c09SVille Tervo 
36667be2edbbSJohan Hedberg 	/* Ensure that the hci_conn contains the identity address type
36677be2edbbSJohan Hedberg 	 * regardless of which address the connection was made with.
36687be2edbbSJohan Hedberg 	 */
3669*a1f4c318SJohan Hedberg 	hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
36707be2edbbSJohan Hedberg 
3671edb4b466SMarcel Holtmann 	/* Lookup the identity address from the stored connection
3672edb4b466SMarcel Holtmann 	 * address and address type.
3673edb4b466SMarcel Holtmann 	 *
3674edb4b466SMarcel Holtmann 	 * When establishing connections to an identity address, the
3675edb4b466SMarcel Holtmann 	 * connection procedure will store the resolvable random
3676edb4b466SMarcel Holtmann 	 * address first. Now if it can be converted back into the
3677edb4b466SMarcel Holtmann 	 * identity address, start using the identity address from
3678edb4b466SMarcel Holtmann 	 * now on.
3679edb4b466SMarcel Holtmann 	 */
3680edb4b466SMarcel Holtmann 	irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
368168d6f6deSJohan Hedberg 	if (irk) {
368268d6f6deSJohan Hedberg 		bacpy(&conn->dst, &irk->bdaddr);
368368d6f6deSJohan Hedberg 		conn->dst_type = irk->addr_type;
368468d6f6deSJohan Hedberg 	}
368568d6f6deSJohan Hedberg 
3686cd17decbSAndre Guedes 	if (ev->status) {
368706c053fbSAndre Guedes 		hci_le_conn_failed(conn, ev->status);
3688cd17decbSAndre Guedes 		goto unlock;
3689cd17decbSAndre Guedes 	}
3690cd17decbSAndre Guedes 
3691b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
369201fdb0fcSMarcel Holtmann 		mgmt_device_connected(hdev, &conn->dst, conn->type,
369395b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
369483bc71b4SVinicius Costa Gomes 
36957b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3696fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3697fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3698fcd89c09SVille Tervo 
369918722c24SJukka Rissanen 	if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
370018722c24SJukka Rissanen 		set_bit(HCI_CONN_6LOWPAN, &conn->flags);
370118722c24SJukka Rissanen 
3702fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3703fcd89c09SVille Tervo 
3704fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3705fcd89c09SVille Tervo 
3706a4790dbdSAndre Guedes 	hci_pend_le_conn_del(hdev, &conn->dst, conn->dst_type);
3707a4790dbdSAndre Guedes 
3708fcd89c09SVille Tervo unlock:
3709fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3710fcd89c09SVille Tervo }
3711fcd89c09SVille Tervo 
3712a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */
3713a4790dbdSAndre Guedes static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
3714a4790dbdSAndre Guedes 				  u8 addr_type)
3715a4790dbdSAndre Guedes {
3716a4790dbdSAndre Guedes 	struct hci_conn *conn;
37175b906a84SAndre Guedes 	struct smp_irk *irk;
37185b906a84SAndre Guedes 
37195b906a84SAndre Guedes 	/* If this is a resolvable address, we should resolve it and then
37205b906a84SAndre Guedes 	 * update address and address type variables.
37215b906a84SAndre Guedes 	 */
37225b906a84SAndre Guedes 	irk = hci_get_irk(hdev, addr, addr_type);
37235b906a84SAndre Guedes 	if (irk) {
37245b906a84SAndre Guedes 		addr = &irk->bdaddr;
37255b906a84SAndre Guedes 		addr_type = irk->addr_type;
37265b906a84SAndre Guedes 	}
3727a4790dbdSAndre Guedes 
3728a4790dbdSAndre Guedes 	if (!hci_pend_le_conn_lookup(hdev, addr, addr_type))
3729a4790dbdSAndre Guedes 		return;
3730a4790dbdSAndre Guedes 
3731a4790dbdSAndre Guedes 	conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
3732a4790dbdSAndre Guedes 			      HCI_AT_NO_BONDING);
3733a4790dbdSAndre Guedes 	if (!IS_ERR(conn))
3734a4790dbdSAndre Guedes 		return;
3735a4790dbdSAndre Guedes 
3736a4790dbdSAndre Guedes 	switch (PTR_ERR(conn)) {
3737a4790dbdSAndre Guedes 	case -EBUSY:
3738a4790dbdSAndre Guedes 		/* If hci_connect() returns -EBUSY it means there is already
3739a4790dbdSAndre Guedes 		 * an LE connection attempt going on. Since controllers don't
3740a4790dbdSAndre Guedes 		 * support more than one connection attempt at the time, we
3741a4790dbdSAndre Guedes 		 * don't consider this an error case.
3742a4790dbdSAndre Guedes 		 */
3743a4790dbdSAndre Guedes 		break;
3744a4790dbdSAndre Guedes 	default:
3745a4790dbdSAndre Guedes 		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
3746a4790dbdSAndre Guedes 	}
3747a4790dbdSAndre Guedes }
3748a4790dbdSAndre Guedes 
37496039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
37509aa04c91SAndre Guedes {
3751e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3752e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
37533c9e9195SAndre Guedes 	s8 rssi;
37549aa04c91SAndre Guedes 
3755a4790dbdSAndre Guedes 	hci_dev_lock(hdev);
3756a4790dbdSAndre Guedes 
3757e95beb41SAndre Guedes 	while (num_reports--) {
3758e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3759e95beb41SAndre Guedes 
3760a4790dbdSAndre Guedes 		if (ev->evt_type == LE_ADV_IND ||
3761a4790dbdSAndre Guedes 		    ev->evt_type == LE_ADV_DIRECT_IND)
3762a4790dbdSAndre Guedes 			check_pending_le_conn(hdev, &ev->bdaddr,
3763a4790dbdSAndre Guedes 					      ev->bdaddr_type);
3764a4790dbdSAndre Guedes 
37653c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
37663c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
376704124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
37683c9e9195SAndre Guedes 
3769e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
37709aa04c91SAndre Guedes 	}
3771a4790dbdSAndre Guedes 
3772a4790dbdSAndre Guedes 	hci_dev_unlock(hdev);
37739aa04c91SAndre Guedes }
37749aa04c91SAndre Guedes 
37756039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3776a7a595f6SVinicius Costa Gomes {
3777a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3778a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3779bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3780a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3781c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3782a7a595f6SVinicius Costa Gomes 
37839f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3784a7a595f6SVinicius Costa Gomes 
3785a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3786a7a595f6SVinicius Costa Gomes 
3787a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3788bea710feSVinicius Costa Gomes 	if (conn == NULL)
3789bea710feSVinicius Costa Gomes 		goto not_found;
3790a7a595f6SVinicius Costa Gomes 
379198a0b845SJohan Hedberg 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random, conn->out);
3792bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3793bea710feSVinicius Costa Gomes 		goto not_found;
3794bea710feSVinicius Costa Gomes 
3795bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3796a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3797c9839a11SVinicius Costa Gomes 
3798c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3799f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_HIGH;
3800f8776218SAndre Guedes 	else
3801f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_MEDIUM;
3802a7a595f6SVinicius Costa Gomes 
380389cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
3804a7a595f6SVinicius Costa Gomes 
3805a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3806a7a595f6SVinicius Costa Gomes 
3807c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3808c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3809c9839a11SVinicius Costa Gomes 		kfree(ltk);
3810c9839a11SVinicius Costa Gomes 	}
3811c9839a11SVinicius Costa Gomes 
3812a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3813bea710feSVinicius Costa Gomes 
3814bea710feSVinicius Costa Gomes 	return;
3815bea710feSVinicius Costa Gomes 
3816bea710feSVinicius Costa Gomes not_found:
3817bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3818bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3819bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3820a7a595f6SVinicius Costa Gomes }
3821a7a595f6SVinicius Costa Gomes 
38226039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3823fcd89c09SVille Tervo {
3824fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3825fcd89c09SVille Tervo 
3826fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3827fcd89c09SVille Tervo 
3828fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3829fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3830fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3831fcd89c09SVille Tervo 		break;
3832fcd89c09SVille Tervo 
38339aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
38349aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
38359aa04c91SAndre Guedes 		break;
38369aa04c91SAndre Guedes 
3837a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3838a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3839a7a595f6SVinicius Costa Gomes 		break;
3840a7a595f6SVinicius Costa Gomes 
3841fcd89c09SVille Tervo 	default:
3842fcd89c09SVille Tervo 		break;
3843fcd89c09SVille Tervo 	}
3844fcd89c09SVille Tervo }
3845fcd89c09SVille Tervo 
38469495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
38479495b2eeSAndrei Emeltchenko {
38489495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
38499495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
38509495b2eeSAndrei Emeltchenko 
38519495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
38529495b2eeSAndrei Emeltchenko 
38539495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
38549495b2eeSAndrei Emeltchenko 
38559495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
38569495b2eeSAndrei Emeltchenko 	if (!hcon)
38579495b2eeSAndrei Emeltchenko 		return;
38589495b2eeSAndrei Emeltchenko 
38599495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
38609495b2eeSAndrei Emeltchenko }
38619495b2eeSAndrei Emeltchenko 
38621da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
38631da177e4SLinus Torvalds {
3864a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3865a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
38661da177e4SLinus Torvalds 
3867b6ddb638SJohan Hedberg 	hci_dev_lock(hdev);
3868b6ddb638SJohan Hedberg 
3869b6ddb638SJohan Hedberg 	/* Received events are (currently) only needed when a request is
3870b6ddb638SJohan Hedberg 	 * ongoing so avoid unnecessary memory allocation.
3871b6ddb638SJohan Hedberg 	 */
3872b6ddb638SJohan Hedberg 	if (hdev->req_status == HCI_REQ_PEND) {
3873b6ddb638SJohan Hedberg 		kfree_skb(hdev->recv_evt);
3874b6ddb638SJohan Hedberg 		hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
3875b6ddb638SJohan Hedberg 	}
3876b6ddb638SJohan Hedberg 
3877b6ddb638SJohan Hedberg 	hci_dev_unlock(hdev);
3878b6ddb638SJohan Hedberg 
38791da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
38801da177e4SLinus Torvalds 
388102350a72SJohan Hedberg 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
3882c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
3883c1f23a2bSJohannes Berg 		u16 opcode = __le16_to_cpu(cmd_hdr->opcode);
388402350a72SJohan Hedberg 
388502350a72SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, 0);
388602350a72SJohan Hedberg 	}
388702350a72SJohan Hedberg 
3888a9de9248SMarcel Holtmann 	switch (event) {
38891da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
38901da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
38911da177e4SLinus Torvalds 		break;
38921da177e4SLinus Torvalds 
38931da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
38941da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
38951da177e4SLinus Torvalds 		break;
38961da177e4SLinus Torvalds 
3897a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3898a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
389921d9e30eSMarcel Holtmann 		break;
390021d9e30eSMarcel Holtmann 
39011da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
39021da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
39031da177e4SLinus Torvalds 		break;
39041da177e4SLinus Torvalds 
39051da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
39061da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
39071da177e4SLinus Torvalds 		break;
39081da177e4SLinus Torvalds 
39091da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
39101da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
39111da177e4SLinus Torvalds 		break;
39121da177e4SLinus Torvalds 
3913a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3914a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3915a9de9248SMarcel Holtmann 		break;
3916a9de9248SMarcel Holtmann 
39171da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
39181da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
39191da177e4SLinus Torvalds 		break;
39201da177e4SLinus Torvalds 
3921a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3922a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3923a9de9248SMarcel Holtmann 		break;
3924a9de9248SMarcel Holtmann 
3925a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3926a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3927a9de9248SMarcel Holtmann 		break;
3928a9de9248SMarcel Holtmann 
3929a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3930a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3931a9de9248SMarcel Holtmann 		break;
3932a9de9248SMarcel Holtmann 
3933a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3934a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3935a9de9248SMarcel Holtmann 		break;
3936a9de9248SMarcel Holtmann 
3937a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3938a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3939a9de9248SMarcel Holtmann 		break;
3940a9de9248SMarcel Holtmann 
3941a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3942a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3943a9de9248SMarcel Holtmann 		break;
3944a9de9248SMarcel Holtmann 
3945a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3946a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
39471da177e4SLinus Torvalds 		break;
39481da177e4SLinus Torvalds 
39491da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
39501da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
39511da177e4SLinus Torvalds 		break;
39521da177e4SLinus Torvalds 
39531da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
39541da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
39551da177e4SLinus Torvalds 		break;
39561da177e4SLinus Torvalds 
39571da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
39581da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
39591da177e4SLinus Torvalds 		break;
39601da177e4SLinus Torvalds 
39611da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
39621da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
39631da177e4SLinus Torvalds 		break;
39641da177e4SLinus Torvalds 
3965a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3966a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3967a8746417SMarcel Holtmann 		break;
3968a8746417SMarcel Holtmann 
396985a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
397085a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
397185a1e930SMarcel Holtmann 		break;
397285a1e930SMarcel Holtmann 
3973a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3974a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3975a9de9248SMarcel Holtmann 		break;
3976a9de9248SMarcel Holtmann 
3977a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3978a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3979a9de9248SMarcel Holtmann 		break;
3980a9de9248SMarcel Holtmann 
3981a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3982a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3983a9de9248SMarcel Holtmann 		break;
3984a9de9248SMarcel Holtmann 
3985a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3986a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
39871da177e4SLinus Torvalds 		break;
39881da177e4SLinus Torvalds 
39891c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
39901c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
39911c2e0041SJohan Hedberg 		break;
39921c2e0041SJohan Hedberg 
39930493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
39940493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
39950493684eSMarcel Holtmann 		break;
39960493684eSMarcel Holtmann 
399703b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
399803b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
399903b555e1SJohan Hedberg 		break;
400003b555e1SJohan Hedberg 
4001a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
4002a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
4003a5c29683SJohan Hedberg 		break;
4004a5c29683SJohan Hedberg 
40051143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
40061143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
40071143d458SBrian Gix 		break;
40081143d458SBrian Gix 
400992a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
401092a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
401192a25256SJohan Hedberg 		break;
401292a25256SJohan Hedberg 
401392a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
401492a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
401592a25256SJohan Hedberg 		break;
401692a25256SJohan Hedberg 
40170493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
40180493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
40190493684eSMarcel Holtmann 		break;
40200493684eSMarcel Holtmann 
402141a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
402241a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
402341a96212SMarcel Holtmann 		break;
402441a96212SMarcel Holtmann 
4025fcd89c09SVille Tervo 	case HCI_EV_LE_META:
4026fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
4027fcd89c09SVille Tervo 		break;
4028fcd89c09SVille Tervo 
40299495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
40309495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
40319495b2eeSAndrei Emeltchenko 		break;
40329495b2eeSAndrei Emeltchenko 
40332763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
40342763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
40352763eda6SSzymon Janc 		break;
40362763eda6SSzymon Janc 
4037d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
4038d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
4039d5e91192SAndrei Emeltchenko 		break;
4040d5e91192SAndrei Emeltchenko 
404127695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
404227695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
404327695fb4SAndrei Emeltchenko 		break;
404427695fb4SAndrei Emeltchenko 
4045606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4046606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
4047606e2a10SAndrei Emeltchenko 		break;
4048606e2a10SAndrei Emeltchenko 
40499eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
40509eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
40519eef6b3aSAndrei Emeltchenko 		break;
40529eef6b3aSAndrei Emeltchenko 
405325e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
405425e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
405525e89e99SAndrei Emeltchenko 		break;
405625e89e99SAndrei Emeltchenko 
40571da177e4SLinus Torvalds 	default:
40589f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
40591da177e4SLinus Torvalds 		break;
40601da177e4SLinus Torvalds 	}
40611da177e4SLinus Torvalds 
40621da177e4SLinus Torvalds 	kfree_skb(skb);
40631da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
40641da177e4SLinus Torvalds }
4065