xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 7024728e)
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;
198a9de9248SMarcel Holtmann }
199a9de9248SMarcel Holtmann 
200a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
201a9de9248SMarcel Holtmann {
202a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2031da177e4SLinus Torvalds 	void *sent;
2041da177e4SLinus Torvalds 
2059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2061da177e4SLinus Torvalds 
207a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2081da177e4SLinus Torvalds 	if (!sent)
209a9de9248SMarcel Holtmann 		return;
2101da177e4SLinus Torvalds 
21156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21256e5cb86SJohan Hedberg 
213f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
214f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
21528cc7bdeSJohan Hedberg 	else if (!status)
21628cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
217f51d5b24SJohan Hedberg 
21856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
219a9de9248SMarcel Holtmann }
220a9de9248SMarcel Holtmann 
221a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
222a9de9248SMarcel Holtmann {
223a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
224a9de9248SMarcel Holtmann 
2259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
226a9de9248SMarcel Holtmann 
227a9de9248SMarcel Holtmann 	if (rp->status)
228a9de9248SMarcel Holtmann 		return;
229a9de9248SMarcel Holtmann 
230db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2311f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
232a9de9248SMarcel Holtmann }
233a9de9248SMarcel Holtmann 
234a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
235a9de9248SMarcel Holtmann {
236a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
237a9de9248SMarcel Holtmann 	void *sent;
238a9de9248SMarcel Holtmann 
2399f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
240a9de9248SMarcel Holtmann 
241a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
242a9de9248SMarcel Holtmann 	if (!sent)
243a9de9248SMarcel Holtmann 		return;
2441da177e4SLinus Torvalds 
2451da177e4SLinus Torvalds 	if (!status) {
246a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
247a9de9248SMarcel Holtmann 
2481da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2491da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2501da177e4SLinus Torvalds 		else
2511da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2521da177e4SLinus Torvalds 	}
253a9de9248SMarcel Holtmann 
25433ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
25533ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
256a9de9248SMarcel Holtmann }
2571da177e4SLinus Torvalds 
258a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
259a9de9248SMarcel Holtmann {
260a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
261a9de9248SMarcel Holtmann 	void *sent;
262a9de9248SMarcel Holtmann 
2639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
264a9de9248SMarcel Holtmann 
265a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2661da177e4SLinus Torvalds 	if (!sent)
267a9de9248SMarcel Holtmann 		return;
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds 	if (!status) {
270a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
271a9de9248SMarcel Holtmann 
2721da177e4SLinus Torvalds 		if (param)
2731da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2741da177e4SLinus Torvalds 		else
2751da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2761da177e4SLinus Torvalds 	}
2771da177e4SLinus Torvalds }
2781da177e4SLinus Torvalds 
279a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
280a9de9248SMarcel Holtmann {
28136f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
28236f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
283a9de9248SMarcel Holtmann 	void *sent;
2841da177e4SLinus Torvalds 
2859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
286a9de9248SMarcel Holtmann 
287a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
2881da177e4SLinus Torvalds 	if (!sent)
289a9de9248SMarcel Holtmann 		return;
2901da177e4SLinus Torvalds 
29136f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
292a9de9248SMarcel Holtmann 
29356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
29456e5cb86SJohan Hedberg 
295fa1bd918SMikel Astiz 	if (status) {
296744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
2972d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
2982d7cee58SJohan Hedberg 		goto done;
2992d7cee58SJohan Hedberg 	}
3002d7cee58SJohan Hedberg 
3010663ca2aSJohan Hedberg 	/* We need to ensure that we set this back on if someone changed
3020663ca2aSJohan Hedberg 	 * the scan mode through a raw HCI socket.
3030663ca2aSJohan Hedberg 	 */
3040663ca2aSJohan Hedberg 	set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
3050663ca2aSJohan Hedberg 
3069fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3079fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
308a9de9248SMarcel Holtmann 
30973f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3101da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3119fbcbb45SJohan Hedberg 		if (!old_iscan)
312744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
31316ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
31416ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
31516ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
31616ab91abSJohan Hedberg 					   to);
31716ab91abSJohan Hedberg 		}
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 
421333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
422333140b5SMarcel Holtmann {
423333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4245ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
425333140b5SMarcel Holtmann 
4269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
427333140b5SMarcel Holtmann 
428333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
429333140b5SMarcel Holtmann 	if (!sent)
430333140b5SMarcel Holtmann 		return;
431333140b5SMarcel Holtmann 
4325ed8eb2fSJohan Hedberg 	if (!status) {
4335ed8eb2fSJohan Hedberg 		if (sent->mode)
434cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_SSP;
4355ed8eb2fSJohan Hedberg 		else
436cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_SSP;
4375ed8eb2fSJohan Hedberg 	}
4385ed8eb2fSJohan Hedberg 
439c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4405ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
441c0ecddc2SJohan Hedberg 	else if (!status) {
4425ed8eb2fSJohan Hedberg 		if (sent->mode)
44384bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
44484bde9d6SJohan Hedberg 		else
44584bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
446c0ecddc2SJohan Hedberg 	}
447333140b5SMarcel Holtmann }
448333140b5SMarcel Holtmann 
449a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
450a9de9248SMarcel Holtmann {
451a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
4521143e5a6SMarcel Holtmann 
4539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
4541143e5a6SMarcel Holtmann 
455a9de9248SMarcel Holtmann 	if (rp->status)
45642c6b129SJohan Hedberg 		return;
4571143e5a6SMarcel Holtmann 
458a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
459e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
460d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
461e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
462d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
4631da177e4SLinus Torvalds 
4649f1db00cSAndrei Emeltchenko 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
465807deac2SGustavo Padovan 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
466d5859e22SJohan Hedberg }
467d5859e22SJohan Hedberg 
4688fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
4698fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
470a9de9248SMarcel Holtmann {
471a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
472a9de9248SMarcel Holtmann 
4739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
474a9de9248SMarcel Holtmann 
4752177bab5SJohan Hedberg 	if (!rp->status)
476a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
477a9de9248SMarcel Holtmann }
478a9de9248SMarcel Holtmann 
4798fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
4808fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
481a9de9248SMarcel Holtmann {
482a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
483a9de9248SMarcel Holtmann 
4849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
485a9de9248SMarcel Holtmann 
486a9de9248SMarcel Holtmann 	if (rp->status)
487a9de9248SMarcel Holtmann 		return;
488a9de9248SMarcel Holtmann 
489a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
4901da177e4SLinus Torvalds 
4911da177e4SLinus Torvalds 	/* Adjust default settings according to features
4921da177e4SLinus Torvalds 	 * supported by device. */
493a9de9248SMarcel Holtmann 
494cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_3SLOT)
4951da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
4961da177e4SLinus Torvalds 
497cad718edSJohan Hedberg 	if (hdev->features[0][0] & LMP_5SLOT)
4981da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
4991da177e4SLinus Torvalds 
500cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV2) {
5011da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
5025b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
5035b7f9909SMarcel Holtmann 	}
5041da177e4SLinus Torvalds 
505cad718edSJohan Hedberg 	if (hdev->features[0][1] & LMP_HV3) {
5061da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
5075b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
5085b7f9909SMarcel Holtmann 	}
5095b7f9909SMarcel Holtmann 
51045db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
5115b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
5125b7f9909SMarcel Holtmann 
513cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV4)
5145b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
5155b7f9909SMarcel Holtmann 
516cad718edSJohan Hedberg 	if (hdev->features[0][4] & LMP_EV5)
5175b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
5181da177e4SLinus Torvalds 
519cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
520efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
521efc7688bSMarcel Holtmann 
522cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
523efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
524efc7688bSMarcel Holtmann 
525cad718edSJohan Hedberg 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
526efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
527efc7688bSMarcel Holtmann 
528a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
529cad718edSJohan Hedberg 	       hdev->features[0][0], hdev->features[0][1],
530cad718edSJohan Hedberg 	       hdev->features[0][2], hdev->features[0][3],
531cad718edSJohan Hedberg 	       hdev->features[0][4], hdev->features[0][5],
532cad718edSJohan Hedberg 	       hdev->features[0][6], hdev->features[0][7]);
5331da177e4SLinus Torvalds }
5341da177e4SLinus Torvalds 
535971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
536971e3a4bSAndre Guedes 					   struct sk_buff *skb)
537971e3a4bSAndre Guedes {
538971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
539971e3a4bSAndre Guedes 
5409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
541971e3a4bSAndre Guedes 
542971e3a4bSAndre Guedes 	if (rp->status)
54342c6b129SJohan Hedberg 		return;
544971e3a4bSAndre Guedes 
545d2c5d77fSJohan Hedberg 	hdev->max_page = rp->max_page;
546d2c5d77fSJohan Hedberg 
547cad718edSJohan Hedberg 	if (rp->page < HCI_MAX_PAGES)
548cad718edSJohan Hedberg 		memcpy(hdev->features[rp->page], rp->features, 8);
549971e3a4bSAndre Guedes }
550971e3a4bSAndre Guedes 
5511e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
5521e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
5531e89cffbSAndrei Emeltchenko {
5541e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
5551e89cffbSAndrei Emeltchenko 
5569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5571e89cffbSAndrei Emeltchenko 
55842c6b129SJohan Hedberg 	if (!rp->status)
5591e89cffbSAndrei Emeltchenko 		hdev->flow_ctl_mode = rp->mode;
5601e89cffbSAndrei Emeltchenko }
5611e89cffbSAndrei Emeltchenko 
562a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
563a9de9248SMarcel Holtmann {
564a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
565a9de9248SMarcel Holtmann 
5669f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
567a9de9248SMarcel Holtmann 
568a9de9248SMarcel Holtmann 	if (rp->status)
569a9de9248SMarcel Holtmann 		return;
570a9de9248SMarcel Holtmann 
571a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
572a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
573a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
574a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
575da1f5198SMarcel Holtmann 
576da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
577da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
578da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
579da1f5198SMarcel Holtmann 	}
580da1f5198SMarcel Holtmann 
581da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
582da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
5831da177e4SLinus Torvalds 
584807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
585807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
5861da177e4SLinus Torvalds }
5871da177e4SLinus Torvalds 
588a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
589a9de9248SMarcel Holtmann {
590a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
5911da177e4SLinus Torvalds 
5929f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
593a9de9248SMarcel Holtmann 
594a9de9248SMarcel Holtmann 	if (!rp->status)
595a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
59623bb5763SJohan Hedberg }
59723bb5763SJohan Hedberg 
598f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
599f332ec66SJohan Hedberg 					   struct sk_buff *skb)
600f332ec66SJohan Hedberg {
601f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
602f332ec66SJohan Hedberg 
603f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
604f332ec66SJohan Hedberg 
605f332ec66SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) {
606f332ec66SJohan Hedberg 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
607f332ec66SJohan Hedberg 		hdev->page_scan_window = __le16_to_cpu(rp->window);
608f332ec66SJohan Hedberg 	}
609f332ec66SJohan Hedberg }
610f332ec66SJohan Hedberg 
6114a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
6124a3ee763SJohan Hedberg 					    struct sk_buff *skb)
6134a3ee763SJohan Hedberg {
6144a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6154a3ee763SJohan Hedberg 	struct hci_cp_write_page_scan_activity *sent;
6164a3ee763SJohan Hedberg 
6174a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6184a3ee763SJohan Hedberg 
6194a3ee763SJohan Hedberg 	if (status)
6204a3ee763SJohan Hedberg 		return;
6214a3ee763SJohan Hedberg 
6224a3ee763SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
6234a3ee763SJohan Hedberg 	if (!sent)
6244a3ee763SJohan Hedberg 		return;
6254a3ee763SJohan Hedberg 
6264a3ee763SJohan Hedberg 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
6274a3ee763SJohan Hedberg 	hdev->page_scan_window = __le16_to_cpu(sent->window);
6284a3ee763SJohan Hedberg }
6294a3ee763SJohan Hedberg 
630f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
631f332ec66SJohan Hedberg 					   struct sk_buff *skb)
632f332ec66SJohan Hedberg {
633f332ec66SJohan Hedberg 	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
634f332ec66SJohan Hedberg 
635f332ec66SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
636f332ec66SJohan Hedberg 
637f332ec66SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status)
638f332ec66SJohan Hedberg 		hdev->page_scan_type = rp->type;
639f332ec66SJohan Hedberg }
640f332ec66SJohan Hedberg 
6414a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
6424a3ee763SJohan Hedberg 					struct sk_buff *skb)
6434a3ee763SJohan Hedberg {
6444a3ee763SJohan Hedberg 	u8 status = *((u8 *) skb->data);
6454a3ee763SJohan Hedberg 	u8 *type;
6464a3ee763SJohan Hedberg 
6474a3ee763SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
6484a3ee763SJohan Hedberg 
6494a3ee763SJohan Hedberg 	if (status)
6504a3ee763SJohan Hedberg 		return;
6514a3ee763SJohan Hedberg 
6524a3ee763SJohan Hedberg 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
6534a3ee763SJohan Hedberg 	if (type)
6544a3ee763SJohan Hedberg 		hdev->page_scan_type = *type;
6554a3ee763SJohan Hedberg }
6564a3ee763SJohan Hedberg 
657350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
658350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
659350ee4cfSAndrei Emeltchenko {
660350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
661350ee4cfSAndrei Emeltchenko 
6629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
663350ee4cfSAndrei Emeltchenko 
664350ee4cfSAndrei Emeltchenko 	if (rp->status)
665350ee4cfSAndrei Emeltchenko 		return;
666350ee4cfSAndrei Emeltchenko 
667350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
668350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
669350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
670350ee4cfSAndrei Emeltchenko 
671350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
672350ee4cfSAndrei Emeltchenko 
673350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
674350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
675350ee4cfSAndrei Emeltchenko }
676350ee4cfSAndrei Emeltchenko 
677928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
678928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
679928abaa7SAndrei Emeltchenko {
680928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
681928abaa7SAndrei Emeltchenko 
6829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
683928abaa7SAndrei Emeltchenko 
684928abaa7SAndrei Emeltchenko 	if (rp->status)
6858e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
686928abaa7SAndrei Emeltchenko 
687928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
688928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
689928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
690928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
691928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
692928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
693928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
694928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
695928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
696928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
697928abaa7SAndrei Emeltchenko 
6988e2a0d92SAndrei Emeltchenko a2mp_rsp:
6998e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
700928abaa7SAndrei Emeltchenko }
701928abaa7SAndrei Emeltchenko 
702903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
703903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
704903e4541SAndrei Emeltchenko {
705903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
706903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
707903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
708903e4541SAndrei Emeltchenko 
709903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
710903e4541SAndrei Emeltchenko 
711903e4541SAndrei Emeltchenko 	if (rp->status)
712903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
713903e4541SAndrei Emeltchenko 
714903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
715903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
716903e4541SAndrei Emeltchenko 
717903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
7182e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
719903e4541SAndrei Emeltchenko 
720903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
721903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
722903e4541SAndrei Emeltchenko 
723903e4541SAndrei Emeltchenko 		/* Read other fragments */
724903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
725903e4541SAndrei Emeltchenko 
726903e4541SAndrei Emeltchenko 		return;
727903e4541SAndrei Emeltchenko 	}
728903e4541SAndrei Emeltchenko 
729903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
730903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
731903e4541SAndrei Emeltchenko 	assoc->offset = 0;
732903e4541SAndrei Emeltchenko 
733903e4541SAndrei Emeltchenko a2mp_rsp:
734903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
735903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
7369495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
737903e4541SAndrei Emeltchenko }
738903e4541SAndrei Emeltchenko 
739d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
740d5859e22SJohan Hedberg 					 struct sk_buff *skb)
741d5859e22SJohan Hedberg {
74291c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
743d5859e22SJohan Hedberg 
7449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
745d5859e22SJohan Hedberg 
74691c4e9b1SMarcel Holtmann 	if (!rp->status)
74791c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
748d5859e22SJohan Hedberg }
749d5859e22SJohan Hedberg 
750980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
751980e1a53SJohan Hedberg {
752980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
753980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
754980e1a53SJohan Hedberg 	struct hci_conn *conn;
755980e1a53SJohan Hedberg 
7569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
757980e1a53SJohan Hedberg 
75856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
75956e5cb86SJohan Hedberg 
760a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
761744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
762980e1a53SJohan Hedberg 
763fa1bd918SMikel Astiz 	if (rp->status)
76456e5cb86SJohan Hedberg 		goto unlock;
765980e1a53SJohan Hedberg 
766980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
767980e1a53SJohan Hedberg 	if (!cp)
76856e5cb86SJohan Hedberg 		goto unlock;
769980e1a53SJohan Hedberg 
770980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
771980e1a53SJohan Hedberg 	if (conn)
772980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
77356e5cb86SJohan Hedberg 
77456e5cb86SJohan Hedberg unlock:
77556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
776980e1a53SJohan Hedberg }
777980e1a53SJohan Hedberg 
778980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
779980e1a53SJohan Hedberg {
780980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
781980e1a53SJohan Hedberg 
7829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
783980e1a53SJohan Hedberg 
78456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
78556e5cb86SJohan Hedberg 
786a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
787744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
788980e1a53SJohan Hedberg 						 rp->status);
78956e5cb86SJohan Hedberg 
79056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
791980e1a53SJohan Hedberg }
79256e5cb86SJohan Hedberg 
7936ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
7946ed58ec5SVille Tervo 				       struct sk_buff *skb)
7956ed58ec5SVille Tervo {
7966ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
7976ed58ec5SVille Tervo 
7989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
7996ed58ec5SVille Tervo 
8006ed58ec5SVille Tervo 	if (rp->status)
8016ed58ec5SVille Tervo 		return;
8026ed58ec5SVille Tervo 
8036ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
8046ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8056ed58ec5SVille Tervo 
8066ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8076ed58ec5SVille Tervo 
8086ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8096ed58ec5SVille Tervo }
810980e1a53SJohan Hedberg 
81160e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
81260e77321SJohan Hedberg 					  struct sk_buff *skb)
81360e77321SJohan Hedberg {
81460e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
81560e77321SJohan Hedberg 
81660e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
81760e77321SJohan Hedberg 
81860e77321SJohan Hedberg 	if (!rp->status)
81960e77321SJohan Hedberg 		memcpy(hdev->le_features, rp->features, 8);
82060e77321SJohan Hedberg }
82160e77321SJohan Hedberg 
8228fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
8238fa19098SJohan Hedberg 					struct sk_buff *skb)
8248fa19098SJohan Hedberg {
8258fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
8268fa19098SJohan Hedberg 
8278fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8288fa19098SJohan Hedberg 
82904b4edcbSJohan Hedberg 	if (!rp->status)
8308fa19098SJohan Hedberg 		hdev->adv_tx_power = rp->tx_power;
8318fa19098SJohan Hedberg }
8328fa19098SJohan Hedberg 
833a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
834a5c29683SJohan Hedberg {
835a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
836a5c29683SJohan Hedberg 
8379f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
838a5c29683SJohan Hedberg 
83956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
84056e5cb86SJohan Hedberg 
841a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
84204124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
84304124681SGustavo F. Padovan 						 rp->status);
84456e5cb86SJohan Hedberg 
84556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
846a5c29683SJohan Hedberg }
847a5c29683SJohan Hedberg 
848a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
849a5c29683SJohan Hedberg 					  struct sk_buff *skb)
850a5c29683SJohan Hedberg {
851a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
852a5c29683SJohan Hedberg 
8539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
854a5c29683SJohan Hedberg 
85556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
85656e5cb86SJohan Hedberg 
857a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
858744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
85904124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
86056e5cb86SJohan Hedberg 
86156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
862a5c29683SJohan Hedberg }
863a5c29683SJohan Hedberg 
8641143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
8651143d458SBrian Gix {
8661143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
8671143d458SBrian Gix 
8689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8691143d458SBrian Gix 
8701143d458SBrian Gix 	hci_dev_lock(hdev);
8711143d458SBrian Gix 
872a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
873272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
874272d90dfSJohan Hedberg 						 0, rp->status);
8751143d458SBrian Gix 
8761143d458SBrian Gix 	hci_dev_unlock(hdev);
8771143d458SBrian Gix }
8781143d458SBrian Gix 
8791143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
8801143d458SBrian Gix 					  struct sk_buff *skb)
8811143d458SBrian Gix {
8821143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
8831143d458SBrian Gix 
8849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8851143d458SBrian Gix 
8861143d458SBrian Gix 	hci_dev_lock(hdev);
8871143d458SBrian Gix 
888a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
8891143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
89004124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
8911143d458SBrian Gix 
8921143d458SBrian Gix 	hci_dev_unlock(hdev);
8931143d458SBrian Gix }
8941143d458SBrian Gix 
895c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
896c35938b2SSzymon Janc 					     struct sk_buff *skb)
897c35938b2SSzymon Janc {
898c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
899c35938b2SSzymon Janc 
9009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
901c35938b2SSzymon Janc 
90256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
903744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
904c35938b2SSzymon Janc 						rp->randomizer, rp->status);
90556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
906c35938b2SSzymon Janc }
907c35938b2SSzymon Janc 
908c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
909c1d5dc4aSJohan Hedberg {
910c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
911c1d5dc4aSJohan Hedberg 
912c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
913c1d5dc4aSJohan Hedberg 
914c1d5dc4aSJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
915c1d5dc4aSJohan Hedberg 	if (!sent)
916c1d5dc4aSJohan Hedberg 		return;
917c1d5dc4aSJohan Hedberg 
918c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
919c1d5dc4aSJohan Hedberg 
920c1d5dc4aSJohan Hedberg 	if (!status) {
921c1d5dc4aSJohan Hedberg 		if (*sent)
922f3d3444aSJohan Hedberg 			set_bit(HCI_ADVERTISING, &hdev->dev_flags);
923c1d5dc4aSJohan Hedberg 		else
924f3d3444aSJohan Hedberg 			clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
925c1d5dc4aSJohan Hedberg 	}
926c1d5dc4aSJohan Hedberg 
92704b4edcbSJohan Hedberg 	if (!test_bit(HCI_INIT, &hdev->flags)) {
92804b4edcbSJohan Hedberg 		struct hci_request req;
929c1d5dc4aSJohan Hedberg 
93004b4edcbSJohan Hedberg 		hci_req_init(&req, hdev);
93104b4edcbSJohan Hedberg 		hci_update_ad(&req);
93204b4edcbSJohan Hedberg 		hci_req_run(&req, NULL);
93304b4edcbSJohan Hedberg 	}
93404b4edcbSJohan Hedberg 
93504b4edcbSJohan Hedberg 	hci_dev_unlock(hdev);
936c1d5dc4aSJohan Hedberg }
937c1d5dc4aSJohan Hedberg 
938eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
939eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
940eb9d91f5SAndre Guedes {
941eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
942eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
943eb9d91f5SAndre Guedes 
9449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
945eb9d91f5SAndre Guedes 
946eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
947eb9d91f5SAndre Guedes 	if (!cp)
948eb9d91f5SAndre Guedes 		return;
949eb9d91f5SAndre Guedes 
950fef5234aSAndre Guedes 	if (status)
9517ba8b4beSAndre Guedes 		return;
9527ba8b4beSAndre Guedes 
9533fd319b8SAndre Guedes 	switch (cp->enable) {
9543fd319b8SAndre Guedes 	case LE_SCAN_ENABLE:
955d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
95668a8aea4SAndrei Emeltchenko 		break;
95768a8aea4SAndrei Emeltchenko 
95876a388beSAndre Guedes 	case LE_SCAN_DISABLE:
959d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
96068a8aea4SAndrei Emeltchenko 		break;
96168a8aea4SAndrei Emeltchenko 
96268a8aea4SAndrei Emeltchenko 	default:
96368a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
96468a8aea4SAndrei Emeltchenko 		break;
96535815085SAndre Guedes 	}
966eb9d91f5SAndre Guedes }
967eb9d91f5SAndre Guedes 
968cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
969cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
970cf1d081fSJohan Hedberg {
971cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
972cf1d081fSJohan Hedberg 
973cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
974cf1d081fSJohan Hedberg 
975cf1d081fSJohan Hedberg 	if (!rp->status)
976cf1d081fSJohan Hedberg 		hdev->le_white_list_size = rp->size;
977cf1d081fSJohan Hedberg }
978cf1d081fSJohan Hedberg 
9799b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
9809b008c04SJohan Hedberg 					    struct sk_buff *skb)
9819b008c04SJohan Hedberg {
9829b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
9839b008c04SJohan Hedberg 
9849b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9859b008c04SJohan Hedberg 
9869b008c04SJohan Hedberg 	if (!rp->status)
9879b008c04SJohan Hedberg 		memcpy(hdev->le_states, rp->le_states, 8);
9889b008c04SJohan Hedberg }
9899b008c04SJohan Hedberg 
9906039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
991f9b49306SAndre Guedes 					   struct sk_buff *skb)
992f9b49306SAndre Guedes {
99306199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
994f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
995f9b49306SAndre Guedes 
9969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
997f9b49306SAndre Guedes 
99806199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
9998f984dfaSJohan Hedberg 	if (!sent)
1000f9b49306SAndre Guedes 		return;
1001f9b49306SAndre Guedes 
10028f984dfaSJohan Hedberg 	if (!status) {
1003416a4ae5SJohan Hedberg 		if (sent->le) {
1004cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE;
1005416a4ae5SJohan Hedberg 			set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1006416a4ae5SJohan Hedberg 		} else {
1007cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE;
1008416a4ae5SJohan Hedberg 			clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1009f3d3444aSJohan Hedberg 			clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1010416a4ae5SJohan Hedberg 		}
101153b2caabSJohan Hedberg 
101253b2caabSJohan Hedberg 		if (sent->simul)
1013cad718edSJohan Hedberg 			hdev->features[1][0] |= LMP_HOST_LE_BREDR;
101453b2caabSJohan Hedberg 		else
1015cad718edSJohan Hedberg 			hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
10168f984dfaSJohan Hedberg 	}
1017f9b49306SAndre Guedes }
1018f9b49306SAndre Guedes 
101993c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
102093c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
102193c284eeSAndrei Emeltchenko {
102293c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
102393c284eeSAndrei Emeltchenko 
102493c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
102593c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
102693c284eeSAndrei Emeltchenko 
102793c284eeSAndrei Emeltchenko 	if (rp->status)
102893c284eeSAndrei Emeltchenko 		return;
102993c284eeSAndrei Emeltchenko 
103093c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
103193c284eeSAndrei Emeltchenko }
103293c284eeSAndrei Emeltchenko 
10336039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1034a9de9248SMarcel Holtmann {
10359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1036a9de9248SMarcel Holtmann 
1037a9de9248SMarcel Holtmann 	if (status) {
1038a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
1039314b2381SJohan Hedberg 		return;
1040314b2381SJohan Hedberg 	}
1041314b2381SJohan Hedberg 
104289352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
1043a9de9248SMarcel Holtmann }
1044a9de9248SMarcel Holtmann 
10456039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
10461da177e4SLinus Torvalds {
1047a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
10481da177e4SLinus Torvalds 	struct hci_conn *conn;
10491da177e4SLinus Torvalds 
10509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1051a9de9248SMarcel Holtmann 
1052a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
10531da177e4SLinus Torvalds 	if (!cp)
10541da177e4SLinus Torvalds 		return;
10551da177e4SLinus Torvalds 
10561da177e4SLinus Torvalds 	hci_dev_lock(hdev);
10571da177e4SLinus Torvalds 
10581da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
10591da177e4SLinus Torvalds 
10606ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
10611da177e4SLinus Torvalds 
10621da177e4SLinus Torvalds 	if (status) {
10631da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
10644c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
10651da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
10661da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
10671da177e4SLinus Torvalds 				hci_conn_del(conn);
10684c67bc74SMarcel Holtmann 			} else
10694c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
10701da177e4SLinus Torvalds 		}
10711da177e4SLinus Torvalds 	} else {
10721da177e4SLinus Torvalds 		if (!conn) {
10731da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
10741da177e4SLinus Torvalds 			if (conn) {
1075a0c808b3SJohan Hedberg 				conn->out = true;
10761da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
10771da177e4SLinus Torvalds 			} else
1078893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
10791da177e4SLinus Torvalds 		}
10801da177e4SLinus Torvalds 	}
10811da177e4SLinus Torvalds 
10821da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
10831da177e4SLinus Torvalds }
10841da177e4SLinus Torvalds 
1085a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
10861da177e4SLinus Torvalds {
1087a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
10881da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
10891da177e4SLinus Torvalds 	__u16 handle;
10901da177e4SLinus Torvalds 
10919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1092b6a0dc82SMarcel Holtmann 
1093a9de9248SMarcel Holtmann 	if (!status)
1094a9de9248SMarcel Holtmann 		return;
1095a9de9248SMarcel Holtmann 
1096a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
10971da177e4SLinus Torvalds 	if (!cp)
1098a9de9248SMarcel Holtmann 		return;
10991da177e4SLinus Torvalds 
11001da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
11011da177e4SLinus Torvalds 
11029f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
11031da177e4SLinus Torvalds 
11041da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11051da177e4SLinus Torvalds 
11061da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
11075a08ecceSAndrei Emeltchenko 	if (acl) {
11085a08ecceSAndrei Emeltchenko 		sco = acl->link;
11095a08ecceSAndrei Emeltchenko 		if (sco) {
11101da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
11111da177e4SLinus Torvalds 
11121da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
11131da177e4SLinus Torvalds 			hci_conn_del(sco);
11141da177e4SLinus Torvalds 		}
11155a08ecceSAndrei Emeltchenko 	}
11161da177e4SLinus Torvalds 
11171da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
11181da177e4SLinus Torvalds }
11191da177e4SLinus Torvalds 
1120f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1121f8558555SMarcel Holtmann {
1122f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1123f8558555SMarcel Holtmann 	struct hci_conn *conn;
1124f8558555SMarcel Holtmann 
11259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1126f8558555SMarcel Holtmann 
1127f8558555SMarcel Holtmann 	if (!status)
1128f8558555SMarcel Holtmann 		return;
1129f8558555SMarcel Holtmann 
1130f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1131f8558555SMarcel Holtmann 	if (!cp)
1132f8558555SMarcel Holtmann 		return;
1133f8558555SMarcel Holtmann 
1134f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1135f8558555SMarcel Holtmann 
1136f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1137f8558555SMarcel Holtmann 	if (conn) {
1138f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1139f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
114076a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1141f8558555SMarcel Holtmann 		}
1142f8558555SMarcel Holtmann 	}
1143f8558555SMarcel Holtmann 
1144f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1145f8558555SMarcel Holtmann }
1146f8558555SMarcel Holtmann 
1147f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1148f8558555SMarcel Holtmann {
1149f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1150f8558555SMarcel Holtmann 	struct hci_conn *conn;
1151f8558555SMarcel Holtmann 
11529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1153f8558555SMarcel Holtmann 
1154f8558555SMarcel Holtmann 	if (!status)
1155f8558555SMarcel Holtmann 		return;
1156f8558555SMarcel Holtmann 
1157f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1158f8558555SMarcel Holtmann 	if (!cp)
1159f8558555SMarcel Holtmann 		return;
1160f8558555SMarcel Holtmann 
1161f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1162f8558555SMarcel Holtmann 
1163f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1164f8558555SMarcel Holtmann 	if (conn) {
1165f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1166f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
116776a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1168f8558555SMarcel Holtmann 		}
1169f8558555SMarcel Holtmann 	}
1170f8558555SMarcel Holtmann 
1171f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1172f8558555SMarcel Holtmann }
1173f8558555SMarcel Holtmann 
1174127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1175392599b9SJohan Hedberg 				    struct hci_conn *conn)
1176392599b9SJohan Hedberg {
1177392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1178392599b9SJohan Hedberg 		return 0;
1179392599b9SJohan Hedberg 
1180765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1181392599b9SJohan Hedberg 		return 0;
1182392599b9SJohan Hedberg 
1183392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1184e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1185807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1186807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1187392599b9SJohan Hedberg 		return 0;
1188392599b9SJohan Hedberg 
1189392599b9SJohan Hedberg 	return 1;
1190392599b9SJohan Hedberg }
1191392599b9SJohan Hedberg 
11926039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
119300abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
119430dc78e1SJohan Hedberg {
119530dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
119630dc78e1SJohan Hedberg 
119730dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
119830dc78e1SJohan Hedberg 
119930dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
120030dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
120130dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
120230dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
120330dc78e1SJohan Hedberg 
120430dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
120530dc78e1SJohan Hedberg }
120630dc78e1SJohan Hedberg 
1207b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
120830dc78e1SJohan Hedberg {
120930dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
121030dc78e1SJohan Hedberg 	struct inquiry_entry *e;
121130dc78e1SJohan Hedberg 
1212b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1213b644ba33SJohan Hedberg 		return false;
1214b644ba33SJohan Hedberg 
1215b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1216c810089cSRam Malovany 	if (!e)
1217c810089cSRam Malovany 		return false;
1218c810089cSRam Malovany 
1219b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1220b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1221b644ba33SJohan Hedberg 		return true;
1222b644ba33SJohan Hedberg 	}
1223b644ba33SJohan Hedberg 
1224b644ba33SJohan Hedberg 	return false;
1225b644ba33SJohan Hedberg }
1226b644ba33SJohan Hedberg 
1227b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1228b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1229b644ba33SJohan Hedberg {
1230b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1231b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1232b644ba33SJohan Hedberg 
1233b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
123404124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
123504124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1236b644ba33SJohan Hedberg 
1237b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1238b644ba33SJohan Hedberg 		return;
1239b644ba33SJohan Hedberg 
124030dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
124130dc78e1SJohan Hedberg 		goto discov_complete;
124230dc78e1SJohan Hedberg 
124330dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
124430dc78e1SJohan Hedberg 		return;
124530dc78e1SJohan Hedberg 
124630dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
12477cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
12487cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
12497cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
12507cc8380eSRam Malovany 	 * Event */
12517cc8380eSRam Malovany 	if (!e)
12527cc8380eSRam Malovany 		return;
12537cc8380eSRam Malovany 
125430dc78e1SJohan Hedberg 	list_del(&e->list);
12557cc8380eSRam Malovany 	if (name) {
12567cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1257b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1258b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1259c3e7c0d9SRam Malovany 	} else {
1260c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
126130dc78e1SJohan Hedberg 	}
126230dc78e1SJohan Hedberg 
1263b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
126430dc78e1SJohan Hedberg 		return;
126530dc78e1SJohan Hedberg 
126630dc78e1SJohan Hedberg discov_complete:
126730dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
126830dc78e1SJohan Hedberg }
126930dc78e1SJohan Hedberg 
1270a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
12711da177e4SLinus Torvalds {
1272127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1273127178d2SJohan Hedberg 	struct hci_conn *conn;
1274127178d2SJohan Hedberg 
12759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1276127178d2SJohan Hedberg 
1277127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1278127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1279127178d2SJohan Hedberg 	if (!status)
1280127178d2SJohan Hedberg 		return;
1281127178d2SJohan Hedberg 
1282127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1283127178d2SJohan Hedberg 	if (!cp)
1284127178d2SJohan Hedberg 		return;
1285127178d2SJohan Hedberg 
1286127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1287127178d2SJohan Hedberg 
1288127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1289b644ba33SJohan Hedberg 
1290b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1291b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1292b644ba33SJohan Hedberg 
129379c6c70cSJohan Hedberg 	if (!conn)
129479c6c70cSJohan Hedberg 		goto unlock;
129579c6c70cSJohan Hedberg 
129679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
129779c6c70cSJohan Hedberg 		goto unlock;
129879c6c70cSJohan Hedberg 
129951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1300c1f23a2bSJohannes Berg 		struct hci_cp_auth_requested auth_cp;
1301c1f23a2bSJohannes Berg 
1302c1f23a2bSJohannes Berg 		auth_cp.handle = __cpu_to_le16(conn->handle);
1303c1f23a2bSJohannes Berg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
1304c1f23a2bSJohannes Berg 			     sizeof(auth_cp), &auth_cp);
1305127178d2SJohan Hedberg 	}
1306127178d2SJohan Hedberg 
130779c6c70cSJohan Hedberg unlock:
1308127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1309a9de9248SMarcel Holtmann }
13101da177e4SLinus Torvalds 
1311769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1312769be974SMarcel Holtmann {
1313769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1314769be974SMarcel Holtmann 	struct hci_conn *conn;
1315769be974SMarcel Holtmann 
13169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1317769be974SMarcel Holtmann 
1318769be974SMarcel Holtmann 	if (!status)
1319769be974SMarcel Holtmann 		return;
1320769be974SMarcel Holtmann 
1321769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1322769be974SMarcel Holtmann 	if (!cp)
1323769be974SMarcel Holtmann 		return;
1324769be974SMarcel Holtmann 
1325769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1326769be974SMarcel Holtmann 
1327769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1328769be974SMarcel Holtmann 	if (conn) {
1329769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1330769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
133176a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1332769be974SMarcel Holtmann 		}
1333769be974SMarcel Holtmann 	}
1334769be974SMarcel Holtmann 
1335769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1336769be974SMarcel Holtmann }
1337769be974SMarcel Holtmann 
1338769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1339769be974SMarcel Holtmann {
1340769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1341769be974SMarcel Holtmann 	struct hci_conn *conn;
1342769be974SMarcel Holtmann 
13439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1344769be974SMarcel Holtmann 
1345769be974SMarcel Holtmann 	if (!status)
1346769be974SMarcel Holtmann 		return;
1347769be974SMarcel Holtmann 
1348769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1349769be974SMarcel Holtmann 	if (!cp)
1350769be974SMarcel Holtmann 		return;
1351769be974SMarcel Holtmann 
1352769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1353769be974SMarcel Holtmann 
1354769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1355769be974SMarcel Holtmann 	if (conn) {
1356769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1357769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
135876a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1359769be974SMarcel Holtmann 		}
1360769be974SMarcel Holtmann 	}
1361769be974SMarcel Holtmann 
1362769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1363769be974SMarcel Holtmann }
1364769be974SMarcel Holtmann 
1365a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1366a9de9248SMarcel Holtmann {
1367b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1368b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1369b6a0dc82SMarcel Holtmann 	__u16 handle;
1370b6a0dc82SMarcel Holtmann 
13719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1372b6a0dc82SMarcel Holtmann 
1373b6a0dc82SMarcel Holtmann 	if (!status)
1374b6a0dc82SMarcel Holtmann 		return;
1375b6a0dc82SMarcel Holtmann 
1376b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1377b6a0dc82SMarcel Holtmann 	if (!cp)
1378b6a0dc82SMarcel Holtmann 		return;
1379b6a0dc82SMarcel Holtmann 
1380b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1381b6a0dc82SMarcel Holtmann 
13829f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1383b6a0dc82SMarcel Holtmann 
1384b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1385b6a0dc82SMarcel Holtmann 
1386b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
13875a08ecceSAndrei Emeltchenko 	if (acl) {
13885a08ecceSAndrei Emeltchenko 		sco = acl->link;
13895a08ecceSAndrei Emeltchenko 		if (sco) {
1390b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1391b6a0dc82SMarcel Holtmann 
1392b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1393b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1394b6a0dc82SMarcel Holtmann 		}
13955a08ecceSAndrei Emeltchenko 	}
1396b6a0dc82SMarcel Holtmann 
1397b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1398a9de9248SMarcel Holtmann }
1399a9de9248SMarcel Holtmann 
1400a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1401a9de9248SMarcel Holtmann {
1402a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
140304837f64SMarcel Holtmann 	struct hci_conn *conn;
140404837f64SMarcel Holtmann 
14059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1406a9de9248SMarcel Holtmann 
1407a9de9248SMarcel Holtmann 	if (!status)
1408a9de9248SMarcel Holtmann 		return;
1409a9de9248SMarcel Holtmann 
1410a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
141104837f64SMarcel Holtmann 	if (!cp)
1412a9de9248SMarcel Holtmann 		return;
141304837f64SMarcel Holtmann 
141404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
141504837f64SMarcel Holtmann 
141604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1417e73439d8SMarcel Holtmann 	if (conn) {
141851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
141904837f64SMarcel Holtmann 
142051a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1421e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1422e73439d8SMarcel Holtmann 	}
1423e73439d8SMarcel Holtmann 
142404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
142504837f64SMarcel Holtmann }
142604837f64SMarcel Holtmann 
1427a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1428a9de9248SMarcel Holtmann {
1429a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
143004837f64SMarcel Holtmann 	struct hci_conn *conn;
143104837f64SMarcel Holtmann 
14329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1433a9de9248SMarcel Holtmann 
1434a9de9248SMarcel Holtmann 	if (!status)
1435a9de9248SMarcel Holtmann 		return;
1436a9de9248SMarcel Holtmann 
1437a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
143804837f64SMarcel Holtmann 	if (!cp)
1439a9de9248SMarcel Holtmann 		return;
144004837f64SMarcel Holtmann 
144104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
144204837f64SMarcel Holtmann 
144304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1444e73439d8SMarcel Holtmann 	if (conn) {
144551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
144604837f64SMarcel Holtmann 
144751a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1448e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1449e73439d8SMarcel Holtmann 	}
1450e73439d8SMarcel Holtmann 
145104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
145204837f64SMarcel Holtmann }
145304837f64SMarcel Holtmann 
145488c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
145588c3df13SJohan Hedberg {
145688c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
145788c3df13SJohan Hedberg 	struct hci_conn *conn;
145888c3df13SJohan Hedberg 
145988c3df13SJohan Hedberg 	if (!status)
146088c3df13SJohan Hedberg 		return;
146188c3df13SJohan Hedberg 
146288c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
146388c3df13SJohan Hedberg 	if (!cp)
146488c3df13SJohan Hedberg 		return;
146588c3df13SJohan Hedberg 
146688c3df13SJohan Hedberg 	hci_dev_lock(hdev);
146788c3df13SJohan Hedberg 
146888c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
146988c3df13SJohan Hedberg 	if (conn)
147088c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
147188c3df13SJohan Hedberg 				       conn->dst_type, status);
147288c3df13SJohan Hedberg 
147388c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
147488c3df13SJohan Hedberg }
147588c3df13SJohan Hedberg 
1476a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1477a02226d6SAndrei Emeltchenko {
147893c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
147993c284eeSAndrei Emeltchenko 
1480a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
148193c284eeSAndrei Emeltchenko 
148293c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
148393c284eeSAndrei Emeltchenko 	if (!cp)
148493c284eeSAndrei Emeltchenko 		return;
148593c284eeSAndrei Emeltchenko 
1486e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1487e58917b9SAndrei Emeltchenko 
1488e58917b9SAndrei Emeltchenko 	if (status) {
1489e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1490e58917b9SAndrei Emeltchenko 
1491e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1492e58917b9SAndrei Emeltchenko 		if (hcon)
1493e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1494e58917b9SAndrei Emeltchenko 	} else {
149593c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1496a02226d6SAndrei Emeltchenko 	}
1497a02226d6SAndrei Emeltchenko 
1498e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1499e58917b9SAndrei Emeltchenko }
1500e58917b9SAndrei Emeltchenko 
15010b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
15020b26ab9dSAndrei Emeltchenko {
15030b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
15040b26ab9dSAndrei Emeltchenko 
15050b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15060b26ab9dSAndrei Emeltchenko 
15070b26ab9dSAndrei Emeltchenko 	if (status)
15080b26ab9dSAndrei Emeltchenko 		return;
15090b26ab9dSAndrei Emeltchenko 
15100b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
15110b26ab9dSAndrei Emeltchenko 	if (!cp)
15120b26ab9dSAndrei Emeltchenko 		return;
15130b26ab9dSAndrei Emeltchenko 
15140b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
15150b26ab9dSAndrei Emeltchenko }
15160b26ab9dSAndrei Emeltchenko 
15176039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15181da177e4SLinus Torvalds {
15191da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
152030dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
152130dc78e1SJohan Hedberg 	struct inquiry_entry *e;
15221da177e4SLinus Torvalds 
15239f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
15241da177e4SLinus Torvalds 
1525a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
152689352e7dSAndre Guedes 
152789352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
152889352e7dSAndre Guedes 		return;
152989352e7dSAndre Guedes 
15303e13fa1eSAndre Guedes 	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
15313e13fa1eSAndre Guedes 	wake_up_bit(&hdev->flags, HCI_INQUIRY);
15323e13fa1eSAndre Guedes 
1533a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
153430dc78e1SJohan Hedberg 		return;
153530dc78e1SJohan Hedberg 
153656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
153730dc78e1SJohan Hedberg 
1538343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
153930dc78e1SJohan Hedberg 		goto unlock;
154030dc78e1SJohan Hedberg 
154130dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1542ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
154330dc78e1SJohan Hedberg 		goto unlock;
154430dc78e1SJohan Hedberg 	}
154530dc78e1SJohan Hedberg 
154630dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
154730dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
154830dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
154930dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
155030dc78e1SJohan Hedberg 	} else {
155130dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
155230dc78e1SJohan Hedberg 	}
155330dc78e1SJohan Hedberg 
155430dc78e1SJohan Hedberg unlock:
155556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
15561da177e4SLinus Torvalds }
15571da177e4SLinus Torvalds 
15586039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
15591da177e4SLinus Torvalds {
156045bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1561a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
15621da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
15631da177e4SLinus Torvalds 
15641da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
15651da177e4SLinus Torvalds 
156645bb4bf0SMarcel Holtmann 	if (!num_rsp)
156745bb4bf0SMarcel Holtmann 		return;
156845bb4bf0SMarcel Holtmann 
15691519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
15701519cc17SAndre Guedes 		return;
15711519cc17SAndre Guedes 
15721da177e4SLinus Torvalds 	hci_dev_lock(hdev);
157345bb4bf0SMarcel Holtmann 
1574e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1575388fc8faSJohan Hedberg 		bool name_known, ssp;
15763175405bSJohan Hedberg 
15771da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
15781da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
15791da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
15801da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
15811da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
15821da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
15831da177e4SLinus Torvalds 		data.rssi		= 0x00;
158441a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
15853175405bSJohan Hedberg 
1586388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
158748264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
158804124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
158904124681SGustavo F. Padovan 				  0);
15901da177e4SLinus Torvalds 	}
159145bb4bf0SMarcel Holtmann 
15921da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
15931da177e4SLinus Torvalds }
15941da177e4SLinus Torvalds 
15956039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
15961da177e4SLinus Torvalds {
1597a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1598a9de9248SMarcel Holtmann 	struct hci_conn *conn;
15991da177e4SLinus Torvalds 
1600a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
160145bb4bf0SMarcel Holtmann 
16021da177e4SLinus Torvalds 	hci_dev_lock(hdev);
160345bb4bf0SMarcel Holtmann 
1604a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
16059499237aSMarcel Holtmann 	if (!conn) {
16069499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
16079499237aSMarcel Holtmann 			goto unlock;
16089499237aSMarcel Holtmann 
16099499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1610a9de9248SMarcel Holtmann 		if (!conn)
1611a9de9248SMarcel Holtmann 			goto unlock;
161245bb4bf0SMarcel Holtmann 
16139499237aSMarcel Holtmann 		conn->type = SCO_LINK;
16149499237aSMarcel Holtmann 	}
16159499237aSMarcel Holtmann 
1616a9de9248SMarcel Holtmann 	if (!ev->status) {
1617a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1618769be974SMarcel Holtmann 
1619769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1620769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1621769be974SMarcel Holtmann 			hci_conn_hold(conn);
1622a9ea3ed9SSzymon Janc 
1623a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1624a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1625a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1626a9ea3ed9SSzymon Janc 			else
1627052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1628769be974SMarcel Holtmann 		} else
1629a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1630a9de9248SMarcel Holtmann 
16317d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
16327d0db0a3SMarcel Holtmann 
1633a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1634a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1635a9de9248SMarcel Holtmann 
1636a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1637a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1638a9de9248SMarcel Holtmann 
1639a9de9248SMarcel Holtmann 		/* Get remote features */
1640a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1641a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1642a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1643769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1644769be974SMarcel Holtmann 				     sizeof(cp), &cp);
164545bb4bf0SMarcel Holtmann 		}
1646a9de9248SMarcel Holtmann 
1647a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1648d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1649a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1650a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1651a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
165204124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
165304124681SGustavo F. Padovan 				     &cp);
1654a9de9248SMarcel Holtmann 		}
165517d5c04cSJohan Hedberg 	} else {
1656a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
165717d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1658744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
165948264f06SJohan Hedberg 					    conn->dst_type, ev->status);
166017d5c04cSJohan Hedberg 	}
166145bb4bf0SMarcel Holtmann 
1662e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1663e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
166445bb4bf0SMarcel Holtmann 
1665769be974SMarcel Holtmann 	if (ev->status) {
1666a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1667a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1668c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1669c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1670a9de9248SMarcel Holtmann 
1671a9de9248SMarcel Holtmann unlock:
16721da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1673a9de9248SMarcel Holtmann 
1674a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
16751da177e4SLinus Torvalds }
16761da177e4SLinus Torvalds 
16776039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
16781da177e4SLinus Torvalds {
1679a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
16801da177e4SLinus Torvalds 	int mask = hdev->link_mode;
168120714bfeSFrédéric Dalleau 	__u8 flags = 0;
16821da177e4SLinus Torvalds 
16836ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
1684807deac2SGustavo Padovan 	       ev->link_type);
16851da177e4SLinus Torvalds 
168620714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
168720714bfeSFrédéric Dalleau 				      &flags);
16881da177e4SLinus Torvalds 
1689138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1690138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
16911da177e4SLinus Torvalds 		/* Connection accepted */
1692c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
16931da177e4SLinus Torvalds 		struct hci_conn *conn;
16941da177e4SLinus Torvalds 
16951da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1696b6a0dc82SMarcel Holtmann 
1697cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1698cc11b9c1SAndrei Emeltchenko 		if (ie)
1699c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1700c7bdd502SMarcel Holtmann 
17018fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
17028fc9ced3SGustavo Padovan 					       &ev->bdaddr);
17031da177e4SLinus Torvalds 		if (!conn) {
1704cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1705cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1706893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
17071da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
17081da177e4SLinus Torvalds 				return;
17091da177e4SLinus Torvalds 			}
17101da177e4SLinus Torvalds 		}
1711b6a0dc82SMarcel Holtmann 
17121da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
1713b6a0dc82SMarcel Holtmann 
17141da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
17151da177e4SLinus Torvalds 
171620714bfeSFrédéric Dalleau 		if (ev->link_type == ACL_LINK ||
171720714bfeSFrédéric Dalleau 		    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
1718b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
171920714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1720b6a0dc82SMarcel Holtmann 
17211da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
17221da177e4SLinus Torvalds 
17231da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
17241da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
17251da177e4SLinus Torvalds 			else
17261da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
17271da177e4SLinus Torvalds 
172804124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
172904124681SGustavo F. Padovan 				     &cp);
173020714bfeSFrédéric Dalleau 		} else if (!(flags & HCI_PROTO_DEFER)) {
1731b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
173220714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1733b6a0dc82SMarcel Holtmann 
1734b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1735a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1736b6a0dc82SMarcel Holtmann 
173782781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
173882781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
173982781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1740b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1741b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1742b6a0dc82SMarcel Holtmann 
1743b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1744b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
174520714bfeSFrédéric Dalleau 		} else {
174620714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT2;
174720714bfeSFrédéric Dalleau 			hci_proto_connect_cfm(conn, 0);
1748b6a0dc82SMarcel Holtmann 		}
17491da177e4SLinus Torvalds 	} else {
17501da177e4SLinus Torvalds 		/* Connection rejected */
17511da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
17521da177e4SLinus Torvalds 
17531da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
17549f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1755a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
17561da177e4SLinus Torvalds 	}
17571da177e4SLinus Torvalds }
17581da177e4SLinus Torvalds 
1759f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
1760f0d6a0eaSMikel Astiz {
1761f0d6a0eaSMikel Astiz 	switch (err) {
1762f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
1763f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
1764f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
1765f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
1766f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
1767f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
1768f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
1769f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
1770f0d6a0eaSMikel Astiz 	default:
1771f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
1772f0d6a0eaSMikel Astiz 	}
1773f0d6a0eaSMikel Astiz }
1774f0d6a0eaSMikel Astiz 
17756039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17761da177e4SLinus Torvalds {
1777a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
177804837f64SMarcel Holtmann 	struct hci_conn *conn;
17791da177e4SLinus Torvalds 
17809f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
17811da177e4SLinus Torvalds 
17821da177e4SLinus Torvalds 	hci_dev_lock(hdev);
17831da177e4SLinus Torvalds 
178404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1785f7520543SJohan Hedberg 	if (!conn)
1786f7520543SJohan Hedberg 		goto unlock;
1787f7520543SJohan Hedberg 
178837d9ef76SJohan Hedberg 	if (ev->status == 0)
17891da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
17907d0db0a3SMarcel Holtmann 
1791b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1792b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
1793f0d6a0eaSMikel Astiz 		if (ev->status) {
179488c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
179588c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
1796f0d6a0eaSMikel Astiz 		} else {
1797f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
1798f0d6a0eaSMikel Astiz 
1799afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
1800f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
1801f0d6a0eaSMikel Astiz 		}
180237d9ef76SJohan Hedberg 	}
1803f7520543SJohan Hedberg 
180437d9ef76SJohan Hedberg 	if (ev->status == 0) {
18052210246cSJohan Hedberg 		u8 type = conn->type;
18062210246cSJohan Hedberg 
18072210246cSJohan Hedberg 		if (type == ACL_LINK && conn->flush_key)
18086ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
18092950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
18101da177e4SLinus Torvalds 		hci_conn_del(conn);
18112210246cSJohan Hedberg 
18122210246cSJohan Hedberg 		/* Re-enable advertising if necessary, since it might
18132210246cSJohan Hedberg 		 * have been disabled by the connection. From the
18142210246cSJohan Hedberg 		 * HCI_LE_Set_Advertise_Enable command description in
18152210246cSJohan Hedberg 		 * the core specification (v4.0):
18162210246cSJohan Hedberg 		 * "The Controller shall continue advertising until the Host
18172210246cSJohan Hedberg 		 * issues an LE_Set_Advertise_Enable command with
18182210246cSJohan Hedberg 		 * Advertising_Enable set to 0x00 (Advertising is disabled)
18192210246cSJohan Hedberg 		 * or until a connection is created or until the Advertising
18202210246cSJohan Hedberg 		 * is timed out due to Directed Advertising."
18212210246cSJohan Hedberg 		 */
18222210246cSJohan Hedberg 		if (type == LE_LINK)
18235976e608SMarcel Holtmann 			mgmt_reenable_advertising(hdev);
182437d9ef76SJohan Hedberg 	}
18251da177e4SLinus Torvalds 
1826f7520543SJohan Hedberg unlock:
18271da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
18281da177e4SLinus Torvalds }
18291da177e4SLinus Torvalds 
18306039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1831a9de9248SMarcel Holtmann {
1832a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1833a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1834a9de9248SMarcel Holtmann 
18359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1836a9de9248SMarcel Holtmann 
1837a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1838a9de9248SMarcel Holtmann 
1839a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1840d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1841d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1842d7556e20SWaldemar Rymarkiewicz 
1843765c2a96SJohan Hedberg 	if (!ev->status) {
1844aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
184551a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1846d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
184719f8def0SWaldemar Rymarkiewicz 		} else {
1848a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1849765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
185019f8def0SWaldemar Rymarkiewicz 		}
18512a611692SJohan Hedberg 	} else {
1852bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1853bab73cb6SJohan Hedberg 				 ev->status);
18542a611692SJohan Hedberg 	}
1855a9de9248SMarcel Holtmann 
185651a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
185751a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1858a9de9248SMarcel Holtmann 
1859f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1860aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1861f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1862f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1863f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1864d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1865d7556e20SWaldemar Rymarkiewicz 				     &cp);
1866f8558555SMarcel Holtmann 		} else {
1867f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1868f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
186976a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1870f8558555SMarcel Holtmann 		}
1871052b30b0SMarcel Holtmann 	} else {
1872a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1873a9de9248SMarcel Holtmann 
1874052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
1875052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
187676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
1877052b30b0SMarcel Holtmann 	}
1878052b30b0SMarcel Holtmann 
187951a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
1880a9de9248SMarcel Holtmann 		if (!ev->status) {
1881a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1882f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1883f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1884d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1885d7556e20SWaldemar Rymarkiewicz 				     &cp);
1886a9de9248SMarcel Holtmann 		} else {
188751a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1888a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
1889a9de9248SMarcel Holtmann 		}
1890a9de9248SMarcel Holtmann 	}
1891a9de9248SMarcel Holtmann 
1892d7556e20SWaldemar Rymarkiewicz unlock:
1893a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1894a9de9248SMarcel Holtmann }
1895a9de9248SMarcel Holtmann 
18966039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
1897a9de9248SMarcel Holtmann {
1898127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
1899127178d2SJohan Hedberg 	struct hci_conn *conn;
1900127178d2SJohan Hedberg 
1901a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1902a9de9248SMarcel Holtmann 
1903a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
1904127178d2SJohan Hedberg 
1905127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1906127178d2SJohan Hedberg 
1907127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
1908b644ba33SJohan Hedberg 
1909b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
1910b644ba33SJohan Hedberg 		goto check_auth;
1911b644ba33SJohan Hedberg 
1912b644ba33SJohan Hedberg 	if (ev->status == 0)
1913b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
1914b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
1915b644ba33SJohan Hedberg 	else
1916b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
1917b644ba33SJohan Hedberg 
1918b644ba33SJohan Hedberg check_auth:
191979c6c70cSJohan Hedberg 	if (!conn)
192079c6c70cSJohan Hedberg 		goto unlock;
192179c6c70cSJohan Hedberg 
192279c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
192379c6c70cSJohan Hedberg 		goto unlock;
192479c6c70cSJohan Hedberg 
192551a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1926127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1927127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1928127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1929127178d2SJohan Hedberg 	}
1930127178d2SJohan Hedberg 
193179c6c70cSJohan Hedberg unlock:
1932127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1933a9de9248SMarcel Holtmann }
1934a9de9248SMarcel Holtmann 
19356039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
1936a9de9248SMarcel Holtmann {
1937a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
1938a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1939a9de9248SMarcel Holtmann 
19409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1941a9de9248SMarcel Holtmann 
1942a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1943a9de9248SMarcel Holtmann 
1944a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1945a9de9248SMarcel Holtmann 	if (conn) {
1946a9de9248SMarcel Holtmann 		if (!ev->status) {
1947ae293196SMarcel Holtmann 			if (ev->encrypt) {
1948ae293196SMarcel Holtmann 				/* Encryption implies authentication */
1949ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
1950a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
1951da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
1952ae293196SMarcel Holtmann 			} else
1953a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
1954a9de9248SMarcel Holtmann 		}
1955a9de9248SMarcel Holtmann 
195651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
1957a9de9248SMarcel Holtmann 
1958a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
1959bed71748SAndre Guedes 			hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
196076a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1961a7d7723aSGustavo Padovan 			goto unlock;
1962a7d7723aSGustavo Padovan 		}
1963a7d7723aSGustavo Padovan 
1964f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1965f8558555SMarcel Holtmann 			if (!ev->status)
1966f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
1967f8558555SMarcel Holtmann 
1968f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
196976a68ba0SDavid Herrmann 			hci_conn_drop(conn);
1970f8558555SMarcel Holtmann 		} else
1971a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
1972a9de9248SMarcel Holtmann 	}
1973a9de9248SMarcel Holtmann 
1974a7d7723aSGustavo Padovan unlock:
1975a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1976a9de9248SMarcel Holtmann }
1977a9de9248SMarcel Holtmann 
19786039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
1979807deac2SGustavo Padovan 					     struct sk_buff *skb)
1980a9de9248SMarcel Holtmann {
1981a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
1982a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1983a9de9248SMarcel Holtmann 
19849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1985a9de9248SMarcel Holtmann 
1986a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1987a9de9248SMarcel Holtmann 
1988a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1989a9de9248SMarcel Holtmann 	if (conn) {
1990a9de9248SMarcel Holtmann 		if (!ev->status)
1991a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
1992a9de9248SMarcel Holtmann 
199351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
1994a9de9248SMarcel Holtmann 
1995a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
1996a9de9248SMarcel Holtmann 	}
1997a9de9248SMarcel Holtmann 
1998a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
1999a9de9248SMarcel Holtmann }
2000a9de9248SMarcel Holtmann 
20016039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2002807deac2SGustavo Padovan 				    struct sk_buff *skb)
2003a9de9248SMarcel Holtmann {
2004a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2005a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2006a9de9248SMarcel Holtmann 
20079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2008a9de9248SMarcel Holtmann 
2009a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2010a9de9248SMarcel Holtmann 
2011a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2012ccd556feSJohan Hedberg 	if (!conn)
2013ccd556feSJohan Hedberg 		goto unlock;
2014ccd556feSJohan Hedberg 
2015769be974SMarcel Holtmann 	if (!ev->status)
2016cad718edSJohan Hedberg 		memcpy(conn->features[0], ev->features, 8);
2017a9de9248SMarcel Holtmann 
2018ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2019ccd556feSJohan Hedberg 		goto unlock;
2020ccd556feSJohan Hedberg 
2021ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2022769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2023769be974SMarcel Holtmann 		cp.handle = ev->handle;
2024769be974SMarcel Holtmann 		cp.page = 0x01;
2025ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2026769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2027392599b9SJohan Hedberg 		goto unlock;
2028392599b9SJohan Hedberg 	}
2029392599b9SJohan Hedberg 
2030671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2031127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2032127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2033127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2034127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2035127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2036b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2037b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
203808c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2039b644ba33SJohan Hedberg 				      conn->dev_class);
2040392599b9SJohan Hedberg 
2041127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2042769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2043769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
204476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2045769be974SMarcel Holtmann 	}
2046769be974SMarcel Holtmann 
2047ccd556feSJohan Hedberg unlock:
2048a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2049a9de9248SMarcel Holtmann }
2050a9de9248SMarcel Holtmann 
20516039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2052a9de9248SMarcel Holtmann {
2053a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
20549238f36aSJohan Hedberg 	u8 status = skb->data[sizeof(*ev)];
2055a9de9248SMarcel Holtmann 	__u16 opcode;
2056a9de9248SMarcel Holtmann 
2057a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2058a9de9248SMarcel Holtmann 
2059a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2060a9de9248SMarcel Holtmann 
2061a9de9248SMarcel Holtmann 	switch (opcode) {
2062a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2063a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2064a9de9248SMarcel Holtmann 		break;
2065a9de9248SMarcel Holtmann 
20664d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
20674d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
20684d93483bSAndre Guedes 		break;
20694d93483bSAndre Guedes 
2070a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2071a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2072a9de9248SMarcel Holtmann 		break;
2073a9de9248SMarcel Holtmann 
2074a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2075a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2076a9de9248SMarcel Holtmann 		break;
2077a9de9248SMarcel Holtmann 
2078a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2079a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2080a9de9248SMarcel Holtmann 		break;
2081a9de9248SMarcel Holtmann 
2082e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2083e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2084e4e8e37cSMarcel Holtmann 		break;
2085e4e8e37cSMarcel Holtmann 
2086a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2087a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2088a9de9248SMarcel Holtmann 		break;
2089a9de9248SMarcel Holtmann 
2090e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2091e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2092e4e8e37cSMarcel Holtmann 		break;
2093e4e8e37cSMarcel Holtmann 
2094e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2095e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2096e4e8e37cSMarcel Holtmann 		break;
2097e4e8e37cSMarcel Holtmann 
2098a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2099a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2100a9de9248SMarcel Holtmann 		break;
2101a9de9248SMarcel Holtmann 
2102a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2103a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2104a9de9248SMarcel Holtmann 		break;
2105a9de9248SMarcel Holtmann 
2106a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2107a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2108a9de9248SMarcel Holtmann 		break;
2109a9de9248SMarcel Holtmann 
2110a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2111a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2112a9de9248SMarcel Holtmann 		break;
2113a9de9248SMarcel Holtmann 
2114a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2115a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2116a9de9248SMarcel Holtmann 		break;
2117a9de9248SMarcel Holtmann 
2118a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2119a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2120a9de9248SMarcel Holtmann 		break;
2121a9de9248SMarcel Holtmann 
2122a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2123a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2124a9de9248SMarcel Holtmann 		break;
2125a9de9248SMarcel Holtmann 
2126a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2127a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2128a9de9248SMarcel Holtmann 		break;
2129a9de9248SMarcel Holtmann 
2130a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2131a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2132a9de9248SMarcel Holtmann 		break;
2133a9de9248SMarcel Holtmann 
2134a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2135a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2136a9de9248SMarcel Holtmann 		break;
2137a9de9248SMarcel Holtmann 
2138333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2139333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2140333140b5SMarcel Holtmann 		break;
2141333140b5SMarcel Holtmann 
2142a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2143a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2144a9de9248SMarcel Holtmann 		break;
2145a9de9248SMarcel Holtmann 
2146a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2147a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2148a9de9248SMarcel Holtmann 		break;
2149a9de9248SMarcel Holtmann 
2150a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2151a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2152a9de9248SMarcel Holtmann 		break;
2153a9de9248SMarcel Holtmann 
2154971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2155971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2156971e3a4bSAndre Guedes 		break;
2157971e3a4bSAndre Guedes 
2158a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2159a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2160a9de9248SMarcel Holtmann 		break;
2161a9de9248SMarcel Holtmann 
2162a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2163a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2164a9de9248SMarcel Holtmann 		break;
2165a9de9248SMarcel Holtmann 
2166f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
2167f332ec66SJohan Hedberg 		hci_cc_read_page_scan_activity(hdev, skb);
2168f332ec66SJohan Hedberg 		break;
2169f332ec66SJohan Hedberg 
21704a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
21714a3ee763SJohan Hedberg 		hci_cc_write_page_scan_activity(hdev, skb);
21724a3ee763SJohan Hedberg 		break;
21734a3ee763SJohan Hedberg 
2174f332ec66SJohan Hedberg 	case HCI_OP_READ_PAGE_SCAN_TYPE:
2175f332ec66SJohan Hedberg 		hci_cc_read_page_scan_type(hdev, skb);
2176f332ec66SJohan Hedberg 		break;
2177f332ec66SJohan Hedberg 
21784a3ee763SJohan Hedberg 	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
21794a3ee763SJohan Hedberg 		hci_cc_write_page_scan_type(hdev, skb);
21804a3ee763SJohan Hedberg 		break;
21814a3ee763SJohan Hedberg 
2182350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2183350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2184350ee4cfSAndrei Emeltchenko 		break;
2185350ee4cfSAndrei Emeltchenko 
21861e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
21871e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
21881e89cffbSAndrei Emeltchenko 		break;
21891e89cffbSAndrei Emeltchenko 
2190928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2191928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2192928abaa7SAndrei Emeltchenko 		break;
2193928abaa7SAndrei Emeltchenko 
2194903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2195903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2196903e4541SAndrei Emeltchenko 		break;
2197903e4541SAndrei Emeltchenko 
2198d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2199d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2200d5859e22SJohan Hedberg 		break;
2201d5859e22SJohan Hedberg 
2202980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2203980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2204980e1a53SJohan Hedberg 		break;
2205980e1a53SJohan Hedberg 
2206980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2207980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2208980e1a53SJohan Hedberg 		break;
2209980e1a53SJohan Hedberg 
2210c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2211c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2212c35938b2SSzymon Janc 		break;
2213c35938b2SSzymon Janc 
22146ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
22156ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
22166ed58ec5SVille Tervo 		break;
22176ed58ec5SVille Tervo 
221860e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
221960e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
222060e77321SJohan Hedberg 		break;
222160e77321SJohan Hedberg 
22228fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
22238fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
22248fa19098SJohan Hedberg 		break;
22258fa19098SJohan Hedberg 
2226a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2227a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2228a5c29683SJohan Hedberg 		break;
2229a5c29683SJohan Hedberg 
2230a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2231a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2232a5c29683SJohan Hedberg 		break;
2233a5c29683SJohan Hedberg 
22341143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
22351143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
22361143d458SBrian Gix 		break;
22371143d458SBrian Gix 
22381143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
22391143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
224016cde993SSzymon Janc 		break;
224107f7fa5dSAndre Guedes 
2242c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2243c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2244c1d5dc4aSJohan Hedberg 		break;
2245c1d5dc4aSJohan Hedberg 
2246eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2247eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2248eb9d91f5SAndre Guedes 		break;
2249eb9d91f5SAndre Guedes 
2250cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2251cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2252cf1d081fSJohan Hedberg 		break;
2253cf1d081fSJohan Hedberg 
22549b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
22559b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
22569b008c04SJohan Hedberg 		break;
22579b008c04SJohan Hedberg 
2258f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2259f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2260f9b49306SAndre Guedes 		break;
2261f9b49306SAndre Guedes 
226293c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
226393c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
226493c284eeSAndrei Emeltchenko 		break;
226593c284eeSAndrei Emeltchenko 
2266a9de9248SMarcel Holtmann 	default:
22679f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2268a9de9248SMarcel Holtmann 		break;
2269a9de9248SMarcel Holtmann 	}
2270a9de9248SMarcel Holtmann 
2271ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
22726bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
22736bd32326SVille Tervo 
2274ad82cdd1SJohan Hedberg 	hci_req_cmd_complete(hdev, opcode, status);
22759238f36aSJohan Hedberg 
2276dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2277a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2278a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2279c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2280a9de9248SMarcel Holtmann 	}
2281a9de9248SMarcel Holtmann }
2282a9de9248SMarcel Holtmann 
22836039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2284a9de9248SMarcel Holtmann {
2285a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2286a9de9248SMarcel Holtmann 	__u16 opcode;
2287a9de9248SMarcel Holtmann 
2288a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2289a9de9248SMarcel Holtmann 
2290a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2291a9de9248SMarcel Holtmann 
2292a9de9248SMarcel Holtmann 	switch (opcode) {
2293a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2294a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2295a9de9248SMarcel Holtmann 		break;
2296a9de9248SMarcel Holtmann 
2297a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2298a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2299a9de9248SMarcel Holtmann 		break;
2300a9de9248SMarcel Holtmann 
2301a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2302a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2303a9de9248SMarcel Holtmann 		break;
2304a9de9248SMarcel Holtmann 
2305f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2306f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2307f8558555SMarcel Holtmann 		break;
2308f8558555SMarcel Holtmann 
2309f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2310f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2311f8558555SMarcel Holtmann 		break;
2312f8558555SMarcel Holtmann 
2313a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2314a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2315a9de9248SMarcel Holtmann 		break;
2316a9de9248SMarcel Holtmann 
2317769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2318769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2319769be974SMarcel Holtmann 		break;
2320769be974SMarcel Holtmann 
2321769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2322769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2323769be974SMarcel Holtmann 		break;
2324769be974SMarcel Holtmann 
2325a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2326a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2327a9de9248SMarcel Holtmann 		break;
2328a9de9248SMarcel Holtmann 
2329a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2330a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2331a9de9248SMarcel Holtmann 		break;
2332a9de9248SMarcel Holtmann 
2333a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2334a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2335a9de9248SMarcel Holtmann 		break;
2336a9de9248SMarcel Holtmann 
23378962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
233888c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
23398962ee74SJohan Hedberg 		break;
23408962ee74SJohan Hedberg 
2341a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2342a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2343a02226d6SAndrei Emeltchenko 		break;
2344a02226d6SAndrei Emeltchenko 
23450b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
23460b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
23470b26ab9dSAndrei Emeltchenko 		break;
23480b26ab9dSAndrei Emeltchenko 
2349a9de9248SMarcel Holtmann 	default:
23509f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2351a9de9248SMarcel Holtmann 		break;
2352a9de9248SMarcel Holtmann 	}
2353a9de9248SMarcel Holtmann 
2354ad82cdd1SJohan Hedberg 	if (opcode != HCI_OP_NOP)
23556bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
23566bd32326SVille Tervo 
235702350a72SJohan Hedberg 	if (ev->status ||
235802350a72SJohan Hedberg 	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
235933720450SAndre Guedes 		hci_req_cmd_complete(hdev, opcode, ev->status);
23609238f36aSJohan Hedberg 
236110572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2362a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2363a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2364c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2365a9de9248SMarcel Holtmann 	}
2366a9de9248SMarcel Holtmann }
2367a9de9248SMarcel Holtmann 
23686039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2369a9de9248SMarcel Holtmann {
2370a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2371a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2372a9de9248SMarcel Holtmann 
23739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2374a9de9248SMarcel Holtmann 
2375a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2376a9de9248SMarcel Holtmann 
2377a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2378a9de9248SMarcel Holtmann 	if (conn) {
2379a9de9248SMarcel Holtmann 		if (!ev->status) {
2380a9de9248SMarcel Holtmann 			if (ev->role)
2381a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2382a9de9248SMarcel Holtmann 			else
2383a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2384a9de9248SMarcel Holtmann 		}
2385a9de9248SMarcel Holtmann 
238651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2387a9de9248SMarcel Holtmann 
2388a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2389a9de9248SMarcel Holtmann 	}
2390a9de9248SMarcel Holtmann 
2391a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2392a9de9248SMarcel Holtmann }
2393a9de9248SMarcel Holtmann 
23946039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
23951da177e4SLinus Torvalds {
2396a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
23971da177e4SLinus Torvalds 	int i;
23981da177e4SLinus Torvalds 
239932ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
240032ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
240132ac5b9bSAndrei Emeltchenko 		return;
240232ac5b9bSAndrei Emeltchenko 	}
240332ac5b9bSAndrei Emeltchenko 
2404c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2405c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
24061da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
24071da177e4SLinus Torvalds 		return;
24081da177e4SLinus Torvalds 	}
24091da177e4SLinus Torvalds 
2410c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2411c5993de8SAndrei Emeltchenko 
2412613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2413613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
24141da177e4SLinus Torvalds 		struct hci_conn *conn;
24151da177e4SLinus Torvalds 		__u16  handle, count;
24161da177e4SLinus Torvalds 
2417613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2418613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
24191da177e4SLinus Torvalds 
24201da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2421f4280918SAndrei Emeltchenko 		if (!conn)
2422f4280918SAndrei Emeltchenko 			continue;
2423f4280918SAndrei Emeltchenko 
24241da177e4SLinus Torvalds 		conn->sent -= count;
24251da177e4SLinus Torvalds 
2426f4280918SAndrei Emeltchenko 		switch (conn->type) {
2427f4280918SAndrei Emeltchenko 		case ACL_LINK:
242870f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
242970f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
24301da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2431f4280918SAndrei Emeltchenko 			break;
2432f4280918SAndrei Emeltchenko 
2433f4280918SAndrei Emeltchenko 		case LE_LINK:
24346ed58ec5SVille Tervo 			if (hdev->le_pkts) {
24356ed58ec5SVille Tervo 				hdev->le_cnt += count;
24366ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
24376ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
24386ed58ec5SVille Tervo 			} else {
24396ed58ec5SVille Tervo 				hdev->acl_cnt += count;
24406ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
24416ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
24426ed58ec5SVille Tervo 			}
2443f4280918SAndrei Emeltchenko 			break;
2444f4280918SAndrei Emeltchenko 
2445f4280918SAndrei Emeltchenko 		case SCO_LINK:
244670f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
244770f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
24485b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2449f4280918SAndrei Emeltchenko 			break;
2450f4280918SAndrei Emeltchenko 
2451f4280918SAndrei Emeltchenko 		default:
2452f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2453f4280918SAndrei Emeltchenko 			break;
24541da177e4SLinus Torvalds 		}
24551da177e4SLinus Torvalds 	}
2456a9de9248SMarcel Holtmann 
24573eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
24581da177e4SLinus Torvalds }
24591da177e4SLinus Torvalds 
246076ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
246176ef7cf7SAndrei Emeltchenko 						 __u16 handle)
246276ef7cf7SAndrei Emeltchenko {
246376ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
246476ef7cf7SAndrei Emeltchenko 
246576ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
246676ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
246776ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
246876ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
246976ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
247076ef7cf7SAndrei Emeltchenko 		if (chan)
247176ef7cf7SAndrei Emeltchenko 			return chan->conn;
247276ef7cf7SAndrei Emeltchenko 		break;
247376ef7cf7SAndrei Emeltchenko 	default:
247476ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
247576ef7cf7SAndrei Emeltchenko 		break;
247676ef7cf7SAndrei Emeltchenko 	}
247776ef7cf7SAndrei Emeltchenko 
247876ef7cf7SAndrei Emeltchenko 	return NULL;
247976ef7cf7SAndrei Emeltchenko }
248076ef7cf7SAndrei Emeltchenko 
24816039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
248225e89e99SAndrei Emeltchenko {
248325e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
248425e89e99SAndrei Emeltchenko 	int i;
248525e89e99SAndrei Emeltchenko 
248625e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
248725e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
248825e89e99SAndrei Emeltchenko 		return;
248925e89e99SAndrei Emeltchenko 	}
249025e89e99SAndrei Emeltchenko 
249125e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
249225e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
249325e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
249425e89e99SAndrei Emeltchenko 		return;
249525e89e99SAndrei Emeltchenko 	}
249625e89e99SAndrei Emeltchenko 
249725e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
249825e89e99SAndrei Emeltchenko 	       ev->num_hndl);
249925e89e99SAndrei Emeltchenko 
250025e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
250125e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
250276ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
250325e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
250425e89e99SAndrei Emeltchenko 
250525e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
250625e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
250725e89e99SAndrei Emeltchenko 
250876ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
250925e89e99SAndrei Emeltchenko 		if (!conn)
251025e89e99SAndrei Emeltchenko 			continue;
251125e89e99SAndrei Emeltchenko 
251225e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
251325e89e99SAndrei Emeltchenko 
251425e89e99SAndrei Emeltchenko 		switch (conn->type) {
251525e89e99SAndrei Emeltchenko 		case ACL_LINK:
2516bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
251725e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
251825e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
251925e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
252025e89e99SAndrei Emeltchenko 			break;
252125e89e99SAndrei Emeltchenko 
252225e89e99SAndrei Emeltchenko 		default:
252325e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
252425e89e99SAndrei Emeltchenko 			break;
252525e89e99SAndrei Emeltchenko 		}
252625e89e99SAndrei Emeltchenko 	}
252725e89e99SAndrei Emeltchenko 
252825e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
252925e89e99SAndrei Emeltchenko }
253025e89e99SAndrei Emeltchenko 
25316039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
25321da177e4SLinus Torvalds {
2533a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
253404837f64SMarcel Holtmann 	struct hci_conn *conn;
25351da177e4SLinus Torvalds 
25369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
25371da177e4SLinus Torvalds 
25381da177e4SLinus Torvalds 	hci_dev_lock(hdev);
25391da177e4SLinus Torvalds 
254004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
254104837f64SMarcel Holtmann 	if (conn) {
254204837f64SMarcel Holtmann 		conn->mode = ev->mode;
254304837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
254404837f64SMarcel Holtmann 
25458fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
25468fc9ced3SGustavo Padovan 					&conn->flags)) {
254704837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
254858a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
254904837f64SMarcel Holtmann 			else
255058a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
255104837f64SMarcel Holtmann 		}
2552e73439d8SMarcel Holtmann 
255351a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2554e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
255504837f64SMarcel Holtmann 	}
255604837f64SMarcel Holtmann 
255704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
255804837f64SMarcel Holtmann }
255904837f64SMarcel Holtmann 
25606039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25611da177e4SLinus Torvalds {
2562052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2563052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2564052b30b0SMarcel Holtmann 
2565a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2566052b30b0SMarcel Holtmann 
2567052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2568052b30b0SMarcel Holtmann 
2569052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2570b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2571b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2572b6f98044SWaldemar Rymarkiewicz 
2573b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2574052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2575052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
257676a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2577052b30b0SMarcel Holtmann 	}
2578052b30b0SMarcel Holtmann 
2579a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
258003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
258103b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2582a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2583a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2584a770bb5aSWaldemar Rymarkiewicz 
2585a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2586a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2587a770bb5aSWaldemar Rymarkiewicz 		else
2588a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2589a770bb5aSWaldemar Rymarkiewicz 
2590744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2591a770bb5aSWaldemar Rymarkiewicz 	}
2592980e1a53SJohan Hedberg 
2593b6f98044SWaldemar Rymarkiewicz unlock:
2594052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
25951da177e4SLinus Torvalds }
25961da177e4SLinus Torvalds 
25976039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
25981da177e4SLinus Torvalds {
259955ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
260055ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
260155ed8ca1SJohan Hedberg 	struct hci_conn *conn;
260255ed8ca1SJohan Hedberg 	struct link_key *key;
260355ed8ca1SJohan Hedberg 
2604a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
260555ed8ca1SJohan Hedberg 
2606034cbea0SAndrei Emeltchenko 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
260755ed8ca1SJohan Hedberg 		return;
260855ed8ca1SJohan Hedberg 
260955ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
261055ed8ca1SJohan Hedberg 
261155ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
261255ed8ca1SJohan Hedberg 	if (!key) {
26136ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
26146ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
261555ed8ca1SJohan Hedberg 		goto not_found;
261655ed8ca1SJohan Hedberg 	}
261755ed8ca1SJohan Hedberg 
26186ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
26196ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
262055ed8ca1SJohan Hedberg 
2621a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2622b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
262355ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
262455ed8ca1SJohan Hedberg 		goto not_found;
262555ed8ca1SJohan Hedberg 	}
262655ed8ca1SJohan Hedberg 
262755ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
262860b83f57SWaldemar Rymarkiewicz 	if (conn) {
262960b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2630807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
263155ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
263255ed8ca1SJohan Hedberg 			goto not_found;
263355ed8ca1SJohan Hedberg 		}
263455ed8ca1SJohan Hedberg 
263560b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
263660b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
26378fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
26388fc9ced3SGustavo Padovan 			       hdev->name);
263960b83f57SWaldemar Rymarkiewicz 			goto not_found;
264060b83f57SWaldemar Rymarkiewicz 		}
264160b83f57SWaldemar Rymarkiewicz 
264260b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
264360b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
264460b83f57SWaldemar Rymarkiewicz 	}
264560b83f57SWaldemar Rymarkiewicz 
264655ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
26479b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
264855ed8ca1SJohan Hedberg 
264955ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
265055ed8ca1SJohan Hedberg 
265155ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
265255ed8ca1SJohan Hedberg 
265355ed8ca1SJohan Hedberg 	return;
265455ed8ca1SJohan Hedberg 
265555ed8ca1SJohan Hedberg not_found:
265655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
265755ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
26581da177e4SLinus Torvalds }
26591da177e4SLinus Torvalds 
26606039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
26611da177e4SLinus Torvalds {
2662052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2663052b30b0SMarcel Holtmann 	struct hci_conn *conn;
266455ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2665052b30b0SMarcel Holtmann 
2666a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2667052b30b0SMarcel Holtmann 
2668052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2669052b30b0SMarcel Holtmann 
2670052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2671052b30b0SMarcel Holtmann 	if (conn) {
2672052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2673052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2674980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
267513d39315SWaldemar Rymarkiewicz 
267613d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
267713d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
267813d39315SWaldemar Rymarkiewicz 
267976a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2680052b30b0SMarcel Holtmann 	}
2681052b30b0SMarcel Holtmann 
2682034cbea0SAndrei Emeltchenko 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
2683d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
268455ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
268555ed8ca1SJohan Hedberg 
2686052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26871da177e4SLinus Torvalds }
26881da177e4SLinus Torvalds 
26896039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
269004837f64SMarcel Holtmann {
2691a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
269204837f64SMarcel Holtmann 	struct hci_conn *conn;
269304837f64SMarcel Holtmann 
26949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
269504837f64SMarcel Holtmann 
269604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
269704837f64SMarcel Holtmann 
269804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
26991da177e4SLinus Torvalds 	if (conn && !ev->status) {
27001da177e4SLinus Torvalds 		struct inquiry_entry *ie;
27011da177e4SLinus Torvalds 
2702cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2703cc11b9c1SAndrei Emeltchenko 		if (ie) {
27041da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
27051da177e4SLinus Torvalds 			ie->timestamp = jiffies;
27061da177e4SLinus Torvalds 		}
27071da177e4SLinus Torvalds 	}
27081da177e4SLinus Torvalds 
27091da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
27101da177e4SLinus Torvalds }
27111da177e4SLinus Torvalds 
27126039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2713a8746417SMarcel Holtmann {
2714a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2715a8746417SMarcel Holtmann 	struct hci_conn *conn;
2716a8746417SMarcel Holtmann 
27179f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2718a8746417SMarcel Holtmann 
2719a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2720a8746417SMarcel Holtmann 
2721a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2722a8746417SMarcel Holtmann 	if (conn && !ev->status)
2723a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2724a8746417SMarcel Holtmann 
2725a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2726a8746417SMarcel Holtmann }
2727a8746417SMarcel Holtmann 
27286039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
272985a1e930SMarcel Holtmann {
2730a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
273185a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
273285a1e930SMarcel Holtmann 
273385a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
273485a1e930SMarcel Holtmann 
273585a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
273685a1e930SMarcel Holtmann 
2737cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2738cc11b9c1SAndrei Emeltchenko 	if (ie) {
273985a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
274085a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
274185a1e930SMarcel Holtmann 	}
274285a1e930SMarcel Holtmann 
274385a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
274485a1e930SMarcel Holtmann }
274585a1e930SMarcel Holtmann 
27466039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2747807deac2SGustavo Padovan 					     struct sk_buff *skb)
2748a9de9248SMarcel Holtmann {
2749a9de9248SMarcel Holtmann 	struct inquiry_data data;
2750a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2751388fc8faSJohan Hedberg 	bool name_known, ssp;
2752a9de9248SMarcel Holtmann 
2753a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2754a9de9248SMarcel Holtmann 
2755a9de9248SMarcel Holtmann 	if (!num_rsp)
2756a9de9248SMarcel Holtmann 		return;
2757a9de9248SMarcel Holtmann 
27581519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
27591519cc17SAndre Guedes 		return;
27601519cc17SAndre Guedes 
2761a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2762a9de9248SMarcel Holtmann 
2763a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2764138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2765138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2766a9de9248SMarcel Holtmann 
2767e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2768a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2769a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2770a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2771a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2772a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2773a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2774a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
277541a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27763175405bSJohan Hedberg 
27773175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2778388fc8faSJohan Hedberg 							      false, &ssp);
277948264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2780e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2781388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2782a9de9248SMarcel Holtmann 		}
2783a9de9248SMarcel Holtmann 	} else {
2784a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2785a9de9248SMarcel Holtmann 
2786e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2787a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2788a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2789a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2790a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2791a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2792a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2793a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
279441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
27953175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2796388fc8faSJohan Hedberg 							      false, &ssp);
279748264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2798e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2799388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2800a9de9248SMarcel Holtmann 		}
2801a9de9248SMarcel Holtmann 	}
2802a9de9248SMarcel Holtmann 
2803a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2804a9de9248SMarcel Holtmann }
2805a9de9248SMarcel Holtmann 
28066039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2807807deac2SGustavo Padovan 					struct sk_buff *skb)
2808a9de9248SMarcel Holtmann {
280941a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
281041a96212SMarcel Holtmann 	struct hci_conn *conn;
281141a96212SMarcel Holtmann 
2812a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
281341a96212SMarcel Holtmann 
281441a96212SMarcel Holtmann 	hci_dev_lock(hdev);
281541a96212SMarcel Holtmann 
281641a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2817ccd556feSJohan Hedberg 	if (!conn)
2818ccd556feSJohan Hedberg 		goto unlock;
2819ccd556feSJohan Hedberg 
2820cad718edSJohan Hedberg 	if (ev->page < HCI_MAX_PAGES)
2821cad718edSJohan Hedberg 		memcpy(conn->features[ev->page], ev->features, 8);
2822cad718edSJohan Hedberg 
2823769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
282441a96212SMarcel Holtmann 		struct inquiry_entry *ie;
282541a96212SMarcel Holtmann 
2826cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2827cc11b9c1SAndrei Emeltchenko 		if (ie)
282802b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
282941a96212SMarcel Holtmann 
2830bbb0eadaSJaganath Kanakkassery 		if (ev->features[0] & LMP_HOST_SSP) {
283158a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
2832bbb0eadaSJaganath Kanakkassery 		} else {
2833bbb0eadaSJaganath Kanakkassery 			/* It is mandatory by the Bluetooth specification that
2834bbb0eadaSJaganath Kanakkassery 			 * Extended Inquiry Results are only used when Secure
2835bbb0eadaSJaganath Kanakkassery 			 * Simple Pairing is enabled, but some devices violate
2836bbb0eadaSJaganath Kanakkassery 			 * this.
2837bbb0eadaSJaganath Kanakkassery 			 *
2838bbb0eadaSJaganath Kanakkassery 			 * To make these devices work, the internal SSP
2839bbb0eadaSJaganath Kanakkassery 			 * enabled flag needs to be cleared if the remote host
2840bbb0eadaSJaganath Kanakkassery 			 * features do not indicate SSP support */
2841bbb0eadaSJaganath Kanakkassery 			clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
2842bbb0eadaSJaganath Kanakkassery 		}
284341a96212SMarcel Holtmann 	}
284441a96212SMarcel Holtmann 
2845ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2846ccd556feSJohan Hedberg 		goto unlock;
2847ccd556feSJohan Hedberg 
2848671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2849127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2850127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2851127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2852127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2853127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2854b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2855b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
285608c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2857b644ba33SJohan Hedberg 				      conn->dev_class);
2858392599b9SJohan Hedberg 
2859127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2860769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2861769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
286276a68ba0SDavid Herrmann 		hci_conn_drop(conn);
2863769be974SMarcel Holtmann 	}
2864769be974SMarcel Holtmann 
2865ccd556feSJohan Hedberg unlock:
286641a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2867a9de9248SMarcel Holtmann }
2868a9de9248SMarcel Holtmann 
28696039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2870807deac2SGustavo Padovan 				       struct sk_buff *skb)
2871a9de9248SMarcel Holtmann {
2872b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2873b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2874b6a0dc82SMarcel Holtmann 
28759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2876b6a0dc82SMarcel Holtmann 
2877b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2878b6a0dc82SMarcel Holtmann 
2879b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
28809dc0a3afSMarcel Holtmann 	if (!conn) {
28819dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
28829dc0a3afSMarcel Holtmann 			goto unlock;
28839dc0a3afSMarcel Holtmann 
28849dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2885b6a0dc82SMarcel Holtmann 		if (!conn)
2886b6a0dc82SMarcel Holtmann 			goto unlock;
2887b6a0dc82SMarcel Holtmann 
28889dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
28899dc0a3afSMarcel Holtmann 	}
28909dc0a3afSMarcel Holtmann 
2891732547f9SMarcel Holtmann 	switch (ev->status) {
2892732547f9SMarcel Holtmann 	case 0x00:
2893732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2894732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2895732547f9SMarcel Holtmann 
2896732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2897732547f9SMarcel Holtmann 		break;
2898732547f9SMarcel Holtmann 
28991a4c958cSFrédéric Dalleau 	case 0x0d:	/* Connection Rejected due to Limited Resources */
2900705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2901732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29021038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2903732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
29042dea632fSFrédéric Dalleau 		if (conn->out) {
2905efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2906efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
29072dea632fSFrédéric Dalleau 			if (hci_setup_sync(conn, conn->link->handle))
2908efc7688bSMarcel Holtmann 				goto unlock;
2909efc7688bSMarcel Holtmann 		}
2910732547f9SMarcel Holtmann 		/* fall through */
2911efc7688bSMarcel Holtmann 
2912732547f9SMarcel Holtmann 	default:
2913b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2914732547f9SMarcel Holtmann 		break;
2915732547f9SMarcel Holtmann 	}
2916b6a0dc82SMarcel Holtmann 
2917b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
2918b6a0dc82SMarcel Holtmann 	if (ev->status)
2919b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
2920b6a0dc82SMarcel Holtmann 
2921b6a0dc82SMarcel Holtmann unlock:
2922b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
2923a9de9248SMarcel Holtmann }
2924a9de9248SMarcel Holtmann 
29256039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
2926807deac2SGustavo Padovan 					    struct sk_buff *skb)
2927a9de9248SMarcel Holtmann {
2928a9de9248SMarcel Holtmann 	struct inquiry_data data;
2929a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
2930a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
29319d939d94SVishal Agarwal 	size_t eir_len;
2932a9de9248SMarcel Holtmann 
2933a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2934a9de9248SMarcel Holtmann 
2935a9de9248SMarcel Holtmann 	if (!num_rsp)
2936a9de9248SMarcel Holtmann 		return;
2937a9de9248SMarcel Holtmann 
29381519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
29391519cc17SAndre Guedes 		return;
29401519cc17SAndre Guedes 
2941a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2942a9de9248SMarcel Holtmann 
2943e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
2944388fc8faSJohan Hedberg 		bool name_known, ssp;
2945561aafbcSJohan Hedberg 
2946a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
2947a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
2948a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
2949a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
2950a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
2951a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
2952a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
295341a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
2954561aafbcSJohan Hedberg 
2955a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
29564ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
29574ddb1930SJohan Hedberg 						       sizeof(info->data),
29584ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
2959561aafbcSJohan Hedberg 		else
2960561aafbcSJohan Hedberg 			name_known = true;
2961561aafbcSJohan Hedberg 
2962388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
2963388fc8faSJohan Hedberg 						      &ssp);
29649d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
296548264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
296604124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
29679d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
2968a9de9248SMarcel Holtmann 	}
2969a9de9248SMarcel Holtmann 
2970a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2971a9de9248SMarcel Holtmann }
2972a9de9248SMarcel Holtmann 
29731c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
29741c2e0041SJohan Hedberg 					 struct sk_buff *skb)
29751c2e0041SJohan Hedberg {
29761c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
29771c2e0041SJohan Hedberg 	struct hci_conn *conn;
29781c2e0041SJohan Hedberg 
29799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
29801c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
29811c2e0041SJohan Hedberg 
29821c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
29831c2e0041SJohan Hedberg 
29841c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
29851c2e0041SJohan Hedberg 	if (!conn)
29861c2e0041SJohan Hedberg 		goto unlock;
29871c2e0041SJohan Hedberg 
29881c2e0041SJohan Hedberg 	if (!ev->status)
29891c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
29901c2e0041SJohan Hedberg 
29911c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
29921c2e0041SJohan Hedberg 
29931c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
2994bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
299576a68ba0SDavid Herrmann 		hci_conn_drop(conn);
29961c2e0041SJohan Hedberg 		goto unlock;
29971c2e0041SJohan Hedberg 	}
29981c2e0041SJohan Hedberg 
29991c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
30001c2e0041SJohan Hedberg 		if (!ev->status)
30011c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
30021c2e0041SJohan Hedberg 
30031c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
300476a68ba0SDavid Herrmann 		hci_conn_drop(conn);
30051c2e0041SJohan Hedberg 	} else {
30061c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
30071c2e0041SJohan Hedberg 
30081c2e0041SJohan Hedberg 		hci_conn_hold(conn);
30091c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
301076a68ba0SDavid Herrmann 		hci_conn_drop(conn);
30111c2e0041SJohan Hedberg 	}
30121c2e0041SJohan Hedberg 
30131c2e0041SJohan Hedberg unlock:
30141c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
30151c2e0041SJohan Hedberg }
30161c2e0041SJohan Hedberg 
30176039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
301817fa4b9dSJohan Hedberg {
301917fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
3020acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_DEDICATED_BONDING ||
3021acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_DEDICATED_BONDING_MITM) {
302217fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
302317fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
3024acabae96SMikel Astiz 		if (conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT ||
3025acabae96SMikel Astiz 		    conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)
3026acabae96SMikel Astiz 			return HCI_AT_DEDICATED_BONDING;
302717fa4b9dSJohan Hedberg 		else
3028acabae96SMikel Astiz 			return HCI_AT_DEDICATED_BONDING_MITM;
302917fa4b9dSJohan Hedberg 	}
303017fa4b9dSJohan Hedberg 
303117fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
3032acabae96SMikel Astiz 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
3033acabae96SMikel Astiz 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
303458797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
303517fa4b9dSJohan Hedberg 
303617fa4b9dSJohan Hedberg 	return conn->auth_type;
303717fa4b9dSJohan Hedberg }
303817fa4b9dSJohan Hedberg 
30396039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
30400493684eSMarcel Holtmann {
30410493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
30420493684eSMarcel Holtmann 	struct hci_conn *conn;
30430493684eSMarcel Holtmann 
30440493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
30450493684eSMarcel Holtmann 
30460493684eSMarcel Holtmann 	hci_dev_lock(hdev);
30470493684eSMarcel Holtmann 
30480493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
304903b555e1SJohan Hedberg 	if (!conn)
305003b555e1SJohan Hedberg 		goto unlock;
305103b555e1SJohan Hedberg 
30520493684eSMarcel Holtmann 	hci_conn_hold(conn);
30530493684eSMarcel Holtmann 
3054a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
305503b555e1SJohan Hedberg 		goto unlock;
305603b555e1SJohan Hedberg 
3057a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
305803b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
305917fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
306017fa4b9dSJohan Hedberg 
306117fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30627a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
30637a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
30647a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
3065a767631aSMikel Astiz 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
30667cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
30677cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
306817fa4b9dSJohan Hedberg 
30698fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
30708fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3071ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3072ce85ee13SSzymon Janc 		else
3073ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3074ce85ee13SSzymon Janc 
307517fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
307617fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
307703b555e1SJohan Hedberg 	} else {
307803b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
307903b555e1SJohan Hedberg 
308003b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
30819f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
308203b555e1SJohan Hedberg 
308303b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
308403b555e1SJohan Hedberg 			     sizeof(cp), &cp);
308503b555e1SJohan Hedberg 	}
308603b555e1SJohan Hedberg 
308703b555e1SJohan Hedberg unlock:
308803b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
308903b555e1SJohan Hedberg }
309003b555e1SJohan Hedberg 
30916039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
309203b555e1SJohan Hedberg {
309303b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
309403b555e1SJohan Hedberg 	struct hci_conn *conn;
309503b555e1SJohan Hedberg 
309603b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
309703b555e1SJohan Hedberg 
309803b555e1SJohan Hedberg 	hci_dev_lock(hdev);
309903b555e1SJohan Hedberg 
310003b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
310103b555e1SJohan Hedberg 	if (!conn)
310203b555e1SJohan Hedberg 		goto unlock;
310303b555e1SJohan Hedberg 
310403b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
310503b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
310658a681efSJohan Hedberg 	if (ev->oob_data)
310758a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
310803b555e1SJohan Hedberg 
310903b555e1SJohan Hedberg unlock:
31100493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
31110493684eSMarcel Holtmann }
31120493684eSMarcel Holtmann 
31136039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3114a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3115a5c29683SJohan Hedberg {
3116a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
311755bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
31187a828908SJohan Hedberg 	struct hci_conn *conn;
3119a5c29683SJohan Hedberg 
3120a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3121a5c29683SJohan Hedberg 
3122a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3123a5c29683SJohan Hedberg 
3124a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
31257a828908SJohan Hedberg 		goto unlock;
31267a828908SJohan Hedberg 
31277a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
31287a828908SJohan Hedberg 	if (!conn)
31297a828908SJohan Hedberg 		goto unlock;
31307a828908SJohan Hedberg 
31317a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
31327a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
31337a828908SJohan Hedberg 
31347a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
31357a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
31367a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
31377a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
31387a828908SJohan Hedberg 	 * bit set. */
3139a767631aSMikel Astiz 	if (!conn->connect_cfm_cb && loc_mitm &&
3140a767631aSMikel Astiz 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
31417a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
31427a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
31437a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
31447a828908SJohan Hedberg 		goto unlock;
31457a828908SJohan Hedberg 	}
31467a828908SJohan Hedberg 
31477a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
3148a767631aSMikel Astiz 	if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
3149a767631aSMikel Astiz 	    (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
315055bc1a37SJohan Hedberg 
315155bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
315255bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
315355bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
315451a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
315555bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
315655bc1a37SJohan Hedberg 			confirm_hint = 1;
315755bc1a37SJohan Hedberg 			goto confirm;
315855bc1a37SJohan Hedberg 		}
315955bc1a37SJohan Hedberg 
31609f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
31619f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
31629f61656aSJohan Hedberg 
31639f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
31649f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
31659f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
31669f61656aSJohan Hedberg 			goto unlock;
31679f61656aSJohan Hedberg 		}
31689f61656aSJohan Hedberg 
31697a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
31707a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
31717a828908SJohan Hedberg 		goto unlock;
31727a828908SJohan Hedberg 	}
31737a828908SJohan Hedberg 
317455bc1a37SJohan Hedberg confirm:
3175272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
317655bc1a37SJohan Hedberg 				  confirm_hint);
3177a5c29683SJohan Hedberg 
31787a828908SJohan Hedberg unlock:
3179a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3180a5c29683SJohan Hedberg }
3181a5c29683SJohan Hedberg 
31826039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
31831143d458SBrian Gix 					 struct sk_buff *skb)
31841143d458SBrian Gix {
31851143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
31861143d458SBrian Gix 
31871143d458SBrian Gix 	BT_DBG("%s", hdev->name);
31881143d458SBrian Gix 
3189a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3190272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
31911143d458SBrian Gix }
31921143d458SBrian Gix 
319392a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
319492a25256SJohan Hedberg 					struct sk_buff *skb)
319592a25256SJohan Hedberg {
319692a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
319792a25256SJohan Hedberg 	struct hci_conn *conn;
319892a25256SJohan Hedberg 
319992a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
320092a25256SJohan Hedberg 
320192a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
320292a25256SJohan Hedberg 	if (!conn)
320392a25256SJohan Hedberg 		return;
320492a25256SJohan Hedberg 
320592a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
320692a25256SJohan Hedberg 	conn->passkey_entered = 0;
320792a25256SJohan Hedberg 
320892a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
320992a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
321092a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
321192a25256SJohan Hedberg 					 conn->passkey_entered);
321292a25256SJohan Hedberg }
321392a25256SJohan Hedberg 
321492a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
321592a25256SJohan Hedberg {
321692a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
321792a25256SJohan Hedberg 	struct hci_conn *conn;
321892a25256SJohan Hedberg 
321992a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
322092a25256SJohan Hedberg 
322192a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
322292a25256SJohan Hedberg 	if (!conn)
322392a25256SJohan Hedberg 		return;
322492a25256SJohan Hedberg 
322592a25256SJohan Hedberg 	switch (ev->type) {
322692a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
322792a25256SJohan Hedberg 		conn->passkey_entered = 0;
322892a25256SJohan Hedberg 		return;
322992a25256SJohan Hedberg 
323092a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
323192a25256SJohan Hedberg 		conn->passkey_entered++;
323292a25256SJohan Hedberg 		break;
323392a25256SJohan Hedberg 
323492a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
323592a25256SJohan Hedberg 		conn->passkey_entered--;
323692a25256SJohan Hedberg 		break;
323792a25256SJohan Hedberg 
323892a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
323992a25256SJohan Hedberg 		conn->passkey_entered = 0;
324092a25256SJohan Hedberg 		break;
324192a25256SJohan Hedberg 
324292a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
324392a25256SJohan Hedberg 		return;
324492a25256SJohan Hedberg 	}
324592a25256SJohan Hedberg 
324692a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
324792a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
324892a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
324992a25256SJohan Hedberg 					 conn->passkey_entered);
325092a25256SJohan Hedberg }
325192a25256SJohan Hedberg 
32526039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3253807deac2SGustavo Padovan 					 struct sk_buff *skb)
32540493684eSMarcel Holtmann {
32550493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
32560493684eSMarcel Holtmann 	struct hci_conn *conn;
32570493684eSMarcel Holtmann 
32580493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
32590493684eSMarcel Holtmann 
32600493684eSMarcel Holtmann 	hci_dev_lock(hdev);
32610493684eSMarcel Holtmann 
32620493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32632a611692SJohan Hedberg 	if (!conn)
32642a611692SJohan Hedberg 		goto unlock;
32652a611692SJohan Hedberg 
32662a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
32672a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
32682a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
32692a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
32702a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3271fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3272bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3273bab73cb6SJohan Hedberg 				 ev->status);
32742a611692SJohan Hedberg 
327576a68ba0SDavid Herrmann 	hci_conn_drop(conn);
32760493684eSMarcel Holtmann 
32772a611692SJohan Hedberg unlock:
32780493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32790493684eSMarcel Holtmann }
32800493684eSMarcel Holtmann 
32816039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3282807deac2SGustavo Padovan 					 struct sk_buff *skb)
328341a96212SMarcel Holtmann {
328441a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
328541a96212SMarcel Holtmann 	struct inquiry_entry *ie;
3286cad718edSJohan Hedberg 	struct hci_conn *conn;
328741a96212SMarcel Holtmann 
328841a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
328941a96212SMarcel Holtmann 
329041a96212SMarcel Holtmann 	hci_dev_lock(hdev);
329141a96212SMarcel Holtmann 
3292cad718edSJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3293cad718edSJohan Hedberg 	if (conn)
3294cad718edSJohan Hedberg 		memcpy(conn->features[1], ev->features, 8);
3295cad718edSJohan Hedberg 
3296cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3297cc11b9c1SAndrei Emeltchenko 	if (ie)
329802b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
329941a96212SMarcel Holtmann 
330041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
330141a96212SMarcel Holtmann }
330241a96212SMarcel Holtmann 
33036039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
33042763eda6SSzymon Janc 					    struct sk_buff *skb)
33052763eda6SSzymon Janc {
33062763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
33072763eda6SSzymon Janc 	struct oob_data *data;
33082763eda6SSzymon Janc 
33092763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
33102763eda6SSzymon Janc 
33112763eda6SSzymon Janc 	hci_dev_lock(hdev);
33122763eda6SSzymon Janc 
3313a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3314e1ba1f15SSzymon Janc 		goto unlock;
3315e1ba1f15SSzymon Janc 
33162763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
33172763eda6SSzymon Janc 	if (data) {
33182763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
33192763eda6SSzymon Janc 
33202763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
33212763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
33222763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
33232763eda6SSzymon Janc 
33242763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
33252763eda6SSzymon Janc 			     &cp);
33262763eda6SSzymon Janc 	} else {
33272763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
33282763eda6SSzymon Janc 
33292763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
33302763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
33312763eda6SSzymon Janc 			     &cp);
33322763eda6SSzymon Janc 	}
33332763eda6SSzymon Janc 
3334e1ba1f15SSzymon Janc unlock:
33352763eda6SSzymon Janc 	hci_dev_unlock(hdev);
33362763eda6SSzymon Janc }
33372763eda6SSzymon Janc 
3338d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3339d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3340d5e91192SAndrei Emeltchenko {
3341d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3342d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3343d5e91192SAndrei Emeltchenko 
3344d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3345d5e91192SAndrei Emeltchenko 	       ev->status);
3346d5e91192SAndrei Emeltchenko 
3347d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3348d5e91192SAndrei Emeltchenko 
3349d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3350d5e91192SAndrei Emeltchenko 	if (!hcon) {
3351d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3352d5e91192SAndrei Emeltchenko 		return;
3353d5e91192SAndrei Emeltchenko 	}
3354d5e91192SAndrei Emeltchenko 
3355d5e91192SAndrei Emeltchenko 	if (ev->status) {
3356d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3357d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3358d5e91192SAndrei Emeltchenko 		return;
3359d5e91192SAndrei Emeltchenko 	}
3360d5e91192SAndrei Emeltchenko 
3361d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3362d5e91192SAndrei Emeltchenko 
3363d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3364d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3365d5e91192SAndrei Emeltchenko 
3366d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3367d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
336876a68ba0SDavid Herrmann 	hci_conn_drop(hcon);
3369d5e91192SAndrei Emeltchenko 
3370d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3371d5e91192SAndrei Emeltchenko 
3372cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
3373cf70ff22SAndrei Emeltchenko 
3374d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3375d5e91192SAndrei Emeltchenko }
3376d5e91192SAndrei Emeltchenko 
337727695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
337827695fb4SAndrei Emeltchenko {
337927695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
338027695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
338127695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
338227695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
338327695fb4SAndrei Emeltchenko 
338427695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
338527695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
338627695fb4SAndrei Emeltchenko 	       ev->status);
338727695fb4SAndrei Emeltchenko 
338827695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
338927695fb4SAndrei Emeltchenko 	if (!hcon)
339027695fb4SAndrei Emeltchenko 		return;
339127695fb4SAndrei Emeltchenko 
339227695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
339327695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
339427695fb4SAndrei Emeltchenko 	if (!hchan)
339527695fb4SAndrei Emeltchenko 		return;
339627695fb4SAndrei Emeltchenko 
339727695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
339827695fb4SAndrei Emeltchenko 
339927695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
340027695fb4SAndrei Emeltchenko 
340127695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
340227695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
340327695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
340427695fb4SAndrei Emeltchenko 
340527695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
340627695fb4SAndrei Emeltchenko 
340727695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
340827695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
340927695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
341027695fb4SAndrei Emeltchenko 
341127695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
341227695fb4SAndrei Emeltchenko 	}
341327695fb4SAndrei Emeltchenko }
341427695fb4SAndrei Emeltchenko 
3415606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3416606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3417606e2a10SAndrei Emeltchenko {
3418606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3419606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3420606e2a10SAndrei Emeltchenko 
3421606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3422606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3423606e2a10SAndrei Emeltchenko 
3424606e2a10SAndrei Emeltchenko 	if (ev->status)
3425606e2a10SAndrei Emeltchenko 		return;
3426606e2a10SAndrei Emeltchenko 
3427606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3428606e2a10SAndrei Emeltchenko 
3429606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3430606e2a10SAndrei Emeltchenko 	if (!hchan)
3431606e2a10SAndrei Emeltchenko 		goto unlock;
3432606e2a10SAndrei Emeltchenko 
3433606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3434606e2a10SAndrei Emeltchenko 
3435606e2a10SAndrei Emeltchenko unlock:
3436606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3437606e2a10SAndrei Emeltchenko }
3438606e2a10SAndrei Emeltchenko 
34399eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
34409eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
34419eef6b3aSAndrei Emeltchenko {
34429eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
34439eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
34449eef6b3aSAndrei Emeltchenko 
34459eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
34469eef6b3aSAndrei Emeltchenko 
34479eef6b3aSAndrei Emeltchenko 	if (ev->status)
34489eef6b3aSAndrei Emeltchenko 		return;
34499eef6b3aSAndrei Emeltchenko 
34509eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
34519eef6b3aSAndrei Emeltchenko 
34529eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
34539eef6b3aSAndrei Emeltchenko 	if (hcon) {
34549eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
34559eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
34569eef6b3aSAndrei Emeltchenko 	}
34579eef6b3aSAndrei Emeltchenko 
34589eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
34599eef6b3aSAndrei Emeltchenko }
34609eef6b3aSAndrei Emeltchenko 
34616039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3462fcd89c09SVille Tervo {
3463fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3464fcd89c09SVille Tervo 	struct hci_conn *conn;
3465fcd89c09SVille Tervo 
34669f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3467fcd89c09SVille Tervo 
3468fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3469fcd89c09SVille Tervo 
34704f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3471b62f328bSVille Tervo 	if (!conn) {
3472b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3473b62f328bSVille Tervo 		if (!conn) {
3474b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3475230fd16aSAndre Guedes 			goto unlock;
3476b62f328bSVille Tervo 		}
347729b7988aSAndre Guedes 
347829b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3479b9b343d2SAndre Guedes 
3480b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3481b9b343d2SAndre Guedes 			conn->out = true;
3482b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3483b9b343d2SAndre Guedes 		}
3484b62f328bSVille Tervo 	}
3485fcd89c09SVille Tervo 
3486cd17decbSAndre Guedes 	if (ev->status) {
3487cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3488cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3489cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3490cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3491cd17decbSAndre Guedes 		hci_conn_del(conn);
3492cd17decbSAndre Guedes 		goto unlock;
3493cd17decbSAndre Guedes 	}
3494cd17decbSAndre Guedes 
3495b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3496b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
349795b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
349883bc71b4SVinicius Costa Gomes 
34997b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3500fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3501fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3502fcd89c09SVille Tervo 
3503fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3504fcd89c09SVille Tervo 
3505fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3506fcd89c09SVille Tervo 
3507fcd89c09SVille Tervo unlock:
3508fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3509fcd89c09SVille Tervo }
3510fcd89c09SVille Tervo 
35116039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
35129aa04c91SAndre Guedes {
3513e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3514e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
35153c9e9195SAndre Guedes 	s8 rssi;
35169aa04c91SAndre Guedes 
3517e95beb41SAndre Guedes 	while (num_reports--) {
3518e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3519e95beb41SAndre Guedes 
35203c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
35213c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
352204124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
35233c9e9195SAndre Guedes 
3524e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
35259aa04c91SAndre Guedes 	}
35269aa04c91SAndre Guedes }
35279aa04c91SAndre Guedes 
35286039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3529a7a595f6SVinicius Costa Gomes {
3530a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3531a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3532bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3533a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3534c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3535a7a595f6SVinicius Costa Gomes 
35369f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3537a7a595f6SVinicius Costa Gomes 
3538a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3539a7a595f6SVinicius Costa Gomes 
3540a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3541bea710feSVinicius Costa Gomes 	if (conn == NULL)
3542bea710feSVinicius Costa Gomes 		goto not_found;
3543a7a595f6SVinicius Costa Gomes 
3544bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3545bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3546bea710feSVinicius Costa Gomes 		goto not_found;
3547bea710feSVinicius Costa Gomes 
3548bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3549a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3550c9839a11SVinicius Costa Gomes 
3551c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3552f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_HIGH;
3553f8776218SAndre Guedes 	else
3554f8776218SAndre Guedes 		conn->pending_sec_level = BT_SECURITY_MEDIUM;
3555a7a595f6SVinicius Costa Gomes 
355689cbb4daSAndre Guedes 	conn->enc_key_size = ltk->enc_size;
3557a7a595f6SVinicius Costa Gomes 
3558a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3559a7a595f6SVinicius Costa Gomes 
3560c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3561c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3562c9839a11SVinicius Costa Gomes 		kfree(ltk);
3563c9839a11SVinicius Costa Gomes 	}
3564c9839a11SVinicius Costa Gomes 
3565a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3566bea710feSVinicius Costa Gomes 
3567bea710feSVinicius Costa Gomes 	return;
3568bea710feSVinicius Costa Gomes 
3569bea710feSVinicius Costa Gomes not_found:
3570bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3571bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3572bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3573a7a595f6SVinicius Costa Gomes }
3574a7a595f6SVinicius Costa Gomes 
35756039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3576fcd89c09SVille Tervo {
3577fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3578fcd89c09SVille Tervo 
3579fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3580fcd89c09SVille Tervo 
3581fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3582fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3583fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3584fcd89c09SVille Tervo 		break;
3585fcd89c09SVille Tervo 
35869aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
35879aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
35889aa04c91SAndre Guedes 		break;
35899aa04c91SAndre Guedes 
3590a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3591a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3592a7a595f6SVinicius Costa Gomes 		break;
3593a7a595f6SVinicius Costa Gomes 
3594fcd89c09SVille Tervo 	default:
3595fcd89c09SVille Tervo 		break;
3596fcd89c09SVille Tervo 	}
3597fcd89c09SVille Tervo }
3598fcd89c09SVille Tervo 
35999495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
36009495b2eeSAndrei Emeltchenko {
36019495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
36029495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
36039495b2eeSAndrei Emeltchenko 
36049495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
36059495b2eeSAndrei Emeltchenko 
36069495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
36079495b2eeSAndrei Emeltchenko 
36089495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
36099495b2eeSAndrei Emeltchenko 	if (!hcon)
36109495b2eeSAndrei Emeltchenko 		return;
36119495b2eeSAndrei Emeltchenko 
36129495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
36139495b2eeSAndrei Emeltchenko }
36149495b2eeSAndrei Emeltchenko 
36151da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
36161da177e4SLinus Torvalds {
3617a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3618a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
36191da177e4SLinus Torvalds 
3620b6ddb638SJohan Hedberg 	hci_dev_lock(hdev);
3621b6ddb638SJohan Hedberg 
3622b6ddb638SJohan Hedberg 	/* Received events are (currently) only needed when a request is
3623b6ddb638SJohan Hedberg 	 * ongoing so avoid unnecessary memory allocation.
3624b6ddb638SJohan Hedberg 	 */
3625b6ddb638SJohan Hedberg 	if (hdev->req_status == HCI_REQ_PEND) {
3626b6ddb638SJohan Hedberg 		kfree_skb(hdev->recv_evt);
3627b6ddb638SJohan Hedberg 		hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
3628b6ddb638SJohan Hedberg 	}
3629b6ddb638SJohan Hedberg 
3630b6ddb638SJohan Hedberg 	hci_dev_unlock(hdev);
3631b6ddb638SJohan Hedberg 
36321da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
36331da177e4SLinus Torvalds 
363402350a72SJohan Hedberg 	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
3635c1f23a2bSJohannes Berg 		struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
3636c1f23a2bSJohannes Berg 		u16 opcode = __le16_to_cpu(cmd_hdr->opcode);
363702350a72SJohan Hedberg 
363802350a72SJohan Hedberg 		hci_req_cmd_complete(hdev, opcode, 0);
363902350a72SJohan Hedberg 	}
364002350a72SJohan Hedberg 
3641a9de9248SMarcel Holtmann 	switch (event) {
36421da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
36431da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
36441da177e4SLinus Torvalds 		break;
36451da177e4SLinus Torvalds 
36461da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
36471da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
36481da177e4SLinus Torvalds 		break;
36491da177e4SLinus Torvalds 
3650a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3651a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
365221d9e30eSMarcel Holtmann 		break;
365321d9e30eSMarcel Holtmann 
36541da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
36551da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
36561da177e4SLinus Torvalds 		break;
36571da177e4SLinus Torvalds 
36581da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
36591da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
36601da177e4SLinus Torvalds 		break;
36611da177e4SLinus Torvalds 
36621da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
36631da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
36641da177e4SLinus Torvalds 		break;
36651da177e4SLinus Torvalds 
3666a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3667a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3668a9de9248SMarcel Holtmann 		break;
3669a9de9248SMarcel Holtmann 
36701da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
36711da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
36721da177e4SLinus Torvalds 		break;
36731da177e4SLinus Torvalds 
3674a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3675a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3676a9de9248SMarcel Holtmann 		break;
3677a9de9248SMarcel Holtmann 
3678a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3679a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3680a9de9248SMarcel Holtmann 		break;
3681a9de9248SMarcel Holtmann 
3682a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3683a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3684a9de9248SMarcel Holtmann 		break;
3685a9de9248SMarcel Holtmann 
3686a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3687a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3688a9de9248SMarcel Holtmann 		break;
3689a9de9248SMarcel Holtmann 
3690a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3691a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3692a9de9248SMarcel Holtmann 		break;
3693a9de9248SMarcel Holtmann 
3694a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3695a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3696a9de9248SMarcel Holtmann 		break;
3697a9de9248SMarcel Holtmann 
3698a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3699a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
37001da177e4SLinus Torvalds 		break;
37011da177e4SLinus Torvalds 
37021da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
37031da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
37041da177e4SLinus Torvalds 		break;
37051da177e4SLinus Torvalds 
37061da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
37071da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
37081da177e4SLinus Torvalds 		break;
37091da177e4SLinus Torvalds 
37101da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
37111da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
37121da177e4SLinus Torvalds 		break;
37131da177e4SLinus Torvalds 
37141da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
37151da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
37161da177e4SLinus Torvalds 		break;
37171da177e4SLinus Torvalds 
3718a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3719a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3720a8746417SMarcel Holtmann 		break;
3721a8746417SMarcel Holtmann 
372285a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
372385a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
372485a1e930SMarcel Holtmann 		break;
372585a1e930SMarcel Holtmann 
3726a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3727a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3728a9de9248SMarcel Holtmann 		break;
3729a9de9248SMarcel Holtmann 
3730a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3731a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3732a9de9248SMarcel Holtmann 		break;
3733a9de9248SMarcel Holtmann 
3734a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3735a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3736a9de9248SMarcel Holtmann 		break;
3737a9de9248SMarcel Holtmann 
3738a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3739a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
37401da177e4SLinus Torvalds 		break;
37411da177e4SLinus Torvalds 
37421c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
37431c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
37441c2e0041SJohan Hedberg 		break;
37451c2e0041SJohan Hedberg 
37460493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
37470493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
37480493684eSMarcel Holtmann 		break;
37490493684eSMarcel Holtmann 
375003b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
375103b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
375203b555e1SJohan Hedberg 		break;
375303b555e1SJohan Hedberg 
3754a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3755a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3756a5c29683SJohan Hedberg 		break;
3757a5c29683SJohan Hedberg 
37581143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
37591143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
37601143d458SBrian Gix 		break;
37611143d458SBrian Gix 
376292a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
376392a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
376492a25256SJohan Hedberg 		break;
376592a25256SJohan Hedberg 
376692a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
376792a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
376892a25256SJohan Hedberg 		break;
376992a25256SJohan Hedberg 
37700493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
37710493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
37720493684eSMarcel Holtmann 		break;
37730493684eSMarcel Holtmann 
377441a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
377541a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
377641a96212SMarcel Holtmann 		break;
377741a96212SMarcel Holtmann 
3778fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3779fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3780fcd89c09SVille Tervo 		break;
3781fcd89c09SVille Tervo 
37829495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
37839495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
37849495b2eeSAndrei Emeltchenko 		break;
37859495b2eeSAndrei Emeltchenko 
37862763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
37872763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
37882763eda6SSzymon Janc 		break;
37892763eda6SSzymon Janc 
3790d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
3791d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
3792d5e91192SAndrei Emeltchenko 		break;
3793d5e91192SAndrei Emeltchenko 
379427695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
379527695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
379627695fb4SAndrei Emeltchenko 		break;
379727695fb4SAndrei Emeltchenko 
3798606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
3799606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
3800606e2a10SAndrei Emeltchenko 		break;
3801606e2a10SAndrei Emeltchenko 
38029eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
38039eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
38049eef6b3aSAndrei Emeltchenko 		break;
38059eef6b3aSAndrei Emeltchenko 
380625e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
380725e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
380825e89e99SAndrei Emeltchenko 		break;
380925e89e99SAndrei Emeltchenko 
38101da177e4SLinus Torvalds 	default:
38119f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
38121da177e4SLinus Torvalds 		break;
38131da177e4SLinus Torvalds 	}
38141da177e4SLinus Torvalds 
38151da177e4SLinus Torvalds 	kfree_skb(skb);
38161da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
38171da177e4SLinus Torvalds }
3818