xref: /openbmc/linux/net/bluetooth/hci_event.c (revision bbaf444a89dd7dd7effd8ed2f4e4ec64da3cc1da)
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>
328e2a0d92SAndrei Emeltchenko #include <net/bluetooth/a2mp.h>
33903e4541SAndrei Emeltchenko #include <net/bluetooth/amp.h>
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds /* Handle HCI Event packets */
361da177e4SLinus Torvalds 
37a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
381da177e4SLinus Torvalds {
39a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
401da177e4SLinus Torvalds 
419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
421da177e4SLinus Torvalds 
43e6d465cbSAndre Guedes 	if (status) {
44e6d465cbSAndre Guedes 		hci_dev_lock(hdev);
45e6d465cbSAndre Guedes 		mgmt_stop_discovery_failed(hdev, status);
46e6d465cbSAndre Guedes 		hci_dev_unlock(hdev);
47a9de9248SMarcel Holtmann 		return;
48e6d465cbSAndre Guedes 	}
491da177e4SLinus Torvalds 
5089352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
5189352e7dSAndre Guedes 
5256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
53ff9ef578SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
5456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
55a9de9248SMarcel Holtmann 
5623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
57a9de9248SMarcel Holtmann 
58a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
591da177e4SLinus Torvalds }
606bd57416SMarcel Holtmann 
614d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
624d93483bSAndre Guedes {
634d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
644d93483bSAndre Guedes 
659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
66ae854a70SAndre Guedes 
67ae854a70SAndre Guedes 	if (status)
68ae854a70SAndre Guedes 		return;
69ae854a70SAndre Guedes 
70ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
714d93483bSAndre Guedes }
724d93483bSAndre Guedes 
73a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
741da177e4SLinus Torvalds {
75a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
76a9de9248SMarcel Holtmann 
779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
78a9de9248SMarcel Holtmann 
79a9de9248SMarcel Holtmann 	if (status)
80a9de9248SMarcel Holtmann 		return;
81a9de9248SMarcel Holtmann 
82ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
83ae854a70SAndre Guedes 
84a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
85a9de9248SMarcel Holtmann }
86a9de9248SMarcel Holtmann 
87807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
88807deac2SGustavo Padovan 					  struct sk_buff *skb)
89a9de9248SMarcel Holtmann {
90a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
91a9de9248SMarcel Holtmann }
92a9de9248SMarcel Holtmann 
93a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
94a9de9248SMarcel Holtmann {
95a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
961da177e4SLinus Torvalds 	struct hci_conn *conn;
971da177e4SLinus Torvalds 
989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
991da177e4SLinus Torvalds 
100a9de9248SMarcel Holtmann 	if (rp->status)
101a9de9248SMarcel Holtmann 		return;
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1041da177e4SLinus Torvalds 
105a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1061da177e4SLinus Torvalds 	if (conn) {
107a9de9248SMarcel Holtmann 		if (rp->role)
1081da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1091da177e4SLinus Torvalds 		else
1101da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1111da177e4SLinus Torvalds 	}
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
114a9de9248SMarcel Holtmann }
1151da177e4SLinus Torvalds 
116e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
117e4e8e37cSMarcel Holtmann {
118e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
119e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
120e4e8e37cSMarcel Holtmann 
1219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
122e4e8e37cSMarcel Holtmann 
123e4e8e37cSMarcel Holtmann 	if (rp->status)
124e4e8e37cSMarcel Holtmann 		return;
125e4e8e37cSMarcel Holtmann 
126e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
127e4e8e37cSMarcel Holtmann 
128e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
129e4e8e37cSMarcel Holtmann 	if (conn)
130e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
131e4e8e37cSMarcel Holtmann 
132e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
133e4e8e37cSMarcel Holtmann }
134e4e8e37cSMarcel Holtmann 
135a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
136a9de9248SMarcel Holtmann {
137a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
138a9de9248SMarcel Holtmann 	struct hci_conn *conn;
139a9de9248SMarcel Holtmann 	void *sent;
140a9de9248SMarcel Holtmann 
1419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
142a9de9248SMarcel Holtmann 
143a9de9248SMarcel Holtmann 	if (rp->status)
144a9de9248SMarcel Holtmann 		return;
145a9de9248SMarcel Holtmann 
146a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14704837f64SMarcel Holtmann 	if (!sent)
148a9de9248SMarcel Holtmann 		return;
14904837f64SMarcel Holtmann 
15004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
15104837f64SMarcel Holtmann 
152a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
153e4e8e37cSMarcel Holtmann 	if (conn)
15483985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15504837f64SMarcel Holtmann 
15604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds 
159807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
160807deac2SGustavo Padovan 					struct sk_buff *skb)
161e4e8e37cSMarcel Holtmann {
162e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
163e4e8e37cSMarcel Holtmann 
1649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
165e4e8e37cSMarcel Holtmann 
166e4e8e37cSMarcel Holtmann 	if (rp->status)
167e4e8e37cSMarcel Holtmann 		return;
168e4e8e37cSMarcel Holtmann 
169e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
170e4e8e37cSMarcel Holtmann }
171e4e8e37cSMarcel Holtmann 
172807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
173807deac2SGustavo Padovan 					 struct sk_buff *skb)
174e4e8e37cSMarcel Holtmann {
175e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
176e4e8e37cSMarcel Holtmann 	void *sent;
177e4e8e37cSMarcel Holtmann 
1789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
179e4e8e37cSMarcel Holtmann 
180e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
181e4e8e37cSMarcel Holtmann 	if (!sent)
182e4e8e37cSMarcel Holtmann 		return;
183e4e8e37cSMarcel Holtmann 
184e4e8e37cSMarcel Holtmann 	if (!status)
185e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
186e4e8e37cSMarcel Holtmann 
18723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
188e4e8e37cSMarcel Holtmann }
189e4e8e37cSMarcel Holtmann 
190a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1911da177e4SLinus Torvalds {
192a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
193a9de9248SMarcel Holtmann 
1949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
195a9de9248SMarcel Holtmann 
19610572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19710572132SGustavo F. Padovan 
19823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
199d23264a8SAndre Guedes 
200a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
201ae854a70SAndre Guedes 	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
202ae854a70SAndre Guedes 			     BIT(HCI_PERIODIC_INQ));
20369775ff6SAndre Guedes 
20469775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
205*bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
206*bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
207a9de9248SMarcel Holtmann }
208a9de9248SMarcel Holtmann 
209a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
210a9de9248SMarcel Holtmann {
211a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2121da177e4SLinus Torvalds 	void *sent;
2131da177e4SLinus Torvalds 
2149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2151da177e4SLinus Torvalds 
216a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2171da177e4SLinus Torvalds 	if (!sent)
218a9de9248SMarcel Holtmann 		return;
2191da177e4SLinus Torvalds 
22056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
22156e5cb86SJohan Hedberg 
222f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
223f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
22428cc7bdeSJohan Hedberg 	else if (!status)
22528cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
226f51d5b24SJohan Hedberg 
22756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
2283159d384SJohan Hedberg 
2293159d384SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
230a9de9248SMarcel Holtmann }
231a9de9248SMarcel Holtmann 
232a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
233a9de9248SMarcel Holtmann {
234a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
235a9de9248SMarcel Holtmann 
2369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
237a9de9248SMarcel Holtmann 
238a9de9248SMarcel Holtmann 	if (rp->status)
239a9de9248SMarcel Holtmann 		return;
240a9de9248SMarcel Holtmann 
241db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2421f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
243a9de9248SMarcel Holtmann }
244a9de9248SMarcel Holtmann 
245a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
246a9de9248SMarcel Holtmann {
247a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
248a9de9248SMarcel Holtmann 	void *sent;
249a9de9248SMarcel Holtmann 
2509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
251a9de9248SMarcel Holtmann 
252a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
253a9de9248SMarcel Holtmann 	if (!sent)
254a9de9248SMarcel Holtmann 		return;
2551da177e4SLinus Torvalds 
2561da177e4SLinus Torvalds 	if (!status) {
257a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
258a9de9248SMarcel Holtmann 
2591da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2601da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2611da177e4SLinus Torvalds 		else
2621da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2631da177e4SLinus Torvalds 	}
264a9de9248SMarcel Holtmann 
26533ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
26633ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
26733ef95edSJohan Hedberg 
26823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
269a9de9248SMarcel Holtmann }
2701da177e4SLinus Torvalds 
271a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
272a9de9248SMarcel Holtmann {
273a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
274a9de9248SMarcel Holtmann 	void *sent;
275a9de9248SMarcel Holtmann 
2769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
277a9de9248SMarcel Holtmann 
278a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2791da177e4SLinus Torvalds 	if (!sent)
280a9de9248SMarcel Holtmann 		return;
2811da177e4SLinus Torvalds 
2821da177e4SLinus Torvalds 	if (!status) {
283a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
284a9de9248SMarcel Holtmann 
2851da177e4SLinus Torvalds 		if (param)
2861da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2871da177e4SLinus Torvalds 		else
2881da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2891da177e4SLinus Torvalds 	}
290a9de9248SMarcel Holtmann 
29123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2921da177e4SLinus Torvalds }
2931da177e4SLinus Torvalds 
294a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
295a9de9248SMarcel Holtmann {
29636f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
29736f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
298a9de9248SMarcel Holtmann 	void *sent;
2991da177e4SLinus Torvalds 
3009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
301a9de9248SMarcel Holtmann 
302a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3031da177e4SLinus Torvalds 	if (!sent)
304a9de9248SMarcel Holtmann 		return;
3051da177e4SLinus Torvalds 
30636f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
307a9de9248SMarcel Holtmann 
30856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
30956e5cb86SJohan Hedberg 
310fa1bd918SMikel Astiz 	if (status) {
311744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3122d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3132d7cee58SJohan Hedberg 		goto done;
3142d7cee58SJohan Hedberg 	}
3152d7cee58SJohan Hedberg 
3169fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3179fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
318a9de9248SMarcel Holtmann 
31973f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3201da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3219fbcbb45SJohan Hedberg 		if (!old_iscan)
322744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
32316ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
32416ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
32516ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
32616ab91abSJohan Hedberg 					   to);
32716ab91abSJohan Hedberg 		}
3289fbcbb45SJohan Hedberg 	} else if (old_iscan)
329744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3301da177e4SLinus Torvalds 
3319fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3321da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3339fbcbb45SJohan Hedberg 		if (!old_pscan)
334744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3359fbcbb45SJohan Hedberg 	} else if (old_pscan)
336744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
337a9de9248SMarcel Holtmann 
33836f7fc7eSJohan Hedberg done:
33956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
34023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3411da177e4SLinus Torvalds }
3421da177e4SLinus Torvalds 
343a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
344a9de9248SMarcel Holtmann {
345a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
346a9de9248SMarcel Holtmann 
3479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
348a9de9248SMarcel Holtmann 
349a9de9248SMarcel Holtmann 	if (rp->status)
350a9de9248SMarcel Holtmann 		return;
351a9de9248SMarcel Holtmann 
352a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
353a9de9248SMarcel Holtmann 
354a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
355a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
356a9de9248SMarcel Holtmann }
357a9de9248SMarcel Holtmann 
358a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
359a9de9248SMarcel Holtmann {
360a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
361a9de9248SMarcel Holtmann 	void *sent;
362a9de9248SMarcel Holtmann 
3639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
364a9de9248SMarcel Holtmann 
365a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
366a9de9248SMarcel Holtmann 	if (!sent)
367a9de9248SMarcel Holtmann 		return;
368a9de9248SMarcel Holtmann 
3697f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3707f9a903cSMarcel Holtmann 
3717f9a903cSMarcel Holtmann 	if (status == 0)
372a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3737f9a903cSMarcel Holtmann 
3747f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3757f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3767f9a903cSMarcel Holtmann 
3777f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
378a9de9248SMarcel Holtmann }
379a9de9248SMarcel Holtmann 
380a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
381a9de9248SMarcel Holtmann {
382a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
383a9de9248SMarcel Holtmann 	__u16 setting;
384a9de9248SMarcel Holtmann 
3859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
386a9de9248SMarcel Holtmann 
387a9de9248SMarcel Holtmann 	if (rp->status)
388a9de9248SMarcel Holtmann 		return;
389a9de9248SMarcel Holtmann 
390a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
391a9de9248SMarcel Holtmann 
392a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
393a9de9248SMarcel Holtmann 		return;
394a9de9248SMarcel Holtmann 
395a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
396a9de9248SMarcel Holtmann 
3979f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
398a9de9248SMarcel Holtmann 
3993c54711cSGustavo F. Padovan 	if (hdev->notify)
400a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
401a9de9248SMarcel Holtmann }
402a9de9248SMarcel Holtmann 
4038fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
4048fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
405a9de9248SMarcel Holtmann {
406a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
407f383f275SMarcel Holtmann 	__u16 setting;
408a9de9248SMarcel Holtmann 	void *sent;
409a9de9248SMarcel Holtmann 
4109f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
411a9de9248SMarcel Holtmann 
412f383f275SMarcel Holtmann 	if (status)
413f383f275SMarcel Holtmann 		return;
414f383f275SMarcel Holtmann 
415a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
416a9de9248SMarcel Holtmann 	if (!sent)
417a9de9248SMarcel Holtmann 		return;
418a9de9248SMarcel Holtmann 
419f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4201da177e4SLinus Torvalds 
421f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
422f383f275SMarcel Holtmann 		return;
423f383f275SMarcel Holtmann 
4241da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4251da177e4SLinus Torvalds 
4269f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4271da177e4SLinus Torvalds 
4283c54711cSGustavo F. Padovan 	if (hdev->notify)
4291da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4301da177e4SLinus Torvalds }
4311da177e4SLinus Torvalds 
432a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4331da177e4SLinus Torvalds {
434a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4351da177e4SLinus Torvalds 
4369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
4371da177e4SLinus Torvalds 
43823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4391143e5a6SMarcel Holtmann }
4401143e5a6SMarcel Holtmann 
441333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
442333140b5SMarcel Holtmann {
443333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4445ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
445333140b5SMarcel Holtmann 
4469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
447333140b5SMarcel Holtmann 
448333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
449333140b5SMarcel Holtmann 	if (!sent)
450333140b5SMarcel Holtmann 		return;
451333140b5SMarcel Holtmann 
4525ed8eb2fSJohan Hedberg 	if (!status) {
4535ed8eb2fSJohan Hedberg 		if (sent->mode)
4545ed8eb2fSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_SSP;
4555ed8eb2fSJohan Hedberg 		else
4565ed8eb2fSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_SSP;
4575ed8eb2fSJohan Hedberg 	}
4585ed8eb2fSJohan Hedberg 
459c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4605ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
461c0ecddc2SJohan Hedberg 	else if (!status) {
4625ed8eb2fSJohan Hedberg 		if (sent->mode)
46384bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
46484bde9d6SJohan Hedberg 		else
46584bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
466c0ecddc2SJohan Hedberg 	}
467333140b5SMarcel Holtmann }
468333140b5SMarcel Holtmann 
469d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
470d5859e22SJohan Hedberg {
471976eb20eSJohan Hedberg 	if (lmp_ext_inq_capable(hdev))
472d5859e22SJohan Hedberg 		return 2;
473d5859e22SJohan Hedberg 
474976eb20eSJohan Hedberg 	if (lmp_inq_rssi_capable(hdev))
475d5859e22SJohan Hedberg 		return 1;
476d5859e22SJohan Hedberg 
477d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
478d5859e22SJohan Hedberg 	    hdev->lmp_subver == 0x0757)
479d5859e22SJohan Hedberg 		return 1;
480d5859e22SJohan Hedberg 
481d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
482d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
483d5859e22SJohan Hedberg 			return 1;
484d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
485d5859e22SJohan Hedberg 			return 1;
486d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
487d5859e22SJohan Hedberg 			return 1;
488d5859e22SJohan Hedberg 	}
489d5859e22SJohan Hedberg 
490d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
491d5859e22SJohan Hedberg 	    hdev->lmp_subver == 0x1805)
492d5859e22SJohan Hedberg 		return 1;
493d5859e22SJohan Hedberg 
494d5859e22SJohan Hedberg 	return 0;
495d5859e22SJohan Hedberg }
496d5859e22SJohan Hedberg 
497d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
498d5859e22SJohan Hedberg {
499d5859e22SJohan Hedberg 	u8 mode;
500d5859e22SJohan Hedberg 
501d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
502d5859e22SJohan Hedberg 
503d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
504d5859e22SJohan Hedberg }
505d5859e22SJohan Hedberg 
506d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
507d5859e22SJohan Hedberg {
508d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
509d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
510d5859e22SJohan Hedberg 	 * command otherwise */
511d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
512d5859e22SJohan Hedberg 
5136de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5146de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5155a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
5166de6c18dSVille Tervo 		return;
5176de6c18dSVille Tervo 
518e1171e8dSJohan Hedberg 	if (lmp_bredr_capable(hdev)) {
519d5859e22SJohan Hedberg 		events[4] |= 0x01; /* Flow Specification Complete */
520d5859e22SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
521d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Read Remote Extended Features Complete */
522d5859e22SJohan Hedberg 		events[5] |= 0x08; /* Synchronous Connection Complete */
523d5859e22SJohan Hedberg 		events[5] |= 0x10; /* Synchronous Connection Changed */
524e1171e8dSJohan Hedberg 	}
525d5859e22SJohan Hedberg 
526976eb20eSJohan Hedberg 	if (lmp_inq_rssi_capable(hdev))
527a24299e6SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
528d5859e22SJohan Hedberg 
529999dcd10SAndre Guedes 	if (lmp_sniffsubr_capable(hdev))
530d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
531d5859e22SJohan Hedberg 
532976eb20eSJohan Hedberg 	if (lmp_pause_enc_capable(hdev))
533d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
534d5859e22SJohan Hedberg 
535976eb20eSJohan Hedberg 	if (lmp_ext_inq_capable(hdev))
536d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
537d5859e22SJohan Hedberg 
538c58e810eSAndre Guedes 	if (lmp_no_flush_capable(hdev))
539d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
540d5859e22SJohan Hedberg 
541976eb20eSJohan Hedberg 	if (lmp_lsto_capable(hdev))
542d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
543d5859e22SJohan Hedberg 
5449a1a1996SAndre Guedes 	if (lmp_ssp_capable(hdev)) {
545d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
546d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
547d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
548d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
549d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
550d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
551d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
552d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
553d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
554d5859e22SJohan Hedberg 					 * Features Notification */
555d5859e22SJohan Hedberg 	}
556d5859e22SJohan Hedberg 
557c383ddc4SAndre Guedes 	if (lmp_le_capable(hdev))
558d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
559d5859e22SJohan Hedberg 
560d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
561e36b04c8SJohan Hedberg 
562e36b04c8SJohan Hedberg 	if (lmp_le_capable(hdev)) {
563e36b04c8SJohan Hedberg 		memset(events, 0, sizeof(events));
564e36b04c8SJohan Hedberg 		events[0] = 0x1f;
565e36b04c8SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
566e36b04c8SJohan Hedberg 			     sizeof(events), events);
567e36b04c8SJohan Hedberg 	}
568d5859e22SJohan Hedberg }
569d5859e22SJohan Hedberg 
5704611dfa8SGustavo Padovan static void bredr_setup(struct hci_dev *hdev)
571e1171e8dSJohan Hedberg {
572e1171e8dSJohan Hedberg 	struct hci_cp_delete_stored_link_key cp;
573e1171e8dSJohan Hedberg 	__le16 param;
574e1171e8dSJohan Hedberg 	__u8 flt_type;
575e1171e8dSJohan Hedberg 
576e1171e8dSJohan Hedberg 	/* Read Buffer Size (ACL mtu, max pkt, etc.) */
577e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
578e1171e8dSJohan Hedberg 
579e1171e8dSJohan Hedberg 	/* Read Class of Device */
580e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
581e1171e8dSJohan Hedberg 
582e1171e8dSJohan Hedberg 	/* Read Local Name */
583e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
584e1171e8dSJohan Hedberg 
585e1171e8dSJohan Hedberg 	/* Read Voice Setting */
586e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
587e1171e8dSJohan Hedberg 
588e1171e8dSJohan Hedberg 	/* Clear Event Filters */
589e1171e8dSJohan Hedberg 	flt_type = HCI_FLT_CLEAR_ALL;
590e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
591e1171e8dSJohan Hedberg 
592e1171e8dSJohan Hedberg 	/* Connection accept timeout ~20 secs */
593e1171e8dSJohan Hedberg 	param = __constant_cpu_to_le16(0x7d00);
594e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
595e1171e8dSJohan Hedberg 
596e1171e8dSJohan Hedberg 	bacpy(&cp.bdaddr, BDADDR_ANY);
597e1171e8dSJohan Hedberg 	cp.delete_all = 1;
598e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
599e1171e8dSJohan Hedberg }
600e1171e8dSJohan Hedberg 
6014611dfa8SGustavo Padovan static void le_setup(struct hci_dev *hdev)
602e1171e8dSJohan Hedberg {
603e1171e8dSJohan Hedberg 	/* Read LE Buffer Size */
604e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
6058fa19098SJohan Hedberg 
6068fa19098SJohan Hedberg 	/* Read LE Advertising Channel TX Power */
6078fa19098SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
608e1171e8dSJohan Hedberg }
609e1171e8dSJohan Hedberg 
610d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
611d5859e22SJohan Hedberg {
612e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
613e61ef499SAndrei Emeltchenko 		return;
614e61ef499SAndrei Emeltchenko 
615e1171e8dSJohan Hedberg 	/* Read BD Address */
616e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
617e1171e8dSJohan Hedberg 
618e1171e8dSJohan Hedberg 	if (lmp_bredr_capable(hdev))
6194611dfa8SGustavo Padovan 		bredr_setup(hdev);
620e1171e8dSJohan Hedberg 
621e1171e8dSJohan Hedberg 	if (lmp_le_capable(hdev))
6224611dfa8SGustavo Padovan 		le_setup(hdev);
623e1171e8dSJohan Hedberg 
624d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
625d5859e22SJohan Hedberg 
626d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
627d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
628d5859e22SJohan Hedberg 
6296d3c730fSGustavo Padovan 	if (lmp_ssp_capable(hdev)) {
63054d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
631d5859e22SJohan Hedberg 			u8 mode = 0x01;
63254d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
63354d04dbbSJohan Hedberg 				     sizeof(mode), &mode);
63454d04dbbSJohan Hedberg 		} else {
63554d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
63654d04dbbSJohan Hedberg 
63754d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
63854d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
63954d04dbbSJohan Hedberg 
64054d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
64154d04dbbSJohan Hedberg 		}
642d5859e22SJohan Hedberg 	}
643d5859e22SJohan Hedberg 
644976eb20eSJohan Hedberg 	if (lmp_inq_rssi_capable(hdev))
645d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
646d5859e22SJohan Hedberg 
647976eb20eSJohan Hedberg 	if (lmp_inq_tx_pwr_capable(hdev))
648d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
649971e3a4bSAndre Guedes 
650976eb20eSJohan Hedberg 	if (lmp_ext_feat_capable(hdev)) {
651971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
652971e3a4bSAndre Guedes 
653971e3a4bSAndre Guedes 		cp.page = 0x01;
65404124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
65504124681SGustavo F. Padovan 			     &cp);
656971e3a4bSAndre Guedes 	}
657e6100a25SAndre Guedes 
65847990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
65947990ea0SJohan Hedberg 		u8 enable = 1;
66004124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
66104124681SGustavo F. Padovan 			     &enable);
66247990ea0SJohan Hedberg 	}
663d5859e22SJohan Hedberg }
664d5859e22SJohan Hedberg 
665a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
666a9de9248SMarcel Holtmann {
667a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6681143e5a6SMarcel Holtmann 
6699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
6701143e5a6SMarcel Holtmann 
671a9de9248SMarcel Holtmann 	if (rp->status)
67228b8df77SAndrei Emeltchenko 		goto done;
6731143e5a6SMarcel Holtmann 
674a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
675e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
676d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
677e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
678d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6791da177e4SLinus Torvalds 
6809f1db00cSAndrei Emeltchenko 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
681807deac2SGustavo Padovan 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
682d5859e22SJohan Hedberg 
683d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
684d5859e22SJohan Hedberg 		hci_setup(hdev);
68528b8df77SAndrei Emeltchenko 
68628b8df77SAndrei Emeltchenko done:
68728b8df77SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
688d5859e22SJohan Hedberg }
689d5859e22SJohan Hedberg 
690d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
691d5859e22SJohan Hedberg {
692035100c8SAndrei Emeltchenko 	struct hci_cp_write_def_link_policy cp;
693d5859e22SJohan Hedberg 	u16 link_policy = 0;
694d5859e22SJohan Hedberg 
6959f92ebf6SAndre Guedes 	if (lmp_rswitch_capable(hdev))
696d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
697976eb20eSJohan Hedberg 	if (lmp_hold_capable(hdev))
698d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
6996eded100SAndre Guedes 	if (lmp_sniff_capable(hdev))
700d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
701976eb20eSJohan Hedberg 	if (lmp_park_capable(hdev))
702d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
703d5859e22SJohan Hedberg 
704035100c8SAndrei Emeltchenko 	cp.policy = cpu_to_le16(link_policy);
705035100c8SAndrei Emeltchenko 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
7061da177e4SLinus Torvalds }
7071da177e4SLinus Torvalds 
7088fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
7098fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
710a9de9248SMarcel Holtmann {
711a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
712a9de9248SMarcel Holtmann 
7139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
714a9de9248SMarcel Holtmann 
715a9de9248SMarcel Holtmann 	if (rp->status)
716d5859e22SJohan Hedberg 		goto done;
717a9de9248SMarcel Holtmann 
718a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
719d5859e22SJohan Hedberg 
720d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
721d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
722d5859e22SJohan Hedberg 
723d5859e22SJohan Hedberg done:
724d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
725a9de9248SMarcel Holtmann }
726a9de9248SMarcel Holtmann 
7278fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
7288fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
729a9de9248SMarcel Holtmann {
730a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
731a9de9248SMarcel Holtmann 
7329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
733a9de9248SMarcel Holtmann 
734a9de9248SMarcel Holtmann 	if (rp->status)
735a9de9248SMarcel Holtmann 		return;
736a9de9248SMarcel Holtmann 
737a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
7381da177e4SLinus Torvalds 
7391da177e4SLinus Torvalds 	/* Adjust default settings according to features
7401da177e4SLinus Torvalds 	 * supported by device. */
741a9de9248SMarcel Holtmann 
7421da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
7431da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
7441da177e4SLinus Torvalds 
7451da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
7461da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
7471da177e4SLinus Torvalds 
7485b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
7491da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
7505b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
7515b7f9909SMarcel Holtmann 	}
7521da177e4SLinus Torvalds 
7535b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
7541da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
7555b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
7565b7f9909SMarcel Holtmann 	}
7575b7f9909SMarcel Holtmann 
75845db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
7595b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
7605b7f9909SMarcel Holtmann 
7615b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
7625b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
7635b7f9909SMarcel Holtmann 
7645b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
7655b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
7661da177e4SLinus Torvalds 
767efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
768efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
769efc7688bSMarcel Holtmann 
770efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
771efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
772efc7688bSMarcel Holtmann 
773efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
774efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
775efc7688bSMarcel Holtmann 
776a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
777a9de9248SMarcel Holtmann 	       hdev->features[0], hdev->features[1],
778a9de9248SMarcel Holtmann 	       hdev->features[2], hdev->features[3],
779a9de9248SMarcel Holtmann 	       hdev->features[4], hdev->features[5],
780a9de9248SMarcel Holtmann 	       hdev->features[6], hdev->features[7]);
7811da177e4SLinus Torvalds }
7821da177e4SLinus Torvalds 
7838f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev)
7848f984dfaSJohan Hedberg {
7858f984dfaSJohan Hedberg 	struct hci_cp_write_le_host_supported cp;
7868f984dfaSJohan Hedberg 
7878f984dfaSJohan Hedberg 	memset(&cp, 0, sizeof(cp));
7888f984dfaSJohan Hedberg 
7899d42820fSMarcel Holtmann 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
7908f984dfaSJohan Hedberg 		cp.le = 1;
791976eb20eSJohan Hedberg 		cp.simul = !!lmp_le_br_capable(hdev);
7928f984dfaSJohan Hedberg 	}
7938f984dfaSJohan Hedberg 
794976eb20eSJohan Hedberg 	if (cp.le != !!lmp_host_le_capable(hdev))
79504124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
79604124681SGustavo F. Padovan 			     &cp);
7978f984dfaSJohan Hedberg }
7988f984dfaSJohan Hedberg 
799971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
800971e3a4bSAndre Guedes 					   struct sk_buff *skb)
801971e3a4bSAndre Guedes {
802971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
803971e3a4bSAndre Guedes 
8049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
805971e3a4bSAndre Guedes 
806971e3a4bSAndre Guedes 	if (rp->status)
8078f984dfaSJohan Hedberg 		goto done;
808971e3a4bSAndre Guedes 
809b5b32b65SAndre Guedes 	switch (rp->page) {
810b5b32b65SAndre Guedes 	case 0:
811b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
812b5b32b65SAndre Guedes 		break;
813b5b32b65SAndre Guedes 	case 1:
81459e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
815b5b32b65SAndre Guedes 		break;
816b5b32b65SAndre Guedes 	}
817971e3a4bSAndre Guedes 
818c383ddc4SAndre Guedes 	if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
8198f984dfaSJohan Hedberg 		hci_set_le_support(hdev);
8208f984dfaSJohan Hedberg 
8218f984dfaSJohan Hedberg done:
822971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
823971e3a4bSAndre Guedes }
824971e3a4bSAndre Guedes 
8251e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
8261e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
8271e89cffbSAndrei Emeltchenko {
8281e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
8291e89cffbSAndrei Emeltchenko 
8309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8311e89cffbSAndrei Emeltchenko 
8321e89cffbSAndrei Emeltchenko 	if (rp->status)
8331e89cffbSAndrei Emeltchenko 		return;
8341e89cffbSAndrei Emeltchenko 
8351e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
8361e89cffbSAndrei Emeltchenko 
8371e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
8381e89cffbSAndrei Emeltchenko }
8391e89cffbSAndrei Emeltchenko 
840a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
841a9de9248SMarcel Holtmann {
842a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
843a9de9248SMarcel Holtmann 
8449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
845a9de9248SMarcel Holtmann 
846a9de9248SMarcel Holtmann 	if (rp->status)
847a9de9248SMarcel Holtmann 		return;
848a9de9248SMarcel Holtmann 
849a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
850a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
851a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
852a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
853da1f5198SMarcel Holtmann 
854da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
855da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
856da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
857da1f5198SMarcel Holtmann 	}
858da1f5198SMarcel Holtmann 
859da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
860da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
8611da177e4SLinus Torvalds 
862807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
863807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
8641da177e4SLinus Torvalds }
8651da177e4SLinus Torvalds 
866a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
867a9de9248SMarcel Holtmann {
868a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
8691da177e4SLinus Torvalds 
8709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
871a9de9248SMarcel Holtmann 
872a9de9248SMarcel Holtmann 	if (!rp->status)
873a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
874a9de9248SMarcel Holtmann 
87523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
87623bb5763SJohan Hedberg }
87723bb5763SJohan Hedberg 
878350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
879350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
880350ee4cfSAndrei Emeltchenko {
881350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
882350ee4cfSAndrei Emeltchenko 
8839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
884350ee4cfSAndrei Emeltchenko 
885350ee4cfSAndrei Emeltchenko 	if (rp->status)
886350ee4cfSAndrei Emeltchenko 		return;
887350ee4cfSAndrei Emeltchenko 
888350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
889350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
890350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
891350ee4cfSAndrei Emeltchenko 
892350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
893350ee4cfSAndrei Emeltchenko 
894350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
895350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
896350ee4cfSAndrei Emeltchenko 
897350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
898350ee4cfSAndrei Emeltchenko }
899350ee4cfSAndrei Emeltchenko 
90023bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
90123bb5763SJohan Hedberg {
90223bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
90323bb5763SJohan Hedberg 
9049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
90523bb5763SJohan Hedberg 
90623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
9071da177e4SLinus Torvalds }
9081da177e4SLinus Torvalds 
909928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
910928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
911928abaa7SAndrei Emeltchenko {
912928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
913928abaa7SAndrei Emeltchenko 
9149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
915928abaa7SAndrei Emeltchenko 
916928abaa7SAndrei Emeltchenko 	if (rp->status)
9178e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
918928abaa7SAndrei Emeltchenko 
919928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
920928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
921928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
922928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
923928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
924928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
925928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
926928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
927928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
928928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
929928abaa7SAndrei Emeltchenko 
930928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
9318e2a0d92SAndrei Emeltchenko 
9328e2a0d92SAndrei Emeltchenko a2mp_rsp:
9338e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
934928abaa7SAndrei Emeltchenko }
935928abaa7SAndrei Emeltchenko 
936903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
937903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
938903e4541SAndrei Emeltchenko {
939903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
940903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
941903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
942903e4541SAndrei Emeltchenko 
943903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
944903e4541SAndrei Emeltchenko 
945903e4541SAndrei Emeltchenko 	if (rp->status)
946903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
947903e4541SAndrei Emeltchenko 
948903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
949903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
950903e4541SAndrei Emeltchenko 
951903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
9522e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
953903e4541SAndrei Emeltchenko 
954903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
955903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
956903e4541SAndrei Emeltchenko 
957903e4541SAndrei Emeltchenko 		/* Read other fragments */
958903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
959903e4541SAndrei Emeltchenko 
960903e4541SAndrei Emeltchenko 		return;
961903e4541SAndrei Emeltchenko 	}
962903e4541SAndrei Emeltchenko 
963903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
964903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
965903e4541SAndrei Emeltchenko 	assoc->offset = 0;
966903e4541SAndrei Emeltchenko 
967903e4541SAndrei Emeltchenko a2mp_rsp:
968903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
969903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
9709495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
971903e4541SAndrei Emeltchenko }
972903e4541SAndrei Emeltchenko 
973b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
974b0916ea0SJohan Hedberg 					  struct sk_buff *skb)
975b0916ea0SJohan Hedberg {
976b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
977b0916ea0SJohan Hedberg 
9789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
979b0916ea0SJohan Hedberg 
980b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
981b0916ea0SJohan Hedberg }
982b0916ea0SJohan Hedberg 
983d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
984d5859e22SJohan Hedberg {
985d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
986d5859e22SJohan Hedberg 
9879f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
988d5859e22SJohan Hedberg 
989d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
990d5859e22SJohan Hedberg }
991d5859e22SJohan Hedberg 
992d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
993d5859e22SJohan Hedberg 				      struct sk_buff *skb)
994d5859e22SJohan Hedberg {
995d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
996d5859e22SJohan Hedberg 
9979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
998d5859e22SJohan Hedberg 
999d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
1000d5859e22SJohan Hedberg }
1001d5859e22SJohan Hedberg 
1002d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
1003d5859e22SJohan Hedberg 					 struct sk_buff *skb)
1004d5859e22SJohan Hedberg {
100591c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
1006d5859e22SJohan Hedberg 
10079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1008d5859e22SJohan Hedberg 
100991c4e9b1SMarcel Holtmann 	if (!rp->status)
101091c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
101191c4e9b1SMarcel Holtmann 
101291c4e9b1SMarcel Holtmann 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
1013d5859e22SJohan Hedberg }
1014d5859e22SJohan Hedberg 
1015d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1016d5859e22SJohan Hedberg {
1017d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
1018d5859e22SJohan Hedberg 
10199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1020d5859e22SJohan Hedberg 
1021d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1022d5859e22SJohan Hedberg }
1023d5859e22SJohan Hedberg 
1024980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1025980e1a53SJohan Hedberg {
1026980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1027980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
1028980e1a53SJohan Hedberg 	struct hci_conn *conn;
1029980e1a53SJohan Hedberg 
10309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1031980e1a53SJohan Hedberg 
103256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
103356e5cb86SJohan Hedberg 
1034a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1035744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
1036980e1a53SJohan Hedberg 
1037fa1bd918SMikel Astiz 	if (rp->status)
103856e5cb86SJohan Hedberg 		goto unlock;
1039980e1a53SJohan Hedberg 
1040980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1041980e1a53SJohan Hedberg 	if (!cp)
104256e5cb86SJohan Hedberg 		goto unlock;
1043980e1a53SJohan Hedberg 
1044980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1045980e1a53SJohan Hedberg 	if (conn)
1046980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
104756e5cb86SJohan Hedberg 
104856e5cb86SJohan Hedberg unlock:
104956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1050980e1a53SJohan Hedberg }
1051980e1a53SJohan Hedberg 
1052980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1053980e1a53SJohan Hedberg {
1054980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1055980e1a53SJohan Hedberg 
10569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1057980e1a53SJohan Hedberg 
105856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
105956e5cb86SJohan Hedberg 
1060a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1061744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
1062980e1a53SJohan Hedberg 						 rp->status);
106356e5cb86SJohan Hedberg 
106456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1065980e1a53SJohan Hedberg }
106656e5cb86SJohan Hedberg 
10676ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
10686ed58ec5SVille Tervo 				       struct sk_buff *skb)
10696ed58ec5SVille Tervo {
10706ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
10716ed58ec5SVille Tervo 
10729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10736ed58ec5SVille Tervo 
10746ed58ec5SVille Tervo 	if (rp->status)
10756ed58ec5SVille Tervo 		return;
10766ed58ec5SVille Tervo 
10776ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
10786ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
10796ed58ec5SVille Tervo 
10806ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
10816ed58ec5SVille Tervo 
10826ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
10836ed58ec5SVille Tervo 
10846ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
10856ed58ec5SVille Tervo }
1086980e1a53SJohan Hedberg 
10878fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
10888fa19098SJohan Hedberg 					struct sk_buff *skb)
10898fa19098SJohan Hedberg {
10908fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
10918fa19098SJohan Hedberg 
10928fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10938fa19098SJohan Hedberg 
10948fa19098SJohan Hedberg 	if (!rp->status)
10958fa19098SJohan Hedberg 		hdev->adv_tx_power = rp->tx_power;
10968fa19098SJohan Hedberg 
10978fa19098SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
10988fa19098SJohan Hedberg }
10998fa19098SJohan Hedberg 
1100e36b04c8SJohan Hedberg static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1101e36b04c8SJohan Hedberg {
1102e36b04c8SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
1103e36b04c8SJohan Hedberg 
1104e36b04c8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1105e36b04c8SJohan Hedberg 
1106e36b04c8SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1107e36b04c8SJohan Hedberg }
1108e36b04c8SJohan Hedberg 
1109a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1110a5c29683SJohan Hedberg {
1111a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1112a5c29683SJohan Hedberg 
11139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1114a5c29683SJohan Hedberg 
111556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
111656e5cb86SJohan Hedberg 
1117a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
111804124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
111904124681SGustavo F. Padovan 						 rp->status);
112056e5cb86SJohan Hedberg 
112156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1122a5c29683SJohan Hedberg }
1123a5c29683SJohan Hedberg 
1124a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
1125a5c29683SJohan Hedberg 					  struct sk_buff *skb)
1126a5c29683SJohan Hedberg {
1127a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1128a5c29683SJohan Hedberg 
11299f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1130a5c29683SJohan Hedberg 
113156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
113256e5cb86SJohan Hedberg 
1133a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1134744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
113504124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
113656e5cb86SJohan Hedberg 
113756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1138a5c29683SJohan Hedberg }
1139a5c29683SJohan Hedberg 
11401143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
11411143d458SBrian Gix {
11421143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
11431143d458SBrian Gix 
11449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
11451143d458SBrian Gix 
11461143d458SBrian Gix 	hci_dev_lock(hdev);
11471143d458SBrian Gix 
1148a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1149272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1150272d90dfSJohan Hedberg 						 0, rp->status);
11511143d458SBrian Gix 
11521143d458SBrian Gix 	hci_dev_unlock(hdev);
11531143d458SBrian Gix }
11541143d458SBrian Gix 
11551143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
11561143d458SBrian Gix 					  struct sk_buff *skb)
11571143d458SBrian Gix {
11581143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
11591143d458SBrian Gix 
11609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
11611143d458SBrian Gix 
11621143d458SBrian Gix 	hci_dev_lock(hdev);
11631143d458SBrian Gix 
1164a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
11651143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
116604124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
11671143d458SBrian Gix 
11681143d458SBrian Gix 	hci_dev_unlock(hdev);
11691143d458SBrian Gix }
11701143d458SBrian Gix 
1171c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1172c35938b2SSzymon Janc 					     struct sk_buff *skb)
1173c35938b2SSzymon Janc {
1174c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1175c35938b2SSzymon Janc 
11769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1177c35938b2SSzymon Janc 
117856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1179744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1180c35938b2SSzymon Janc 						rp->randomizer, rp->status);
118156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1182c35938b2SSzymon Janc }
1183c35938b2SSzymon Janc 
118407f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
118507f7fa5dSAndre Guedes {
118607f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
118707f7fa5dSAndre Guedes 
11889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
11897ba8b4beSAndre Guedes 
11907ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
11913fd24153SAndre Guedes 
11923fd24153SAndre Guedes 	if (status) {
11933fd24153SAndre Guedes 		hci_dev_lock(hdev);
11943fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
11953fd24153SAndre Guedes 		hci_dev_unlock(hdev);
11963fd24153SAndre Guedes 		return;
11973fd24153SAndre Guedes 	}
119807f7fa5dSAndre Guedes }
119907f7fa5dSAndre Guedes 
1200eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1201eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1202eb9d91f5SAndre Guedes {
1203eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1204eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1205eb9d91f5SAndre Guedes 
12069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1207eb9d91f5SAndre Guedes 
1208eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1209eb9d91f5SAndre Guedes 	if (!cp)
1210eb9d91f5SAndre Guedes 		return;
1211eb9d91f5SAndre Guedes 
121268a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
121368a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
12147ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
12157ba8b4beSAndre Guedes 
12163fd24153SAndre Guedes 		if (status) {
12173fd24153SAndre Guedes 			hci_dev_lock(hdev);
12183fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
12193fd24153SAndre Guedes 			hci_dev_unlock(hdev);
12207ba8b4beSAndre Guedes 			return;
12213fd24153SAndre Guedes 		}
12227ba8b4beSAndre Guedes 
1223d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1224d23264a8SAndre Guedes 
1225a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1226343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1227a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
122868a8aea4SAndrei Emeltchenko 		break;
122968a8aea4SAndrei Emeltchenko 
123068a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1231c9ecc48eSAndre Guedes 		if (status) {
1232c9ecc48eSAndre Guedes 			hci_dev_lock(hdev);
1233c9ecc48eSAndre Guedes 			mgmt_stop_discovery_failed(hdev, status);
1234c9ecc48eSAndre Guedes 			hci_dev_unlock(hdev);
12357ba8b4beSAndre Guedes 			return;
1236c9ecc48eSAndre Guedes 		}
12377ba8b4beSAndre Guedes 
1238d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1239d23264a8SAndre Guedes 
1240bc3dd33cSAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1241bc3dd33cSAndre Guedes 		    hdev->discovery.state == DISCOVERY_FINDING) {
12425e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
12435e0452c0SAndre Guedes 		} else {
1244c599008fSAndre Guedes 			hci_dev_lock(hdev);
1245c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1246c599008fSAndre Guedes 			hci_dev_unlock(hdev);
12475e0452c0SAndre Guedes 		}
1248c599008fSAndre Guedes 
124968a8aea4SAndrei Emeltchenko 		break;
125068a8aea4SAndrei Emeltchenko 
125168a8aea4SAndrei Emeltchenko 	default:
125268a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
125368a8aea4SAndrei Emeltchenko 		break;
125435815085SAndre Guedes 	}
1255eb9d91f5SAndre Guedes }
1256eb9d91f5SAndre Guedes 
1257a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1258a7a595f6SVinicius Costa Gomes {
1259a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1260a7a595f6SVinicius Costa Gomes 
12619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1262a7a595f6SVinicius Costa Gomes 
1263a7a595f6SVinicius Costa Gomes 	if (rp->status)
1264a7a595f6SVinicius Costa Gomes 		return;
1265a7a595f6SVinicius Costa Gomes 
1266a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1267a7a595f6SVinicius Costa Gomes }
1268a7a595f6SVinicius Costa Gomes 
1269a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1270a7a595f6SVinicius Costa Gomes {
1271a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1272a7a595f6SVinicius Costa Gomes 
12739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1274a7a595f6SVinicius Costa Gomes 
1275a7a595f6SVinicius Costa Gomes 	if (rp->status)
1276a7a595f6SVinicius Costa Gomes 		return;
1277a7a595f6SVinicius Costa Gomes 
1278a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1279a7a595f6SVinicius Costa Gomes }
1280a7a595f6SVinicius Costa Gomes 
12816039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1282f9b49306SAndre Guedes 					   struct sk_buff *skb)
1283f9b49306SAndre Guedes {
128406199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1285f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1286f9b49306SAndre Guedes 
12879f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1288f9b49306SAndre Guedes 
128906199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
12908f984dfaSJohan Hedberg 	if (!sent)
1291f9b49306SAndre Guedes 		return;
1292f9b49306SAndre Guedes 
12938f984dfaSJohan Hedberg 	if (!status) {
12948f984dfaSJohan Hedberg 		if (sent->le)
12958f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
12968f984dfaSJohan Hedberg 		else
12978f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
129853b2caabSJohan Hedberg 
129953b2caabSJohan Hedberg 		if (sent->simul)
130053b2caabSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE_BREDR;
130153b2caabSJohan Hedberg 		else
130253b2caabSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
13038f984dfaSJohan Hedberg 	}
13048f984dfaSJohan Hedberg 
13058f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
13068f984dfaSJohan Hedberg 	    !test_bit(HCI_INIT, &hdev->flags))
13078f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
13088f984dfaSJohan Hedberg 
13098f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1310f9b49306SAndre Guedes }
1311f9b49306SAndre Guedes 
131293c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
131393c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
131493c284eeSAndrei Emeltchenko {
131593c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
131693c284eeSAndrei Emeltchenko 
131793c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
131893c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
131993c284eeSAndrei Emeltchenko 
132093c284eeSAndrei Emeltchenko 	if (rp->status)
132193c284eeSAndrei Emeltchenko 		return;
132293c284eeSAndrei Emeltchenko 
132393c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
132493c284eeSAndrei Emeltchenko }
132593c284eeSAndrei Emeltchenko 
13266039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1327a9de9248SMarcel Holtmann {
13289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1329a9de9248SMarcel Holtmann 
1330a9de9248SMarcel Holtmann 	if (status) {
133123bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1332a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
133356e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1334a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
13357a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
133656e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1337314b2381SJohan Hedberg 		return;
1338314b2381SJohan Hedberg 	}
1339314b2381SJohan Hedberg 
134089352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
134189352e7dSAndre Guedes 
134256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1343343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
134456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1345a9de9248SMarcel Holtmann }
1346a9de9248SMarcel Holtmann 
13476039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
13481da177e4SLinus Torvalds {
1349a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
13501da177e4SLinus Torvalds 	struct hci_conn *conn;
13511da177e4SLinus Torvalds 
13529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1353a9de9248SMarcel Holtmann 
1354a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
13551da177e4SLinus Torvalds 	if (!cp)
13561da177e4SLinus Torvalds 		return;
13571da177e4SLinus Torvalds 
13581da177e4SLinus Torvalds 	hci_dev_lock(hdev);
13591da177e4SLinus Torvalds 
13601da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
13611da177e4SLinus Torvalds 
13626ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
13631da177e4SLinus Torvalds 
13641da177e4SLinus Torvalds 	if (status) {
13651da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
13664c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
13671da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
13681da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
13691da177e4SLinus Torvalds 				hci_conn_del(conn);
13704c67bc74SMarcel Holtmann 			} else
13714c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
13721da177e4SLinus Torvalds 		}
13731da177e4SLinus Torvalds 	} else {
13741da177e4SLinus Torvalds 		if (!conn) {
13751da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
13761da177e4SLinus Torvalds 			if (conn) {
1377a0c808b3SJohan Hedberg 				conn->out = true;
13781da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
13791da177e4SLinus Torvalds 			} else
1380893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
13811da177e4SLinus Torvalds 		}
13821da177e4SLinus Torvalds 	}
13831da177e4SLinus Torvalds 
13841da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
13851da177e4SLinus Torvalds }
13861da177e4SLinus Torvalds 
1387a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
13881da177e4SLinus Torvalds {
1389a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
13901da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
13911da177e4SLinus Torvalds 	__u16 handle;
13921da177e4SLinus Torvalds 
13939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1394b6a0dc82SMarcel Holtmann 
1395a9de9248SMarcel Holtmann 	if (!status)
1396a9de9248SMarcel Holtmann 		return;
1397a9de9248SMarcel Holtmann 
1398a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
13991da177e4SLinus Torvalds 	if (!cp)
1400a9de9248SMarcel Holtmann 		return;
14011da177e4SLinus Torvalds 
14021da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
14031da177e4SLinus Torvalds 
14049f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
14051da177e4SLinus Torvalds 
14061da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14071da177e4SLinus Torvalds 
14081da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14095a08ecceSAndrei Emeltchenko 	if (acl) {
14105a08ecceSAndrei Emeltchenko 		sco = acl->link;
14115a08ecceSAndrei Emeltchenko 		if (sco) {
14121da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
14131da177e4SLinus Torvalds 
14141da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
14151da177e4SLinus Torvalds 			hci_conn_del(sco);
14161da177e4SLinus Torvalds 		}
14175a08ecceSAndrei Emeltchenko 	}
14181da177e4SLinus Torvalds 
14191da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14201da177e4SLinus Torvalds }
14211da177e4SLinus Torvalds 
1422f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1423f8558555SMarcel Holtmann {
1424f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1425f8558555SMarcel Holtmann 	struct hci_conn *conn;
1426f8558555SMarcel Holtmann 
14279f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1428f8558555SMarcel Holtmann 
1429f8558555SMarcel Holtmann 	if (!status)
1430f8558555SMarcel Holtmann 		return;
1431f8558555SMarcel Holtmann 
1432f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1433f8558555SMarcel Holtmann 	if (!cp)
1434f8558555SMarcel Holtmann 		return;
1435f8558555SMarcel Holtmann 
1436f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1437f8558555SMarcel Holtmann 
1438f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1439f8558555SMarcel Holtmann 	if (conn) {
1440f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1441f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1442f8558555SMarcel Holtmann 			hci_conn_put(conn);
1443f8558555SMarcel Holtmann 		}
1444f8558555SMarcel Holtmann 	}
1445f8558555SMarcel Holtmann 
1446f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1447f8558555SMarcel Holtmann }
1448f8558555SMarcel Holtmann 
1449f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1450f8558555SMarcel Holtmann {
1451f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1452f8558555SMarcel Holtmann 	struct hci_conn *conn;
1453f8558555SMarcel Holtmann 
14549f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1455f8558555SMarcel Holtmann 
1456f8558555SMarcel Holtmann 	if (!status)
1457f8558555SMarcel Holtmann 		return;
1458f8558555SMarcel Holtmann 
1459f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1460f8558555SMarcel Holtmann 	if (!cp)
1461f8558555SMarcel Holtmann 		return;
1462f8558555SMarcel Holtmann 
1463f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1464f8558555SMarcel Holtmann 
1465f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1466f8558555SMarcel Holtmann 	if (conn) {
1467f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1468f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1469f8558555SMarcel Holtmann 			hci_conn_put(conn);
1470f8558555SMarcel Holtmann 		}
1471f8558555SMarcel Holtmann 	}
1472f8558555SMarcel Holtmann 
1473f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1474f8558555SMarcel Holtmann }
1475f8558555SMarcel Holtmann 
1476127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1477392599b9SJohan Hedberg 				    struct hci_conn *conn)
1478392599b9SJohan Hedberg {
1479392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1480392599b9SJohan Hedberg 		return 0;
1481392599b9SJohan Hedberg 
1482765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1483392599b9SJohan Hedberg 		return 0;
1484392599b9SJohan Hedberg 
1485392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1486e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1487807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1488807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1489392599b9SJohan Hedberg 		return 0;
1490392599b9SJohan Hedberg 
1491392599b9SJohan Hedberg 	return 1;
1492392599b9SJohan Hedberg }
1493392599b9SJohan Hedberg 
14946039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
149500abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
149630dc78e1SJohan Hedberg {
149730dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
149830dc78e1SJohan Hedberg 
149930dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
150030dc78e1SJohan Hedberg 
150130dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
150230dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
150330dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
150430dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
150530dc78e1SJohan Hedberg 
150630dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
150730dc78e1SJohan Hedberg }
150830dc78e1SJohan Hedberg 
1509b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
151030dc78e1SJohan Hedberg {
151130dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
151230dc78e1SJohan Hedberg 	struct inquiry_entry *e;
151330dc78e1SJohan Hedberg 
1514b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1515b644ba33SJohan Hedberg 		return false;
1516b644ba33SJohan Hedberg 
1517b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1518c810089cSRam Malovany 	if (!e)
1519c810089cSRam Malovany 		return false;
1520c810089cSRam Malovany 
1521b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1522b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1523b644ba33SJohan Hedberg 		return true;
1524b644ba33SJohan Hedberg 	}
1525b644ba33SJohan Hedberg 
1526b644ba33SJohan Hedberg 	return false;
1527b644ba33SJohan Hedberg }
1528b644ba33SJohan Hedberg 
1529b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1530b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1531b644ba33SJohan Hedberg {
1532b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1533b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1534b644ba33SJohan Hedberg 
1535b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
153604124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
153704124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1538b644ba33SJohan Hedberg 
1539b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1540b644ba33SJohan Hedberg 		return;
1541b644ba33SJohan Hedberg 
154230dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
154330dc78e1SJohan Hedberg 		goto discov_complete;
154430dc78e1SJohan Hedberg 
154530dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
154630dc78e1SJohan Hedberg 		return;
154730dc78e1SJohan Hedberg 
154830dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
15497cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
15507cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
15517cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
15527cc8380eSRam Malovany 	 * Event */
15537cc8380eSRam Malovany 	if (!e)
15547cc8380eSRam Malovany 		return;
15557cc8380eSRam Malovany 
155630dc78e1SJohan Hedberg 	list_del(&e->list);
15577cc8380eSRam Malovany 	if (name) {
15587cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1559b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1560b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1561c3e7c0d9SRam Malovany 	} else {
1562c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
156330dc78e1SJohan Hedberg 	}
156430dc78e1SJohan Hedberg 
1565b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
156630dc78e1SJohan Hedberg 		return;
156730dc78e1SJohan Hedberg 
156830dc78e1SJohan Hedberg discov_complete:
156930dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
157030dc78e1SJohan Hedberg }
157130dc78e1SJohan Hedberg 
1572a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
15731da177e4SLinus Torvalds {
1574127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1575127178d2SJohan Hedberg 	struct hci_conn *conn;
1576127178d2SJohan Hedberg 
15779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1578127178d2SJohan Hedberg 
1579127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1580127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1581127178d2SJohan Hedberg 	if (!status)
1582127178d2SJohan Hedberg 		return;
1583127178d2SJohan Hedberg 
1584127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1585127178d2SJohan Hedberg 	if (!cp)
1586127178d2SJohan Hedberg 		return;
1587127178d2SJohan Hedberg 
1588127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1589127178d2SJohan Hedberg 
1590127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1591b644ba33SJohan Hedberg 
1592b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1593b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1594b644ba33SJohan Hedberg 
159579c6c70cSJohan Hedberg 	if (!conn)
159679c6c70cSJohan Hedberg 		goto unlock;
159779c6c70cSJohan Hedberg 
159879c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
159979c6c70cSJohan Hedberg 		goto unlock;
160079c6c70cSJohan Hedberg 
160151a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1602127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1603127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1604127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1605127178d2SJohan Hedberg 	}
1606127178d2SJohan Hedberg 
160779c6c70cSJohan Hedberg unlock:
1608127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1609a9de9248SMarcel Holtmann }
16101da177e4SLinus Torvalds 
1611769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1612769be974SMarcel Holtmann {
1613769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1614769be974SMarcel Holtmann 	struct hci_conn *conn;
1615769be974SMarcel Holtmann 
16169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1617769be974SMarcel Holtmann 
1618769be974SMarcel Holtmann 	if (!status)
1619769be974SMarcel Holtmann 		return;
1620769be974SMarcel Holtmann 
1621769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1622769be974SMarcel Holtmann 	if (!cp)
1623769be974SMarcel Holtmann 		return;
1624769be974SMarcel Holtmann 
1625769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1626769be974SMarcel Holtmann 
1627769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1628769be974SMarcel Holtmann 	if (conn) {
1629769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1630769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1631769be974SMarcel Holtmann 			hci_conn_put(conn);
1632769be974SMarcel Holtmann 		}
1633769be974SMarcel Holtmann 	}
1634769be974SMarcel Holtmann 
1635769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1636769be974SMarcel Holtmann }
1637769be974SMarcel Holtmann 
1638769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1639769be974SMarcel Holtmann {
1640769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1641769be974SMarcel Holtmann 	struct hci_conn *conn;
1642769be974SMarcel Holtmann 
16439f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1644769be974SMarcel Holtmann 
1645769be974SMarcel Holtmann 	if (!status)
1646769be974SMarcel Holtmann 		return;
1647769be974SMarcel Holtmann 
1648769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1649769be974SMarcel Holtmann 	if (!cp)
1650769be974SMarcel Holtmann 		return;
1651769be974SMarcel Holtmann 
1652769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1653769be974SMarcel Holtmann 
1654769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1655769be974SMarcel Holtmann 	if (conn) {
1656769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1657769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1658769be974SMarcel Holtmann 			hci_conn_put(conn);
1659769be974SMarcel Holtmann 		}
1660769be974SMarcel Holtmann 	}
1661769be974SMarcel Holtmann 
1662769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1663769be974SMarcel Holtmann }
1664769be974SMarcel Holtmann 
1665a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1666a9de9248SMarcel Holtmann {
1667b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1668b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1669b6a0dc82SMarcel Holtmann 	__u16 handle;
1670b6a0dc82SMarcel Holtmann 
16719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1672b6a0dc82SMarcel Holtmann 
1673b6a0dc82SMarcel Holtmann 	if (!status)
1674b6a0dc82SMarcel Holtmann 		return;
1675b6a0dc82SMarcel Holtmann 
1676b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1677b6a0dc82SMarcel Holtmann 	if (!cp)
1678b6a0dc82SMarcel Holtmann 		return;
1679b6a0dc82SMarcel Holtmann 
1680b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1681b6a0dc82SMarcel Holtmann 
16829f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1683b6a0dc82SMarcel Holtmann 
1684b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1685b6a0dc82SMarcel Holtmann 
1686b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
16875a08ecceSAndrei Emeltchenko 	if (acl) {
16885a08ecceSAndrei Emeltchenko 		sco = acl->link;
16895a08ecceSAndrei Emeltchenko 		if (sco) {
1690b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1691b6a0dc82SMarcel Holtmann 
1692b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1693b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1694b6a0dc82SMarcel Holtmann 		}
16955a08ecceSAndrei Emeltchenko 	}
1696b6a0dc82SMarcel Holtmann 
1697b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1698a9de9248SMarcel Holtmann }
1699a9de9248SMarcel Holtmann 
1700a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1701a9de9248SMarcel Holtmann {
1702a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
170304837f64SMarcel Holtmann 	struct hci_conn *conn;
170404837f64SMarcel Holtmann 
17059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1706a9de9248SMarcel Holtmann 
1707a9de9248SMarcel Holtmann 	if (!status)
1708a9de9248SMarcel Holtmann 		return;
1709a9de9248SMarcel Holtmann 
1710a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
171104837f64SMarcel Holtmann 	if (!cp)
1712a9de9248SMarcel Holtmann 		return;
171304837f64SMarcel Holtmann 
171404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
171504837f64SMarcel Holtmann 
171604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1717e73439d8SMarcel Holtmann 	if (conn) {
171851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
171904837f64SMarcel Holtmann 
172051a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1721e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1722e73439d8SMarcel Holtmann 	}
1723e73439d8SMarcel Holtmann 
172404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
172504837f64SMarcel Holtmann }
172604837f64SMarcel Holtmann 
1727a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1728a9de9248SMarcel Holtmann {
1729a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
173004837f64SMarcel Holtmann 	struct hci_conn *conn;
173104837f64SMarcel Holtmann 
17329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1733a9de9248SMarcel Holtmann 
1734a9de9248SMarcel Holtmann 	if (!status)
1735a9de9248SMarcel Holtmann 		return;
1736a9de9248SMarcel Holtmann 
1737a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
173804837f64SMarcel Holtmann 	if (!cp)
1739a9de9248SMarcel Holtmann 		return;
174004837f64SMarcel Holtmann 
174104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
174204837f64SMarcel Holtmann 
174304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1744e73439d8SMarcel Holtmann 	if (conn) {
174551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
174604837f64SMarcel Holtmann 
174751a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1748e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1749e73439d8SMarcel Holtmann 	}
1750e73439d8SMarcel Holtmann 
175104837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
175204837f64SMarcel Holtmann }
175304837f64SMarcel Holtmann 
175488c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
175588c3df13SJohan Hedberg {
175688c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
175788c3df13SJohan Hedberg 	struct hci_conn *conn;
175888c3df13SJohan Hedberg 
175988c3df13SJohan Hedberg 	if (!status)
176088c3df13SJohan Hedberg 		return;
176188c3df13SJohan Hedberg 
176288c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
176388c3df13SJohan Hedberg 	if (!cp)
176488c3df13SJohan Hedberg 		return;
176588c3df13SJohan Hedberg 
176688c3df13SJohan Hedberg 	hci_dev_lock(hdev);
176788c3df13SJohan Hedberg 
176888c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
176988c3df13SJohan Hedberg 	if (conn)
177088c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
177188c3df13SJohan Hedberg 				       conn->dst_type, status);
177288c3df13SJohan Hedberg 
177388c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
177488c3df13SJohan Hedberg }
177588c3df13SJohan Hedberg 
1776fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1777fcd89c09SVille Tervo {
1778fcd89c09SVille Tervo 	struct hci_conn *conn;
1779fcd89c09SVille Tervo 
17809f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1781fcd89c09SVille Tervo 
1782f00a06acSAndre Guedes 	if (status) {
1783fcd89c09SVille Tervo 		hci_dev_lock(hdev);
1784fcd89c09SVille Tervo 
17850c95ab78SAndre Guedes 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
1786f00a06acSAndre Guedes 		if (!conn) {
1787f00a06acSAndre Guedes 			hci_dev_unlock(hdev);
1788f00a06acSAndre Guedes 			return;
1789f00a06acSAndre Guedes 		}
1790fcd89c09SVille Tervo 
17916ed93dc6SAndrei Emeltchenko 		BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
1792fcd89c09SVille Tervo 
1793fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
17940c95ab78SAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
1795328c9248SHemant Gupta 				    conn->dst_type, status);
1796fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, status);
1797fcd89c09SVille Tervo 		hci_conn_del(conn);
1798fcd89c09SVille Tervo 
1799fcd89c09SVille Tervo 		hci_dev_unlock(hdev);
1800fcd89c09SVille Tervo 	}
1801f00a06acSAndre Guedes }
1802fcd89c09SVille Tervo 
1803a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1804a7a595f6SVinicius Costa Gomes {
18059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1806a7a595f6SVinicius Costa Gomes }
1807a7a595f6SVinicius Costa Gomes 
1808a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1809a02226d6SAndrei Emeltchenko {
181093c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
181193c284eeSAndrei Emeltchenko 
1812a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
181393c284eeSAndrei Emeltchenko 
181493c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
181593c284eeSAndrei Emeltchenko 	if (!cp)
181693c284eeSAndrei Emeltchenko 		return;
181793c284eeSAndrei Emeltchenko 
1818e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1819e58917b9SAndrei Emeltchenko 
1820e58917b9SAndrei Emeltchenko 	if (status) {
1821e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1822e58917b9SAndrei Emeltchenko 
1823e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1824e58917b9SAndrei Emeltchenko 		if (hcon)
1825e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1826e58917b9SAndrei Emeltchenko 	} else {
182793c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1828a02226d6SAndrei Emeltchenko 	}
1829a02226d6SAndrei Emeltchenko 
1830e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1831e58917b9SAndrei Emeltchenko }
1832e58917b9SAndrei Emeltchenko 
18330b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
18340b26ab9dSAndrei Emeltchenko {
18350b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
18360b26ab9dSAndrei Emeltchenko 
18370b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18380b26ab9dSAndrei Emeltchenko 
18390b26ab9dSAndrei Emeltchenko 	if (status)
18400b26ab9dSAndrei Emeltchenko 		return;
18410b26ab9dSAndrei Emeltchenko 
18420b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
18430b26ab9dSAndrei Emeltchenko 	if (!cp)
18440b26ab9dSAndrei Emeltchenko 		return;
18450b26ab9dSAndrei Emeltchenko 
18460b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
18470b26ab9dSAndrei Emeltchenko }
18480b26ab9dSAndrei Emeltchenko 
18495ce66b59SAndrei Emeltchenko static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
18505ce66b59SAndrei Emeltchenko {
18515ce66b59SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18525ce66b59SAndrei Emeltchenko }
18535ce66b59SAndrei Emeltchenko 
18546039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18551da177e4SLinus Torvalds {
18561da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
185730dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
185830dc78e1SJohan Hedberg 	struct inquiry_entry *e;
18591da177e4SLinus Torvalds 
18609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18611da177e4SLinus Torvalds 
186223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
18636bd57416SMarcel Holtmann 
1864a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
186589352e7dSAndre Guedes 
186689352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
186789352e7dSAndre Guedes 		return;
186889352e7dSAndre Guedes 
1869a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
187030dc78e1SJohan Hedberg 		return;
187130dc78e1SJohan Hedberg 
187256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
187330dc78e1SJohan Hedberg 
1874343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
187530dc78e1SJohan Hedberg 		goto unlock;
187630dc78e1SJohan Hedberg 
187730dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1878ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
187930dc78e1SJohan Hedberg 		goto unlock;
188030dc78e1SJohan Hedberg 	}
188130dc78e1SJohan Hedberg 
188230dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
188330dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
188430dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
188530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
188630dc78e1SJohan Hedberg 	} else {
188730dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
188830dc78e1SJohan Hedberg 	}
188930dc78e1SJohan Hedberg 
189030dc78e1SJohan Hedberg unlock:
189156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
18921da177e4SLinus Torvalds }
18931da177e4SLinus Torvalds 
18946039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
18951da177e4SLinus Torvalds {
189645bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1897a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
18981da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
18991da177e4SLinus Torvalds 
19001da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
19011da177e4SLinus Torvalds 
190245bb4bf0SMarcel Holtmann 	if (!num_rsp)
190345bb4bf0SMarcel Holtmann 		return;
190445bb4bf0SMarcel Holtmann 
19051519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
19061519cc17SAndre Guedes 		return;
19071519cc17SAndre Guedes 
19081da177e4SLinus Torvalds 	hci_dev_lock(hdev);
190945bb4bf0SMarcel Holtmann 
1910e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1911388fc8faSJohan Hedberg 		bool name_known, ssp;
19123175405bSJohan Hedberg 
19131da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
19141da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
19151da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
19161da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
19171da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
19181da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
19191da177e4SLinus Torvalds 		data.rssi		= 0x00;
192041a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
19213175405bSJohan Hedberg 
1922388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
192348264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
192404124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
192504124681SGustavo F. Padovan 				  0);
19261da177e4SLinus Torvalds 	}
192745bb4bf0SMarcel Holtmann 
19281da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19291da177e4SLinus Torvalds }
19301da177e4SLinus Torvalds 
19316039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19321da177e4SLinus Torvalds {
1933a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1934a9de9248SMarcel Holtmann 	struct hci_conn *conn;
19351da177e4SLinus Torvalds 
1936a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
193745bb4bf0SMarcel Holtmann 
19381da177e4SLinus Torvalds 	hci_dev_lock(hdev);
193945bb4bf0SMarcel Holtmann 
1940a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
19419499237aSMarcel Holtmann 	if (!conn) {
19429499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
19439499237aSMarcel Holtmann 			goto unlock;
19449499237aSMarcel Holtmann 
19459499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1946a9de9248SMarcel Holtmann 		if (!conn)
1947a9de9248SMarcel Holtmann 			goto unlock;
194845bb4bf0SMarcel Holtmann 
19499499237aSMarcel Holtmann 		conn->type = SCO_LINK;
19509499237aSMarcel Holtmann 	}
19519499237aSMarcel Holtmann 
1952a9de9248SMarcel Holtmann 	if (!ev->status) {
1953a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1954769be974SMarcel Holtmann 
1955769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1956769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1957769be974SMarcel Holtmann 			hci_conn_hold(conn);
1958a9ea3ed9SSzymon Janc 
1959a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1960a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1961a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1962a9ea3ed9SSzymon Janc 			else
1963052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1964769be974SMarcel Holtmann 		} else
1965a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1966a9de9248SMarcel Holtmann 
19679eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
19687d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
19697d0db0a3SMarcel Holtmann 
1970a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1971a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1972a9de9248SMarcel Holtmann 
1973a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1974a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1975a9de9248SMarcel Holtmann 
1976a9de9248SMarcel Holtmann 		/* Get remote features */
1977a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1978a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1979a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1980769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1981769be974SMarcel Holtmann 				     sizeof(cp), &cp);
198245bb4bf0SMarcel Holtmann 		}
1983a9de9248SMarcel Holtmann 
1984a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1985d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1986a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1987a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1988a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
198904124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
199004124681SGustavo F. Padovan 				     &cp);
1991a9de9248SMarcel Holtmann 		}
199217d5c04cSJohan Hedberg 	} else {
1993a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
199417d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1995744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
199648264f06SJohan Hedberg 					    conn->dst_type, ev->status);
199717d5c04cSJohan Hedberg 	}
199845bb4bf0SMarcel Holtmann 
1999e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
2000e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
200145bb4bf0SMarcel Holtmann 
2002769be974SMarcel Holtmann 	if (ev->status) {
2003a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2004a9de9248SMarcel Holtmann 		hci_conn_del(conn);
2005c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
2006c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2007a9de9248SMarcel Holtmann 
2008a9de9248SMarcel Holtmann unlock:
20091da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
2010a9de9248SMarcel Holtmann 
2011a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
20121da177e4SLinus Torvalds }
20131da177e4SLinus Torvalds 
20146039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
20151da177e4SLinus Torvalds {
2016a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
20171da177e4SLinus Torvalds 	int mask = hdev->link_mode;
20181da177e4SLinus Torvalds 
20196ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
2020807deac2SGustavo Padovan 	       ev->link_type);
20211da177e4SLinus Torvalds 
20221da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
20231da177e4SLinus Torvalds 
2024138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
2025138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
20261da177e4SLinus Torvalds 		/* Connection accepted */
2027c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
20281da177e4SLinus Torvalds 		struct hci_conn *conn;
20291da177e4SLinus Torvalds 
20301da177e4SLinus Torvalds 		hci_dev_lock(hdev);
2031b6a0dc82SMarcel Holtmann 
2032cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2033cc11b9c1SAndrei Emeltchenko 		if (ie)
2034c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
2035c7bdd502SMarcel Holtmann 
20368fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
20378fc9ced3SGustavo Padovan 					       &ev->bdaddr);
20381da177e4SLinus Torvalds 		if (!conn) {
2039cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2040cc11b9c1SAndrei Emeltchenko 			if (!conn) {
2041893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
20421da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
20431da177e4SLinus Torvalds 				return;
20441da177e4SLinus Torvalds 			}
20451da177e4SLinus Torvalds 		}
2046b6a0dc82SMarcel Holtmann 
20471da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
20481da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
2049b6a0dc82SMarcel Holtmann 
20501da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
20511da177e4SLinus Torvalds 
2052b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
2053b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
2054b6a0dc82SMarcel Holtmann 
20551da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
20561da177e4SLinus Torvalds 
20571da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
20581da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
20591da177e4SLinus Torvalds 			else
20601da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
20611da177e4SLinus Torvalds 
206204124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
206304124681SGustavo F. Padovan 				     &cp);
2064b6a0dc82SMarcel Holtmann 		} else {
2065b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
2066b6a0dc82SMarcel Holtmann 
2067b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
2068a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
2069b6a0dc82SMarcel Holtmann 
207082781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
207182781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
207282781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
2073b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
2074b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
2075b6a0dc82SMarcel Holtmann 
2076b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2077b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
2078b6a0dc82SMarcel Holtmann 		}
20791da177e4SLinus Torvalds 	} else {
20801da177e4SLinus Torvalds 		/* Connection rejected */
20811da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
20821da177e4SLinus Torvalds 
20831da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
20849f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
2085a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
20861da177e4SLinus Torvalds 	}
20871da177e4SLinus Torvalds }
20881da177e4SLinus Torvalds 
2089f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2090f0d6a0eaSMikel Astiz {
2091f0d6a0eaSMikel Astiz 	switch (err) {
2092f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2093f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2094f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2095f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2096f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2097f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2098f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2099f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2100f0d6a0eaSMikel Astiz 	default:
2101f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2102f0d6a0eaSMikel Astiz 	}
2103f0d6a0eaSMikel Astiz }
2104f0d6a0eaSMikel Astiz 
21056039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
21061da177e4SLinus Torvalds {
2107a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
210804837f64SMarcel Holtmann 	struct hci_conn *conn;
21091da177e4SLinus Torvalds 
21109f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
21111da177e4SLinus Torvalds 
21121da177e4SLinus Torvalds 	hci_dev_lock(hdev);
21131da177e4SLinus Torvalds 
211404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2115f7520543SJohan Hedberg 	if (!conn)
2116f7520543SJohan Hedberg 		goto unlock;
2117f7520543SJohan Hedberg 
211837d9ef76SJohan Hedberg 	if (ev->status == 0)
21191da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
21207d0db0a3SMarcel Holtmann 
2121b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
2122b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
2123f0d6a0eaSMikel Astiz 		if (ev->status) {
212488c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
212588c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
2126f0d6a0eaSMikel Astiz 		} else {
2127f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
2128f0d6a0eaSMikel Astiz 
2129afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
2130f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
2131f0d6a0eaSMikel Astiz 		}
213237d9ef76SJohan Hedberg 	}
2133f7520543SJohan Hedberg 
213437d9ef76SJohan Hedberg 	if (ev->status == 0) {
21356ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
21366ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
21372950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
21381da177e4SLinus Torvalds 		hci_conn_del(conn);
213937d9ef76SJohan Hedberg 	}
21401da177e4SLinus Torvalds 
2141f7520543SJohan Hedberg unlock:
21421da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
21431da177e4SLinus Torvalds }
21441da177e4SLinus Torvalds 
21456039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2146a9de9248SMarcel Holtmann {
2147a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2148a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2149a9de9248SMarcel Holtmann 
21509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2151a9de9248SMarcel Holtmann 
2152a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2153a9de9248SMarcel Holtmann 
2154a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2155d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2156d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2157d7556e20SWaldemar Rymarkiewicz 
2158765c2a96SJohan Hedberg 	if (!ev->status) {
2159aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
216051a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2161d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
216219f8def0SWaldemar Rymarkiewicz 		} else {
2163a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2164765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
216519f8def0SWaldemar Rymarkiewicz 		}
21662a611692SJohan Hedberg 	} else {
2167bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
2168bab73cb6SJohan Hedberg 				 ev->status);
21692a611692SJohan Hedberg 	}
2170a9de9248SMarcel Holtmann 
217151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
217251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2173a9de9248SMarcel Holtmann 
2174f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2175aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2176f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2177f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2178f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2179d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2180d7556e20SWaldemar Rymarkiewicz 				     &cp);
2181f8558555SMarcel Holtmann 		} else {
2182f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2183f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2184f8558555SMarcel Holtmann 			hci_conn_put(conn);
2185f8558555SMarcel Holtmann 		}
2186052b30b0SMarcel Holtmann 	} else {
2187a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2188a9de9248SMarcel Holtmann 
2189052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2190052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2191052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2192052b30b0SMarcel Holtmann 	}
2193052b30b0SMarcel Holtmann 
219451a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2195a9de9248SMarcel Holtmann 		if (!ev->status) {
2196a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2197f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2198f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2199d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2200d7556e20SWaldemar Rymarkiewicz 				     &cp);
2201a9de9248SMarcel Holtmann 		} else {
220251a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2203a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2204a9de9248SMarcel Holtmann 		}
2205a9de9248SMarcel Holtmann 	}
2206a9de9248SMarcel Holtmann 
2207d7556e20SWaldemar Rymarkiewicz unlock:
2208a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2209a9de9248SMarcel Holtmann }
2210a9de9248SMarcel Holtmann 
22116039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2212a9de9248SMarcel Holtmann {
2213127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2214127178d2SJohan Hedberg 	struct hci_conn *conn;
2215127178d2SJohan Hedberg 
2216a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2217a9de9248SMarcel Holtmann 
2218a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2219127178d2SJohan Hedberg 
2220127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2221127178d2SJohan Hedberg 
2222127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2223b644ba33SJohan Hedberg 
2224b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2225b644ba33SJohan Hedberg 		goto check_auth;
2226b644ba33SJohan Hedberg 
2227b644ba33SJohan Hedberg 	if (ev->status == 0)
2228b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2229b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2230b644ba33SJohan Hedberg 	else
2231b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2232b644ba33SJohan Hedberg 
2233b644ba33SJohan Hedberg check_auth:
223479c6c70cSJohan Hedberg 	if (!conn)
223579c6c70cSJohan Hedberg 		goto unlock;
223679c6c70cSJohan Hedberg 
223779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
223879c6c70cSJohan Hedberg 		goto unlock;
223979c6c70cSJohan Hedberg 
224051a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2241127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2242127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2243127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2244127178d2SJohan Hedberg 	}
2245127178d2SJohan Hedberg 
224679c6c70cSJohan Hedberg unlock:
2247127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2248a9de9248SMarcel Holtmann }
2249a9de9248SMarcel Holtmann 
22506039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2251a9de9248SMarcel Holtmann {
2252a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2253a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2254a9de9248SMarcel Holtmann 
22559f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2256a9de9248SMarcel Holtmann 
2257a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2258a9de9248SMarcel Holtmann 
2259a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2260a9de9248SMarcel Holtmann 	if (conn) {
2261a9de9248SMarcel Holtmann 		if (!ev->status) {
2262ae293196SMarcel Holtmann 			if (ev->encrypt) {
2263ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2264ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2265a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2266da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2267ae293196SMarcel Holtmann 			} else
2268a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2269a9de9248SMarcel Holtmann 		}
2270a9de9248SMarcel Holtmann 
227151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2272a9de9248SMarcel Holtmann 
2273a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2274d839c813SGustavo Padovan 			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
2275a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2276a7d7723aSGustavo Padovan 			goto unlock;
2277a7d7723aSGustavo Padovan 		}
2278a7d7723aSGustavo Padovan 
2279f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2280f8558555SMarcel Holtmann 			if (!ev->status)
2281f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2282f8558555SMarcel Holtmann 
2283f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2284f8558555SMarcel Holtmann 			hci_conn_put(conn);
2285f8558555SMarcel Holtmann 		} else
2286a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2287a9de9248SMarcel Holtmann 	}
2288a9de9248SMarcel Holtmann 
2289a7d7723aSGustavo Padovan unlock:
2290a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2291a9de9248SMarcel Holtmann }
2292a9de9248SMarcel Holtmann 
22936039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2294807deac2SGustavo Padovan 					     struct sk_buff *skb)
2295a9de9248SMarcel Holtmann {
2296a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2297a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2298a9de9248SMarcel Holtmann 
22999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2300a9de9248SMarcel Holtmann 
2301a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2302a9de9248SMarcel Holtmann 
2303a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2304a9de9248SMarcel Holtmann 	if (conn) {
2305a9de9248SMarcel Holtmann 		if (!ev->status)
2306a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2307a9de9248SMarcel Holtmann 
230851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2309a9de9248SMarcel Holtmann 
2310a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2311a9de9248SMarcel Holtmann 	}
2312a9de9248SMarcel Holtmann 
2313a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2314a9de9248SMarcel Holtmann }
2315a9de9248SMarcel Holtmann 
23166039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2317807deac2SGustavo Padovan 				    struct sk_buff *skb)
2318a9de9248SMarcel Holtmann {
2319a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2320a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2321a9de9248SMarcel Holtmann 
23229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2323a9de9248SMarcel Holtmann 
2324a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2325a9de9248SMarcel Holtmann 
2326a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2327ccd556feSJohan Hedberg 	if (!conn)
2328ccd556feSJohan Hedberg 		goto unlock;
2329ccd556feSJohan Hedberg 
2330769be974SMarcel Holtmann 	if (!ev->status)
2331a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2332a9de9248SMarcel Holtmann 
2333ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2334ccd556feSJohan Hedberg 		goto unlock;
2335ccd556feSJohan Hedberg 
2336ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2337769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2338769be974SMarcel Holtmann 		cp.handle = ev->handle;
2339769be974SMarcel Holtmann 		cp.page = 0x01;
2340ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2341769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2342392599b9SJohan Hedberg 		goto unlock;
2343392599b9SJohan Hedberg 	}
2344392599b9SJohan Hedberg 
2345671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2346127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2347127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2348127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2349127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2350127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2351b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2352b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
235308c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2354b644ba33SJohan Hedberg 				      conn->dev_class);
2355392599b9SJohan Hedberg 
2356127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2357769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2358769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2359769be974SMarcel Holtmann 		hci_conn_put(conn);
2360769be974SMarcel Holtmann 	}
2361769be974SMarcel Holtmann 
2362ccd556feSJohan Hedberg unlock:
2363a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2364a9de9248SMarcel Holtmann }
2365a9de9248SMarcel Holtmann 
23666039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
23676039aa73SGustavo Padovan {
23686039aa73SGustavo Padovan 	BT_DBG("%s", hdev->name);
23696039aa73SGustavo Padovan }
23706039aa73SGustavo Padovan 
23716039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2372807deac2SGustavo Padovan 				       struct sk_buff *skb)
2373a9de9248SMarcel Holtmann {
2374a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2375a9de9248SMarcel Holtmann }
2376a9de9248SMarcel Holtmann 
23776039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2378a9de9248SMarcel Holtmann {
2379a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2380a9de9248SMarcel Holtmann 	__u16 opcode;
2381a9de9248SMarcel Holtmann 
2382a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2383a9de9248SMarcel Holtmann 
2384a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2385a9de9248SMarcel Holtmann 
2386a9de9248SMarcel Holtmann 	switch (opcode) {
2387a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2388a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2389a9de9248SMarcel Holtmann 		break;
2390a9de9248SMarcel Holtmann 
23914d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
23924d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
23934d93483bSAndre Guedes 		break;
23944d93483bSAndre Guedes 
2395a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2396a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2397a9de9248SMarcel Holtmann 		break;
2398a9de9248SMarcel Holtmann 
2399a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2400a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2401a9de9248SMarcel Holtmann 		break;
2402a9de9248SMarcel Holtmann 
2403a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2404a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2405a9de9248SMarcel Holtmann 		break;
2406a9de9248SMarcel Holtmann 
2407e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2408e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2409e4e8e37cSMarcel Holtmann 		break;
2410e4e8e37cSMarcel Holtmann 
2411a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2412a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2413a9de9248SMarcel Holtmann 		break;
2414a9de9248SMarcel Holtmann 
2415e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2416e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2417e4e8e37cSMarcel Holtmann 		break;
2418e4e8e37cSMarcel Holtmann 
2419e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2420e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2421e4e8e37cSMarcel Holtmann 		break;
2422e4e8e37cSMarcel Holtmann 
2423a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2424a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2425a9de9248SMarcel Holtmann 		break;
2426a9de9248SMarcel Holtmann 
2427a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2428a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2429a9de9248SMarcel Holtmann 		break;
2430a9de9248SMarcel Holtmann 
2431a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2432a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2433a9de9248SMarcel Holtmann 		break;
2434a9de9248SMarcel Holtmann 
2435a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2436a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2437a9de9248SMarcel Holtmann 		break;
2438a9de9248SMarcel Holtmann 
2439a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2440a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2441a9de9248SMarcel Holtmann 		break;
2442a9de9248SMarcel Holtmann 
2443a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2444a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2445a9de9248SMarcel Holtmann 		break;
2446a9de9248SMarcel Holtmann 
2447a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2448a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2449a9de9248SMarcel Holtmann 		break;
2450a9de9248SMarcel Holtmann 
2451a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2452a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2453a9de9248SMarcel Holtmann 		break;
2454a9de9248SMarcel Holtmann 
2455a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2456a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2457a9de9248SMarcel Holtmann 		break;
2458a9de9248SMarcel Holtmann 
2459a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2460a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2461a9de9248SMarcel Holtmann 		break;
2462a9de9248SMarcel Holtmann 
2463a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2464a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2465a9de9248SMarcel Holtmann 		break;
2466a9de9248SMarcel Holtmann 
2467333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2468333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2469333140b5SMarcel Holtmann 		break;
2470333140b5SMarcel Holtmann 
2471a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2472a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2473a9de9248SMarcel Holtmann 		break;
2474a9de9248SMarcel Holtmann 
2475a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2476a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2477a9de9248SMarcel Holtmann 		break;
2478a9de9248SMarcel Holtmann 
2479a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2480a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2481a9de9248SMarcel Holtmann 		break;
2482a9de9248SMarcel Holtmann 
2483971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2484971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2485971e3a4bSAndre Guedes 		break;
2486971e3a4bSAndre Guedes 
2487a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2488a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2489a9de9248SMarcel Holtmann 		break;
2490a9de9248SMarcel Holtmann 
2491a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2492a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2493a9de9248SMarcel Holtmann 		break;
2494a9de9248SMarcel Holtmann 
2495350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2496350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2497350ee4cfSAndrei Emeltchenko 		break;
2498350ee4cfSAndrei Emeltchenko 
249923bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
250023bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
250123bb5763SJohan Hedberg 		break;
250223bb5763SJohan Hedberg 
25031e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
25041e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
25051e89cffbSAndrei Emeltchenko 		break;
25061e89cffbSAndrei Emeltchenko 
2507928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2508928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2509928abaa7SAndrei Emeltchenko 		break;
2510928abaa7SAndrei Emeltchenko 
2511903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2512903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2513903e4541SAndrei Emeltchenko 		break;
2514903e4541SAndrei Emeltchenko 
2515b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2516b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2517b0916ea0SJohan Hedberg 		break;
2518b0916ea0SJohan Hedberg 
2519d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2520d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2521d5859e22SJohan Hedberg 		break;
2522d5859e22SJohan Hedberg 
2523d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2524d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2525d5859e22SJohan Hedberg 		break;
2526d5859e22SJohan Hedberg 
2527d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2528d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2529d5859e22SJohan Hedberg 		break;
2530d5859e22SJohan Hedberg 
2531d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2532d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2533d5859e22SJohan Hedberg 		break;
2534d5859e22SJohan Hedberg 
2535980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2536980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2537980e1a53SJohan Hedberg 		break;
2538980e1a53SJohan Hedberg 
2539980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2540980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2541980e1a53SJohan Hedberg 		break;
2542980e1a53SJohan Hedberg 
2543c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2544c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2545c35938b2SSzymon Janc 		break;
2546c35938b2SSzymon Janc 
25476ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
25486ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
25496ed58ec5SVille Tervo 		break;
25506ed58ec5SVille Tervo 
25518fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
25528fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
25538fa19098SJohan Hedberg 		break;
25548fa19098SJohan Hedberg 
2555e36b04c8SJohan Hedberg 	case HCI_OP_LE_SET_EVENT_MASK:
2556e36b04c8SJohan Hedberg 		hci_cc_le_set_event_mask(hdev, skb);
2557e36b04c8SJohan Hedberg 		break;
2558e36b04c8SJohan Hedberg 
2559a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2560a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2561a5c29683SJohan Hedberg 		break;
2562a5c29683SJohan Hedberg 
2563a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2564a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2565a5c29683SJohan Hedberg 		break;
2566a5c29683SJohan Hedberg 
25671143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
25681143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
25691143d458SBrian Gix 		break;
25701143d458SBrian Gix 
25711143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
25721143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
257316cde993SSzymon Janc 		break;
257407f7fa5dSAndre Guedes 
257507f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
257607f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
25771143d458SBrian Gix 		break;
25781143d458SBrian Gix 
2579eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2580eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2581eb9d91f5SAndre Guedes 		break;
2582eb9d91f5SAndre Guedes 
2583a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2584a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2585a7a595f6SVinicius Costa Gomes 		break;
2586a7a595f6SVinicius Costa Gomes 
2587a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2588a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2589a7a595f6SVinicius Costa Gomes 		break;
2590a7a595f6SVinicius Costa Gomes 
2591f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2592f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2593f9b49306SAndre Guedes 		break;
2594f9b49306SAndre Guedes 
259593c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
259693c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
259793c284eeSAndrei Emeltchenko 		break;
259893c284eeSAndrei Emeltchenko 
2599a9de9248SMarcel Holtmann 	default:
26009f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2601a9de9248SMarcel Holtmann 		break;
2602a9de9248SMarcel Holtmann 	}
2603a9de9248SMarcel Holtmann 
26046bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
26056bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
26066bd32326SVille Tervo 
2607a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2608a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2609a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2610c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2611a9de9248SMarcel Holtmann 	}
2612a9de9248SMarcel Holtmann }
2613a9de9248SMarcel Holtmann 
26146039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2615a9de9248SMarcel Holtmann {
2616a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2617a9de9248SMarcel Holtmann 	__u16 opcode;
2618a9de9248SMarcel Holtmann 
2619a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2620a9de9248SMarcel Holtmann 
2621a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2622a9de9248SMarcel Holtmann 
2623a9de9248SMarcel Holtmann 	switch (opcode) {
2624a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2625a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2626a9de9248SMarcel Holtmann 		break;
2627a9de9248SMarcel Holtmann 
2628a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2629a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2630a9de9248SMarcel Holtmann 		break;
2631a9de9248SMarcel Holtmann 
2632a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2633a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2634a9de9248SMarcel Holtmann 		break;
2635a9de9248SMarcel Holtmann 
2636f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2637f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2638f8558555SMarcel Holtmann 		break;
2639f8558555SMarcel Holtmann 
2640f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2641f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2642f8558555SMarcel Holtmann 		break;
2643f8558555SMarcel Holtmann 
2644a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2645a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2646a9de9248SMarcel Holtmann 		break;
2647a9de9248SMarcel Holtmann 
2648769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2649769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2650769be974SMarcel Holtmann 		break;
2651769be974SMarcel Holtmann 
2652769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2653769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2654769be974SMarcel Holtmann 		break;
2655769be974SMarcel Holtmann 
2656a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2657a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2658a9de9248SMarcel Holtmann 		break;
2659a9de9248SMarcel Holtmann 
2660a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2661a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2662a9de9248SMarcel Holtmann 		break;
2663a9de9248SMarcel Holtmann 
2664a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2665a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2666a9de9248SMarcel Holtmann 		break;
2667a9de9248SMarcel Holtmann 
26688962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
266988c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
26708962ee74SJohan Hedberg 		break;
26718962ee74SJohan Hedberg 
2672fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2673fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2674fcd89c09SVille Tervo 		break;
2675fcd89c09SVille Tervo 
2676a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2677a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2678a7a595f6SVinicius Costa Gomes 		break;
2679a7a595f6SVinicius Costa Gomes 
2680a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2681a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2682a02226d6SAndrei Emeltchenko 		break;
2683a02226d6SAndrei Emeltchenko 
26840b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
26850b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
26860b26ab9dSAndrei Emeltchenko 		break;
26870b26ab9dSAndrei Emeltchenko 
26885ce66b59SAndrei Emeltchenko 	case HCI_OP_CREATE_LOGICAL_LINK:
26895ce66b59SAndrei Emeltchenko 		hci_cs_create_logical_link(hdev, ev->status);
26905ce66b59SAndrei Emeltchenko 		break;
26915ce66b59SAndrei Emeltchenko 
2692a9de9248SMarcel Holtmann 	default:
26939f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2694a9de9248SMarcel Holtmann 		break;
2695a9de9248SMarcel Holtmann 	}
2696a9de9248SMarcel Holtmann 
26976bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
26986bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
26996bd32326SVille Tervo 
270010572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2701a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2702a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2703c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2704a9de9248SMarcel Holtmann 	}
2705a9de9248SMarcel Holtmann }
2706a9de9248SMarcel Holtmann 
27076039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2708a9de9248SMarcel Holtmann {
2709a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2710a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2711a9de9248SMarcel Holtmann 
27129f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2713a9de9248SMarcel Holtmann 
2714a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2715a9de9248SMarcel Holtmann 
2716a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2717a9de9248SMarcel Holtmann 	if (conn) {
2718a9de9248SMarcel Holtmann 		if (!ev->status) {
2719a9de9248SMarcel Holtmann 			if (ev->role)
2720a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2721a9de9248SMarcel Holtmann 			else
2722a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2723a9de9248SMarcel Holtmann 		}
2724a9de9248SMarcel Holtmann 
272551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2726a9de9248SMarcel Holtmann 
2727a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2728a9de9248SMarcel Holtmann 	}
2729a9de9248SMarcel Holtmann 
2730a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2731a9de9248SMarcel Holtmann }
2732a9de9248SMarcel Holtmann 
27336039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
27341da177e4SLinus Torvalds {
2735a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
27361da177e4SLinus Torvalds 	int i;
27371da177e4SLinus Torvalds 
273832ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
273932ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
274032ac5b9bSAndrei Emeltchenko 		return;
274132ac5b9bSAndrei Emeltchenko 	}
274232ac5b9bSAndrei Emeltchenko 
2743c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2744c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
27451da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
27461da177e4SLinus Torvalds 		return;
27471da177e4SLinus Torvalds 	}
27481da177e4SLinus Torvalds 
2749c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2750c5993de8SAndrei Emeltchenko 
2751613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2752613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
27531da177e4SLinus Torvalds 		struct hci_conn *conn;
27541da177e4SLinus Torvalds 		__u16  handle, count;
27551da177e4SLinus Torvalds 
2756613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2757613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
27581da177e4SLinus Torvalds 
27591da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2760f4280918SAndrei Emeltchenko 		if (!conn)
2761f4280918SAndrei Emeltchenko 			continue;
2762f4280918SAndrei Emeltchenko 
27631da177e4SLinus Torvalds 		conn->sent -= count;
27641da177e4SLinus Torvalds 
2765f4280918SAndrei Emeltchenko 		switch (conn->type) {
2766f4280918SAndrei Emeltchenko 		case ACL_LINK:
276770f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
276870f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
27691da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2770f4280918SAndrei Emeltchenko 			break;
2771f4280918SAndrei Emeltchenko 
2772f4280918SAndrei Emeltchenko 		case LE_LINK:
27736ed58ec5SVille Tervo 			if (hdev->le_pkts) {
27746ed58ec5SVille Tervo 				hdev->le_cnt += count;
27756ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
27766ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
27776ed58ec5SVille Tervo 			} else {
27786ed58ec5SVille Tervo 				hdev->acl_cnt += count;
27796ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
27806ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
27816ed58ec5SVille Tervo 			}
2782f4280918SAndrei Emeltchenko 			break;
2783f4280918SAndrei Emeltchenko 
2784f4280918SAndrei Emeltchenko 		case SCO_LINK:
278570f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
278670f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
27875b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2788f4280918SAndrei Emeltchenko 			break;
2789f4280918SAndrei Emeltchenko 
2790f4280918SAndrei Emeltchenko 		default:
2791f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2792f4280918SAndrei Emeltchenko 			break;
27931da177e4SLinus Torvalds 		}
27941da177e4SLinus Torvalds 	}
2795a9de9248SMarcel Holtmann 
27963eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
27971da177e4SLinus Torvalds }
27981da177e4SLinus Torvalds 
279976ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
280076ef7cf7SAndrei Emeltchenko 						 __u16 handle)
280176ef7cf7SAndrei Emeltchenko {
280276ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
280376ef7cf7SAndrei Emeltchenko 
280476ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
280576ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
280676ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
280776ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
280876ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
280976ef7cf7SAndrei Emeltchenko 		if (chan)
281076ef7cf7SAndrei Emeltchenko 			return chan->conn;
281176ef7cf7SAndrei Emeltchenko 		break;
281276ef7cf7SAndrei Emeltchenko 	default:
281376ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
281476ef7cf7SAndrei Emeltchenko 		break;
281576ef7cf7SAndrei Emeltchenko 	}
281676ef7cf7SAndrei Emeltchenko 
281776ef7cf7SAndrei Emeltchenko 	return NULL;
281876ef7cf7SAndrei Emeltchenko }
281976ef7cf7SAndrei Emeltchenko 
28206039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
282125e89e99SAndrei Emeltchenko {
282225e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
282325e89e99SAndrei Emeltchenko 	int i;
282425e89e99SAndrei Emeltchenko 
282525e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
282625e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
282725e89e99SAndrei Emeltchenko 		return;
282825e89e99SAndrei Emeltchenko 	}
282925e89e99SAndrei Emeltchenko 
283025e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
283125e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
283225e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
283325e89e99SAndrei Emeltchenko 		return;
283425e89e99SAndrei Emeltchenko 	}
283525e89e99SAndrei Emeltchenko 
283625e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
283725e89e99SAndrei Emeltchenko 	       ev->num_hndl);
283825e89e99SAndrei Emeltchenko 
283925e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
284025e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
284176ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
284225e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
284325e89e99SAndrei Emeltchenko 
284425e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
284525e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
284625e89e99SAndrei Emeltchenko 
284776ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
284825e89e99SAndrei Emeltchenko 		if (!conn)
284925e89e99SAndrei Emeltchenko 			continue;
285025e89e99SAndrei Emeltchenko 
285125e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
285225e89e99SAndrei Emeltchenko 
285325e89e99SAndrei Emeltchenko 		switch (conn->type) {
285425e89e99SAndrei Emeltchenko 		case ACL_LINK:
2855bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
285625e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
285725e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
285825e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
285925e89e99SAndrei Emeltchenko 			break;
286025e89e99SAndrei Emeltchenko 
286125e89e99SAndrei Emeltchenko 		default:
286225e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
286325e89e99SAndrei Emeltchenko 			break;
286425e89e99SAndrei Emeltchenko 		}
286525e89e99SAndrei Emeltchenko 	}
286625e89e99SAndrei Emeltchenko 
286725e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
286825e89e99SAndrei Emeltchenko }
286925e89e99SAndrei Emeltchenko 
28706039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
28711da177e4SLinus Torvalds {
2872a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
287304837f64SMarcel Holtmann 	struct hci_conn *conn;
28741da177e4SLinus Torvalds 
28759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
28761da177e4SLinus Torvalds 
28771da177e4SLinus Torvalds 	hci_dev_lock(hdev);
28781da177e4SLinus Torvalds 
287904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
288004837f64SMarcel Holtmann 	if (conn) {
288104837f64SMarcel Holtmann 		conn->mode = ev->mode;
288204837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
288304837f64SMarcel Holtmann 
28848fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
28858fc9ced3SGustavo Padovan 					&conn->flags)) {
288604837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
288758a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
288804837f64SMarcel Holtmann 			else
288958a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
289004837f64SMarcel Holtmann 		}
2891e73439d8SMarcel Holtmann 
289251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2893e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
289404837f64SMarcel Holtmann 	}
289504837f64SMarcel Holtmann 
289604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
289704837f64SMarcel Holtmann }
289804837f64SMarcel Holtmann 
28996039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29001da177e4SLinus Torvalds {
2901052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2902052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2903052b30b0SMarcel Holtmann 
2904a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2905052b30b0SMarcel Holtmann 
2906052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2907052b30b0SMarcel Holtmann 
2908052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2909b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2910b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2911b6f98044SWaldemar Rymarkiewicz 
2912b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2913052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2914052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2915052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2916052b30b0SMarcel Holtmann 	}
2917052b30b0SMarcel Holtmann 
2918a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
291903b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
292003b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2921a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2922a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2923a770bb5aSWaldemar Rymarkiewicz 
2924a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2925a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2926a770bb5aSWaldemar Rymarkiewicz 		else
2927a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2928a770bb5aSWaldemar Rymarkiewicz 
2929744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2930a770bb5aSWaldemar Rymarkiewicz 	}
2931980e1a53SJohan Hedberg 
2932b6f98044SWaldemar Rymarkiewicz unlock:
2933052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
29341da177e4SLinus Torvalds }
29351da177e4SLinus Torvalds 
29366039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29371da177e4SLinus Torvalds {
293855ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
293955ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
294055ed8ca1SJohan Hedberg 	struct hci_conn *conn;
294155ed8ca1SJohan Hedberg 	struct link_key *key;
294255ed8ca1SJohan Hedberg 
2943a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
294455ed8ca1SJohan Hedberg 
2945a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
294655ed8ca1SJohan Hedberg 		return;
294755ed8ca1SJohan Hedberg 
294855ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
294955ed8ca1SJohan Hedberg 
295055ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
295155ed8ca1SJohan Hedberg 	if (!key) {
29526ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
29536ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
295455ed8ca1SJohan Hedberg 		goto not_found;
295555ed8ca1SJohan Hedberg 	}
295655ed8ca1SJohan Hedberg 
29576ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
29586ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
295955ed8ca1SJohan Hedberg 
2960a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2961b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
296255ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
296355ed8ca1SJohan Hedberg 		goto not_found;
296455ed8ca1SJohan Hedberg 	}
296555ed8ca1SJohan Hedberg 
296655ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
296760b83f57SWaldemar Rymarkiewicz 	if (conn) {
296860b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2969807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
297055ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
297155ed8ca1SJohan Hedberg 			goto not_found;
297255ed8ca1SJohan Hedberg 		}
297355ed8ca1SJohan Hedberg 
297460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
297560b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
29768fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
29778fc9ced3SGustavo Padovan 			       hdev->name);
297860b83f57SWaldemar Rymarkiewicz 			goto not_found;
297960b83f57SWaldemar Rymarkiewicz 		}
298060b83f57SWaldemar Rymarkiewicz 
298160b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
298260b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
298360b83f57SWaldemar Rymarkiewicz 	}
298460b83f57SWaldemar Rymarkiewicz 
298555ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
29869b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
298755ed8ca1SJohan Hedberg 
298855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
298955ed8ca1SJohan Hedberg 
299055ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
299155ed8ca1SJohan Hedberg 
299255ed8ca1SJohan Hedberg 	return;
299355ed8ca1SJohan Hedberg 
299455ed8ca1SJohan Hedberg not_found:
299555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
299655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
29971da177e4SLinus Torvalds }
29981da177e4SLinus Torvalds 
29996039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
30001da177e4SLinus Torvalds {
3001052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
3002052b30b0SMarcel Holtmann 	struct hci_conn *conn;
300355ed8ca1SJohan Hedberg 	u8 pin_len = 0;
3004052b30b0SMarcel Holtmann 
3005a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3006052b30b0SMarcel Holtmann 
3007052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3008052b30b0SMarcel Holtmann 
3009052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3010052b30b0SMarcel Holtmann 	if (conn) {
3011052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3012052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3013980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
301413d39315SWaldemar Rymarkiewicz 
301513d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
301613d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
301713d39315SWaldemar Rymarkiewicz 
3018052b30b0SMarcel Holtmann 		hci_conn_put(conn);
3019052b30b0SMarcel Holtmann 	}
3020052b30b0SMarcel Holtmann 
3021a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
3022d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
302355ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
302455ed8ca1SJohan Hedberg 
3025052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
30261da177e4SLinus Torvalds }
30271da177e4SLinus Torvalds 
30286039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
302904837f64SMarcel Holtmann {
3030a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
303104837f64SMarcel Holtmann 	struct hci_conn *conn;
303204837f64SMarcel Holtmann 
30339f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
303404837f64SMarcel Holtmann 
303504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
303604837f64SMarcel Holtmann 
303704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30381da177e4SLinus Torvalds 	if (conn && !ev->status) {
30391da177e4SLinus Torvalds 		struct inquiry_entry *ie;
30401da177e4SLinus Torvalds 
3041cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3042cc11b9c1SAndrei Emeltchenko 		if (ie) {
30431da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
30441da177e4SLinus Torvalds 			ie->timestamp = jiffies;
30451da177e4SLinus Torvalds 		}
30461da177e4SLinus Torvalds 	}
30471da177e4SLinus Torvalds 
30481da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
30491da177e4SLinus Torvalds }
30501da177e4SLinus Torvalds 
30516039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3052a8746417SMarcel Holtmann {
3053a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3054a8746417SMarcel Holtmann 	struct hci_conn *conn;
3055a8746417SMarcel Holtmann 
30569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3057a8746417SMarcel Holtmann 
3058a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
3059a8746417SMarcel Holtmann 
3060a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3061a8746417SMarcel Holtmann 	if (conn && !ev->status)
3062a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3063a8746417SMarcel Holtmann 
3064a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
3065a8746417SMarcel Holtmann }
3066a8746417SMarcel Holtmann 
30676039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
306885a1e930SMarcel Holtmann {
3069a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
307085a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
307185a1e930SMarcel Holtmann 
307285a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
307385a1e930SMarcel Holtmann 
307485a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
307585a1e930SMarcel Holtmann 
3076cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3077cc11b9c1SAndrei Emeltchenko 	if (ie) {
307885a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
307985a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
308085a1e930SMarcel Holtmann 	}
308185a1e930SMarcel Holtmann 
308285a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
308385a1e930SMarcel Holtmann }
308485a1e930SMarcel Holtmann 
30856039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3086807deac2SGustavo Padovan 					     struct sk_buff *skb)
3087a9de9248SMarcel Holtmann {
3088a9de9248SMarcel Holtmann 	struct inquiry_data data;
3089a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
3090388fc8faSJohan Hedberg 	bool name_known, ssp;
3091a9de9248SMarcel Holtmann 
3092a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3093a9de9248SMarcel Holtmann 
3094a9de9248SMarcel Holtmann 	if (!num_rsp)
3095a9de9248SMarcel Holtmann 		return;
3096a9de9248SMarcel Holtmann 
30971519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30981519cc17SAndre Guedes 		return;
30991519cc17SAndre Guedes 
3100a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3101a9de9248SMarcel Holtmann 
3102a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3103138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3104138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3105a9de9248SMarcel Holtmann 
3106e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3107a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3108a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3109a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3110a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3111a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3112a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3113a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
311441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
31153175405bSJohan Hedberg 
31163175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3117388fc8faSJohan Hedberg 							      false, &ssp);
311848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3119e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3120388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3121a9de9248SMarcel Holtmann 		}
3122a9de9248SMarcel Holtmann 	} else {
3123a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3124a9de9248SMarcel Holtmann 
3125e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3126a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3127a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3128a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3129a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3130a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3131a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3132a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
313341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
31343175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3135388fc8faSJohan Hedberg 							      false, &ssp);
313648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3137e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3138388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3139a9de9248SMarcel Holtmann 		}
3140a9de9248SMarcel Holtmann 	}
3141a9de9248SMarcel Holtmann 
3142a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3143a9de9248SMarcel Holtmann }
3144a9de9248SMarcel Holtmann 
31456039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3146807deac2SGustavo Padovan 					struct sk_buff *skb)
3147a9de9248SMarcel Holtmann {
314841a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
314941a96212SMarcel Holtmann 	struct hci_conn *conn;
315041a96212SMarcel Holtmann 
3151a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
315241a96212SMarcel Holtmann 
315341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
315441a96212SMarcel Holtmann 
315541a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3156ccd556feSJohan Hedberg 	if (!conn)
3157ccd556feSJohan Hedberg 		goto unlock;
3158ccd556feSJohan Hedberg 
3159769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
316041a96212SMarcel Holtmann 		struct inquiry_entry *ie;
316141a96212SMarcel Holtmann 
3162cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3163cc11b9c1SAndrei Emeltchenko 		if (ie)
316402b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
316541a96212SMarcel Holtmann 
316602b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
316758a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
316841a96212SMarcel Holtmann 	}
316941a96212SMarcel Holtmann 
3170ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3171ccd556feSJohan Hedberg 		goto unlock;
3172ccd556feSJohan Hedberg 
3173671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3174127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3175127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3176127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3177127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3178127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3179b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3180b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
318108c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
3182b644ba33SJohan Hedberg 				      conn->dev_class);
3183392599b9SJohan Hedberg 
3184127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3185769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3186769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
3187769be974SMarcel Holtmann 		hci_conn_put(conn);
3188769be974SMarcel Holtmann 	}
3189769be974SMarcel Holtmann 
3190ccd556feSJohan Hedberg unlock:
319141a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3192a9de9248SMarcel Holtmann }
3193a9de9248SMarcel Holtmann 
31946039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3195807deac2SGustavo Padovan 				       struct sk_buff *skb)
3196a9de9248SMarcel Holtmann {
3197b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3198b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3199b6a0dc82SMarcel Holtmann 
32009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3201b6a0dc82SMarcel Holtmann 
3202b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3203b6a0dc82SMarcel Holtmann 
3204b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
32059dc0a3afSMarcel Holtmann 	if (!conn) {
32069dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
32079dc0a3afSMarcel Holtmann 			goto unlock;
32089dc0a3afSMarcel Holtmann 
32099dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3210b6a0dc82SMarcel Holtmann 		if (!conn)
3211b6a0dc82SMarcel Holtmann 			goto unlock;
3212b6a0dc82SMarcel Holtmann 
32139dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
32149dc0a3afSMarcel Holtmann 	}
32159dc0a3afSMarcel Holtmann 
3216732547f9SMarcel Holtmann 	switch (ev->status) {
3217732547f9SMarcel Holtmann 	case 0x00:
3218732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3219732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3220732547f9SMarcel Holtmann 
32219eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
3222732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3223732547f9SMarcel Holtmann 		break;
3224732547f9SMarcel Holtmann 
3225705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3226732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
32271038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3228732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
3229732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
3230efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3231efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
3232efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
3233efc7688bSMarcel Holtmann 			goto unlock;
3234efc7688bSMarcel Holtmann 		}
3235732547f9SMarcel Holtmann 		/* fall through */
3236efc7688bSMarcel Holtmann 
3237732547f9SMarcel Holtmann 	default:
3238b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3239732547f9SMarcel Holtmann 		break;
3240732547f9SMarcel Holtmann 	}
3241b6a0dc82SMarcel Holtmann 
3242b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3243b6a0dc82SMarcel Holtmann 	if (ev->status)
3244b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3245b6a0dc82SMarcel Holtmann 
3246b6a0dc82SMarcel Holtmann unlock:
3247b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3248a9de9248SMarcel Holtmann }
3249a9de9248SMarcel Holtmann 
32506039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
3251a9de9248SMarcel Holtmann {
3252a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3253a9de9248SMarcel Holtmann }
3254a9de9248SMarcel Holtmann 
32556039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
325604837f64SMarcel Holtmann {
3257a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
325804837f64SMarcel Holtmann 
32599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
326004837f64SMarcel Holtmann }
326104837f64SMarcel Holtmann 
32626039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3263807deac2SGustavo Padovan 					    struct sk_buff *skb)
3264a9de9248SMarcel Holtmann {
3265a9de9248SMarcel Holtmann 	struct inquiry_data data;
3266a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3267a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
32689d939d94SVishal Agarwal 	size_t eir_len;
3269a9de9248SMarcel Holtmann 
3270a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3271a9de9248SMarcel Holtmann 
3272a9de9248SMarcel Holtmann 	if (!num_rsp)
3273a9de9248SMarcel Holtmann 		return;
3274a9de9248SMarcel Holtmann 
32751519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
32761519cc17SAndre Guedes 		return;
32771519cc17SAndre Guedes 
3278a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3279a9de9248SMarcel Holtmann 
3280e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3281388fc8faSJohan Hedberg 		bool name_known, ssp;
3282561aafbcSJohan Hedberg 
3283a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3284a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3285a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3286a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3287a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3288a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3289a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
329041a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3291561aafbcSJohan Hedberg 
3292a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
32934ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
32944ddb1930SJohan Hedberg 						       sizeof(info->data),
32954ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3296561aafbcSJohan Hedberg 		else
3297561aafbcSJohan Hedberg 			name_known = true;
3298561aafbcSJohan Hedberg 
3299388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3300388fc8faSJohan Hedberg 						      &ssp);
33019d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
330248264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
330304124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
33049d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3305a9de9248SMarcel Holtmann 	}
3306a9de9248SMarcel Holtmann 
3307a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3308a9de9248SMarcel Holtmann }
3309a9de9248SMarcel Holtmann 
33101c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
33111c2e0041SJohan Hedberg 					 struct sk_buff *skb)
33121c2e0041SJohan Hedberg {
33131c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
33141c2e0041SJohan Hedberg 	struct hci_conn *conn;
33151c2e0041SJohan Hedberg 
33169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
33171c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
33181c2e0041SJohan Hedberg 
33191c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
33201c2e0041SJohan Hedberg 
33211c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
33221c2e0041SJohan Hedberg 	if (!conn)
33231c2e0041SJohan Hedberg 		goto unlock;
33241c2e0041SJohan Hedberg 
33251c2e0041SJohan Hedberg 	if (!ev->status)
33261c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
33271c2e0041SJohan Hedberg 
33281c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
33291c2e0041SJohan Hedberg 
33301c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
33311c2e0041SJohan Hedberg 		hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
33321c2e0041SJohan Hedberg 		hci_conn_put(conn);
33331c2e0041SJohan Hedberg 		goto unlock;
33341c2e0041SJohan Hedberg 	}
33351c2e0041SJohan Hedberg 
33361c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
33371c2e0041SJohan Hedberg 		if (!ev->status)
33381c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
33391c2e0041SJohan Hedberg 
33401c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
33411c2e0041SJohan Hedberg 		hci_conn_put(conn);
33421c2e0041SJohan Hedberg 	} else {
33431c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
33441c2e0041SJohan Hedberg 
33451c2e0041SJohan Hedberg 		hci_conn_hold(conn);
33461c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
33471c2e0041SJohan Hedberg 		hci_conn_put(conn);
33481c2e0041SJohan Hedberg 	}
33491c2e0041SJohan Hedberg 
33501c2e0041SJohan Hedberg unlock:
33511c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
33521c2e0041SJohan Hedberg }
33531c2e0041SJohan Hedberg 
33546039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
335517fa4b9dSJohan Hedberg {
335617fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
335717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
335817fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
335917fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
336017fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
336117fa4b9dSJohan Hedberg 			return 0x02;
336217fa4b9dSJohan Hedberg 		else
336317fa4b9dSJohan Hedberg 			return 0x03;
336417fa4b9dSJohan Hedberg 	}
336517fa4b9dSJohan Hedberg 
336617fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
336717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
336858797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
336917fa4b9dSJohan Hedberg 
337017fa4b9dSJohan Hedberg 	return conn->auth_type;
337117fa4b9dSJohan Hedberg }
337217fa4b9dSJohan Hedberg 
33736039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
33740493684eSMarcel Holtmann {
33750493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
33760493684eSMarcel Holtmann 	struct hci_conn *conn;
33770493684eSMarcel Holtmann 
33780493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
33790493684eSMarcel Holtmann 
33800493684eSMarcel Holtmann 	hci_dev_lock(hdev);
33810493684eSMarcel Holtmann 
33820493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
338303b555e1SJohan Hedberg 	if (!conn)
338403b555e1SJohan Hedberg 		goto unlock;
338503b555e1SJohan Hedberg 
33860493684eSMarcel Holtmann 	hci_conn_hold(conn);
33870493684eSMarcel Holtmann 
3388a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
338903b555e1SJohan Hedberg 		goto unlock;
339003b555e1SJohan Hedberg 
3391a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
339203b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
339317fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
339417fa4b9dSJohan Hedberg 
339517fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
33967a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
33977a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
33987a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
33997a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
34007cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
34017cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
340217fa4b9dSJohan Hedberg 
34038fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
34048fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3405ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3406ce85ee13SSzymon Janc 		else
3407ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3408ce85ee13SSzymon Janc 
340917fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
341017fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
341103b555e1SJohan Hedberg 	} else {
341203b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
341303b555e1SJohan Hedberg 
341403b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
34159f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
341603b555e1SJohan Hedberg 
341703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
341803b555e1SJohan Hedberg 			     sizeof(cp), &cp);
341903b555e1SJohan Hedberg 	}
342003b555e1SJohan Hedberg 
342103b555e1SJohan Hedberg unlock:
342203b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
342303b555e1SJohan Hedberg }
342403b555e1SJohan Hedberg 
34256039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
342603b555e1SJohan Hedberg {
342703b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
342803b555e1SJohan Hedberg 	struct hci_conn *conn;
342903b555e1SJohan Hedberg 
343003b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
343103b555e1SJohan Hedberg 
343203b555e1SJohan Hedberg 	hci_dev_lock(hdev);
343303b555e1SJohan Hedberg 
343403b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
343503b555e1SJohan Hedberg 	if (!conn)
343603b555e1SJohan Hedberg 		goto unlock;
343703b555e1SJohan Hedberg 
343803b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
343903b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
344058a681efSJohan Hedberg 	if (ev->oob_data)
344158a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
344203b555e1SJohan Hedberg 
344303b555e1SJohan Hedberg unlock:
34440493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
34450493684eSMarcel Holtmann }
34460493684eSMarcel Holtmann 
34476039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3448a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3449a5c29683SJohan Hedberg {
3450a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
345155bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
34527a828908SJohan Hedberg 	struct hci_conn *conn;
3453a5c29683SJohan Hedberg 
3454a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3455a5c29683SJohan Hedberg 
3456a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3457a5c29683SJohan Hedberg 
3458a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
34597a828908SJohan Hedberg 		goto unlock;
34607a828908SJohan Hedberg 
34617a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
34627a828908SJohan Hedberg 	if (!conn)
34637a828908SJohan Hedberg 		goto unlock;
34647a828908SJohan Hedberg 
34657a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
34667a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
34677a828908SJohan Hedberg 
34687a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
34697a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
34707a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
34717a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
34727a828908SJohan Hedberg 	 * bit set. */
34737a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
34747a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
34757a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
34767a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
34777a828908SJohan Hedberg 		goto unlock;
34787a828908SJohan Hedberg 	}
34797a828908SJohan Hedberg 
34807a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
34817a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
34827a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
348355bc1a37SJohan Hedberg 
348455bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
348555bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
348655bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
348751a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
348855bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
348955bc1a37SJohan Hedberg 			confirm_hint = 1;
349055bc1a37SJohan Hedberg 			goto confirm;
349155bc1a37SJohan Hedberg 		}
349255bc1a37SJohan Hedberg 
34939f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
34949f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
34959f61656aSJohan Hedberg 
34969f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
34979f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
34989f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
34999f61656aSJohan Hedberg 			goto unlock;
35009f61656aSJohan Hedberg 		}
35019f61656aSJohan Hedberg 
35027a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
35037a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
35047a828908SJohan Hedberg 		goto unlock;
35057a828908SJohan Hedberg 	}
35067a828908SJohan Hedberg 
350755bc1a37SJohan Hedberg confirm:
3508272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
350955bc1a37SJohan Hedberg 				  confirm_hint);
3510a5c29683SJohan Hedberg 
35117a828908SJohan Hedberg unlock:
3512a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3513a5c29683SJohan Hedberg }
3514a5c29683SJohan Hedberg 
35156039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
35161143d458SBrian Gix 					 struct sk_buff *skb)
35171143d458SBrian Gix {
35181143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
35191143d458SBrian Gix 
35201143d458SBrian Gix 	BT_DBG("%s", hdev->name);
35211143d458SBrian Gix 
3522a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3523272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
35241143d458SBrian Gix }
35251143d458SBrian Gix 
352692a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
352792a25256SJohan Hedberg 					struct sk_buff *skb)
352892a25256SJohan Hedberg {
352992a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
353092a25256SJohan Hedberg 	struct hci_conn *conn;
353192a25256SJohan Hedberg 
353292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
353392a25256SJohan Hedberg 
353492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
353592a25256SJohan Hedberg 	if (!conn)
353692a25256SJohan Hedberg 		return;
353792a25256SJohan Hedberg 
353892a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
353992a25256SJohan Hedberg 	conn->passkey_entered = 0;
354092a25256SJohan Hedberg 
354192a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
354292a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
354392a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
354492a25256SJohan Hedberg 					 conn->passkey_entered);
354592a25256SJohan Hedberg }
354692a25256SJohan Hedberg 
354792a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
354892a25256SJohan Hedberg {
354992a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
355092a25256SJohan Hedberg 	struct hci_conn *conn;
355192a25256SJohan Hedberg 
355292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
355392a25256SJohan Hedberg 
355492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
355592a25256SJohan Hedberg 	if (!conn)
355692a25256SJohan Hedberg 		return;
355792a25256SJohan Hedberg 
355892a25256SJohan Hedberg 	switch (ev->type) {
355992a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
356092a25256SJohan Hedberg 		conn->passkey_entered = 0;
356192a25256SJohan Hedberg 		return;
356292a25256SJohan Hedberg 
356392a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
356492a25256SJohan Hedberg 		conn->passkey_entered++;
356592a25256SJohan Hedberg 		break;
356692a25256SJohan Hedberg 
356792a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
356892a25256SJohan Hedberg 		conn->passkey_entered--;
356992a25256SJohan Hedberg 		break;
357092a25256SJohan Hedberg 
357192a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
357292a25256SJohan Hedberg 		conn->passkey_entered = 0;
357392a25256SJohan Hedberg 		break;
357492a25256SJohan Hedberg 
357592a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
357692a25256SJohan Hedberg 		return;
357792a25256SJohan Hedberg 	}
357892a25256SJohan Hedberg 
357992a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
358092a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
358192a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
358292a25256SJohan Hedberg 					 conn->passkey_entered);
358392a25256SJohan Hedberg }
358492a25256SJohan Hedberg 
35856039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3586807deac2SGustavo Padovan 					 struct sk_buff *skb)
35870493684eSMarcel Holtmann {
35880493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
35890493684eSMarcel Holtmann 	struct hci_conn *conn;
35900493684eSMarcel Holtmann 
35910493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
35920493684eSMarcel Holtmann 
35930493684eSMarcel Holtmann 	hci_dev_lock(hdev);
35940493684eSMarcel Holtmann 
35950493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
35962a611692SJohan Hedberg 	if (!conn)
35972a611692SJohan Hedberg 		goto unlock;
35982a611692SJohan Hedberg 
35992a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
36002a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
36012a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
36022a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
36032a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3604fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3605bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3606bab73cb6SJohan Hedberg 				 ev->status);
36072a611692SJohan Hedberg 
36080493684eSMarcel Holtmann 	hci_conn_put(conn);
36090493684eSMarcel Holtmann 
36102a611692SJohan Hedberg unlock:
36110493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
36120493684eSMarcel Holtmann }
36130493684eSMarcel Holtmann 
36146039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3615807deac2SGustavo Padovan 					 struct sk_buff *skb)
361641a96212SMarcel Holtmann {
361741a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
361841a96212SMarcel Holtmann 	struct inquiry_entry *ie;
361941a96212SMarcel Holtmann 
362041a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
362141a96212SMarcel Holtmann 
362241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
362341a96212SMarcel Holtmann 
3624cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3625cc11b9c1SAndrei Emeltchenko 	if (ie)
362602b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
362741a96212SMarcel Holtmann 
362841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
362941a96212SMarcel Holtmann }
363041a96212SMarcel Holtmann 
36316039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
36322763eda6SSzymon Janc 					    struct sk_buff *skb)
36332763eda6SSzymon Janc {
36342763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
36352763eda6SSzymon Janc 	struct oob_data *data;
36362763eda6SSzymon Janc 
36372763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
36382763eda6SSzymon Janc 
36392763eda6SSzymon Janc 	hci_dev_lock(hdev);
36402763eda6SSzymon Janc 
3641a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3642e1ba1f15SSzymon Janc 		goto unlock;
3643e1ba1f15SSzymon Janc 
36442763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
36452763eda6SSzymon Janc 	if (data) {
36462763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
36472763eda6SSzymon Janc 
36482763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
36492763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
36502763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
36512763eda6SSzymon Janc 
36522763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
36532763eda6SSzymon Janc 			     &cp);
36542763eda6SSzymon Janc 	} else {
36552763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
36562763eda6SSzymon Janc 
36572763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
36582763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
36592763eda6SSzymon Janc 			     &cp);
36602763eda6SSzymon Janc 	}
36612763eda6SSzymon Janc 
3662e1ba1f15SSzymon Janc unlock:
36632763eda6SSzymon Janc 	hci_dev_unlock(hdev);
36642763eda6SSzymon Janc }
36652763eda6SSzymon Janc 
3666d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3667d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3668d5e91192SAndrei Emeltchenko {
3669d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3670d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3671d5e91192SAndrei Emeltchenko 
3672d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3673d5e91192SAndrei Emeltchenko 	       ev->status);
3674d5e91192SAndrei Emeltchenko 
3675d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3676d5e91192SAndrei Emeltchenko 
3677d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3678d5e91192SAndrei Emeltchenko 	if (!hcon) {
3679d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3680d5e91192SAndrei Emeltchenko 		return;
3681d5e91192SAndrei Emeltchenko 	}
3682d5e91192SAndrei Emeltchenko 
3683d5e91192SAndrei Emeltchenko 	if (ev->status) {
3684d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3685d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3686d5e91192SAndrei Emeltchenko 		return;
3687d5e91192SAndrei Emeltchenko 	}
3688d5e91192SAndrei Emeltchenko 
3689d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3690d5e91192SAndrei Emeltchenko 
3691d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3692d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3693d5e91192SAndrei Emeltchenko 
3694d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3695d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3696d5e91192SAndrei Emeltchenko 	hci_conn_put(hcon);
3697d5e91192SAndrei Emeltchenko 
3698d5e91192SAndrei Emeltchenko 	hci_conn_hold_device(hcon);
3699d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3700d5e91192SAndrei Emeltchenko 
3701cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
3702cf70ff22SAndrei Emeltchenko 
3703d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3704d5e91192SAndrei Emeltchenko }
3705d5e91192SAndrei Emeltchenko 
370627695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
370727695fb4SAndrei Emeltchenko {
370827695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
370927695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
371027695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
371127695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
371227695fb4SAndrei Emeltchenko 
371327695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
371427695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
371527695fb4SAndrei Emeltchenko 	       ev->status);
371627695fb4SAndrei Emeltchenko 
371727695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
371827695fb4SAndrei Emeltchenko 	if (!hcon)
371927695fb4SAndrei Emeltchenko 		return;
372027695fb4SAndrei Emeltchenko 
372127695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
372227695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
372327695fb4SAndrei Emeltchenko 	if (!hchan)
372427695fb4SAndrei Emeltchenko 		return;
372527695fb4SAndrei Emeltchenko 
372627695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
372727695fb4SAndrei Emeltchenko 
372827695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
372927695fb4SAndrei Emeltchenko 
373027695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
373127695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
373227695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
373327695fb4SAndrei Emeltchenko 
373427695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
373527695fb4SAndrei Emeltchenko 
373627695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
373727695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
373827695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
373927695fb4SAndrei Emeltchenko 
374027695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
374127695fb4SAndrei Emeltchenko 	}
374227695fb4SAndrei Emeltchenko }
374327695fb4SAndrei Emeltchenko 
3744606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3745606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3746606e2a10SAndrei Emeltchenko {
3747606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3748606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3749606e2a10SAndrei Emeltchenko 
3750606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3751606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3752606e2a10SAndrei Emeltchenko 
3753606e2a10SAndrei Emeltchenko 	if (ev->status)
3754606e2a10SAndrei Emeltchenko 		return;
3755606e2a10SAndrei Emeltchenko 
3756606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3757606e2a10SAndrei Emeltchenko 
3758606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3759606e2a10SAndrei Emeltchenko 	if (!hchan)
3760606e2a10SAndrei Emeltchenko 		goto unlock;
3761606e2a10SAndrei Emeltchenko 
3762606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3763606e2a10SAndrei Emeltchenko 
3764606e2a10SAndrei Emeltchenko unlock:
3765606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3766606e2a10SAndrei Emeltchenko }
3767606e2a10SAndrei Emeltchenko 
37689eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
37699eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
37709eef6b3aSAndrei Emeltchenko {
37719eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
37729eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
37739eef6b3aSAndrei Emeltchenko 
37749eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
37759eef6b3aSAndrei Emeltchenko 
37769eef6b3aSAndrei Emeltchenko 	if (ev->status)
37779eef6b3aSAndrei Emeltchenko 		return;
37789eef6b3aSAndrei Emeltchenko 
37799eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
37809eef6b3aSAndrei Emeltchenko 
37819eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
37829eef6b3aSAndrei Emeltchenko 	if (hcon) {
37839eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
37849eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
37859eef6b3aSAndrei Emeltchenko 	}
37869eef6b3aSAndrei Emeltchenko 
37879eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
37889eef6b3aSAndrei Emeltchenko }
37899eef6b3aSAndrei Emeltchenko 
37906039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3791fcd89c09SVille Tervo {
3792fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3793fcd89c09SVille Tervo 	struct hci_conn *conn;
3794fcd89c09SVille Tervo 
37959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3796fcd89c09SVille Tervo 
3797fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3798fcd89c09SVille Tervo 
37994f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3800b62f328bSVille Tervo 	if (!conn) {
3801b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3802b62f328bSVille Tervo 		if (!conn) {
3803b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3804230fd16aSAndre Guedes 			goto unlock;
3805b62f328bSVille Tervo 		}
380629b7988aSAndre Guedes 
380729b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3808b9b343d2SAndre Guedes 
3809b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3810b9b343d2SAndre Guedes 			conn->out = true;
3811b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3812b9b343d2SAndre Guedes 		}
3813b62f328bSVille Tervo 	}
3814fcd89c09SVille Tervo 
3815cd17decbSAndre Guedes 	if (ev->status) {
3816cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3817cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3818cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3819cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3820cd17decbSAndre Guedes 		hci_conn_del(conn);
3821cd17decbSAndre Guedes 		goto unlock;
3822cd17decbSAndre Guedes 	}
3823cd17decbSAndre Guedes 
3824b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3825b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
382695b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
382783bc71b4SVinicius Costa Gomes 
38287b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3829fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3830fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3831fcd89c09SVille Tervo 
3832fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3833fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3834fcd89c09SVille Tervo 
3835fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3836fcd89c09SVille Tervo 
3837fcd89c09SVille Tervo unlock:
3838fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3839fcd89c09SVille Tervo }
3840fcd89c09SVille Tervo 
38416039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
38429aa04c91SAndre Guedes {
3843e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3844e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
38453c9e9195SAndre Guedes 	s8 rssi;
38469aa04c91SAndre Guedes 
38479aa04c91SAndre Guedes 	hci_dev_lock(hdev);
38489aa04c91SAndre Guedes 
3849e95beb41SAndre Guedes 	while (num_reports--) {
3850e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3851e95beb41SAndre Guedes 
38523c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
38533c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
385404124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
38553c9e9195SAndre Guedes 
3856e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
38579aa04c91SAndre Guedes 	}
38589aa04c91SAndre Guedes 
38599aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
38609aa04c91SAndre Guedes }
38619aa04c91SAndre Guedes 
38626039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3863a7a595f6SVinicius Costa Gomes {
3864a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3865a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3866bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3867a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3868c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3869a7a595f6SVinicius Costa Gomes 
38709f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3871a7a595f6SVinicius Costa Gomes 
3872a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3873a7a595f6SVinicius Costa Gomes 
3874a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3875bea710feSVinicius Costa Gomes 	if (conn == NULL)
3876bea710feSVinicius Costa Gomes 		goto not_found;
3877a7a595f6SVinicius Costa Gomes 
3878bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3879bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3880bea710feSVinicius Costa Gomes 		goto not_found;
3881bea710feSVinicius Costa Gomes 
3882bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3883a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3884c9839a11SVinicius Costa Gomes 
3885c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3886c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3887a7a595f6SVinicius Costa Gomes 
3888a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3889a7a595f6SVinicius Costa Gomes 
3890c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3891c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3892c9839a11SVinicius Costa Gomes 		kfree(ltk);
3893c9839a11SVinicius Costa Gomes 	}
3894c9839a11SVinicius Costa Gomes 
3895a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3896bea710feSVinicius Costa Gomes 
3897bea710feSVinicius Costa Gomes 	return;
3898bea710feSVinicius Costa Gomes 
3899bea710feSVinicius Costa Gomes not_found:
3900bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3901bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3902bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3903a7a595f6SVinicius Costa Gomes }
3904a7a595f6SVinicius Costa Gomes 
39056039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3906fcd89c09SVille Tervo {
3907fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3908fcd89c09SVille Tervo 
3909fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3910fcd89c09SVille Tervo 
3911fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3912fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3913fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3914fcd89c09SVille Tervo 		break;
3915fcd89c09SVille Tervo 
39169aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
39179aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
39189aa04c91SAndre Guedes 		break;
39199aa04c91SAndre Guedes 
3920a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3921a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3922a7a595f6SVinicius Costa Gomes 		break;
3923a7a595f6SVinicius Costa Gomes 
3924fcd89c09SVille Tervo 	default:
3925fcd89c09SVille Tervo 		break;
3926fcd89c09SVille Tervo 	}
3927fcd89c09SVille Tervo }
3928fcd89c09SVille Tervo 
39299495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
39309495b2eeSAndrei Emeltchenko {
39319495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
39329495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
39339495b2eeSAndrei Emeltchenko 
39349495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
39359495b2eeSAndrei Emeltchenko 
39369495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
39379495b2eeSAndrei Emeltchenko 
39389495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
39399495b2eeSAndrei Emeltchenko 	if (!hcon)
39409495b2eeSAndrei Emeltchenko 		return;
39419495b2eeSAndrei Emeltchenko 
39429495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
39439495b2eeSAndrei Emeltchenko }
39449495b2eeSAndrei Emeltchenko 
39451da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
39461da177e4SLinus Torvalds {
3947a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3948a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
39491da177e4SLinus Torvalds 
39501da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
39511da177e4SLinus Torvalds 
3952a9de9248SMarcel Holtmann 	switch (event) {
39531da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
39541da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
39551da177e4SLinus Torvalds 		break;
39561da177e4SLinus Torvalds 
39571da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
39581da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
39591da177e4SLinus Torvalds 		break;
39601da177e4SLinus Torvalds 
3961a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3962a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
396321d9e30eSMarcel Holtmann 		break;
396421d9e30eSMarcel Holtmann 
39651da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
39661da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
39671da177e4SLinus Torvalds 		break;
39681da177e4SLinus Torvalds 
39691da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
39701da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
39711da177e4SLinus Torvalds 		break;
39721da177e4SLinus Torvalds 
39731da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
39741da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
39751da177e4SLinus Torvalds 		break;
39761da177e4SLinus Torvalds 
3977a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3978a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3979a9de9248SMarcel Holtmann 		break;
3980a9de9248SMarcel Holtmann 
39811da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
39821da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
39831da177e4SLinus Torvalds 		break;
39841da177e4SLinus Torvalds 
3985a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3986a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3987a9de9248SMarcel Holtmann 		break;
3988a9de9248SMarcel Holtmann 
3989a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3990a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3991a9de9248SMarcel Holtmann 		break;
3992a9de9248SMarcel Holtmann 
3993a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3994a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3995a9de9248SMarcel Holtmann 		break;
3996a9de9248SMarcel Holtmann 
3997a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3998a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3999a9de9248SMarcel Holtmann 		break;
4000a9de9248SMarcel Holtmann 
4001a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
4002a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
4003a9de9248SMarcel Holtmann 		break;
4004a9de9248SMarcel Holtmann 
4005a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
4006a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
4007a9de9248SMarcel Holtmann 		break;
4008a9de9248SMarcel Holtmann 
4009a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
4010a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
4011a9de9248SMarcel Holtmann 		break;
4012a9de9248SMarcel Holtmann 
4013a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
4014a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
4015a9de9248SMarcel Holtmann 		break;
4016a9de9248SMarcel Holtmann 
4017a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
4018a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
40191da177e4SLinus Torvalds 		break;
40201da177e4SLinus Torvalds 
40211da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
40221da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
40231da177e4SLinus Torvalds 		break;
40241da177e4SLinus Torvalds 
40251da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
40261da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
40271da177e4SLinus Torvalds 		break;
40281da177e4SLinus Torvalds 
40291da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
40301da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
40311da177e4SLinus Torvalds 		break;
40321da177e4SLinus Torvalds 
40331da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
40341da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
40351da177e4SLinus Torvalds 		break;
40361da177e4SLinus Torvalds 
4037a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
4038a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
4039a8746417SMarcel Holtmann 		break;
4040a8746417SMarcel Holtmann 
404185a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
404285a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
404385a1e930SMarcel Holtmann 		break;
404485a1e930SMarcel Holtmann 
4045a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4046a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
4047a9de9248SMarcel Holtmann 		break;
4048a9de9248SMarcel Holtmann 
4049a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
4050a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
4051a9de9248SMarcel Holtmann 		break;
4052a9de9248SMarcel Holtmann 
4053a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
4054a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
4055a9de9248SMarcel Holtmann 		break;
4056a9de9248SMarcel Holtmann 
4057a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
4058a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
4059a9de9248SMarcel Holtmann 		break;
4060a9de9248SMarcel Holtmann 
406104837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
406204837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
406304837f64SMarcel Holtmann 		break;
406404837f64SMarcel Holtmann 
4065a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
4066a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
40671da177e4SLinus Torvalds 		break;
40681da177e4SLinus Torvalds 
40691c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
40701c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
40711c2e0041SJohan Hedberg 		break;
40721c2e0041SJohan Hedberg 
40730493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
40740493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
40750493684eSMarcel Holtmann 		break;
40760493684eSMarcel Holtmann 
407703b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
407803b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
407903b555e1SJohan Hedberg 		break;
408003b555e1SJohan Hedberg 
4081a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
4082a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
4083a5c29683SJohan Hedberg 		break;
4084a5c29683SJohan Hedberg 
40851143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
40861143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
40871143d458SBrian Gix 		break;
40881143d458SBrian Gix 
408992a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
409092a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
409192a25256SJohan Hedberg 		break;
409292a25256SJohan Hedberg 
409392a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
409492a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
409592a25256SJohan Hedberg 		break;
409692a25256SJohan Hedberg 
40970493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
40980493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
40990493684eSMarcel Holtmann 		break;
41000493684eSMarcel Holtmann 
410141a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
410241a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
410341a96212SMarcel Holtmann 		break;
410441a96212SMarcel Holtmann 
4105fcd89c09SVille Tervo 	case HCI_EV_LE_META:
4106fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
4107fcd89c09SVille Tervo 		break;
4108fcd89c09SVille Tervo 
41099495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
41109495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
41119495b2eeSAndrei Emeltchenko 		break;
41129495b2eeSAndrei Emeltchenko 
41132763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
41142763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
41152763eda6SSzymon Janc 		break;
41162763eda6SSzymon Janc 
4117d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
4118d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
4119d5e91192SAndrei Emeltchenko 		break;
4120d5e91192SAndrei Emeltchenko 
412127695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
412227695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
412327695fb4SAndrei Emeltchenko 		break;
412427695fb4SAndrei Emeltchenko 
4125606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4126606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
4127606e2a10SAndrei Emeltchenko 		break;
4128606e2a10SAndrei Emeltchenko 
41299eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
41309eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
41319eef6b3aSAndrei Emeltchenko 		break;
41329eef6b3aSAndrei Emeltchenko 
413325e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
413425e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
413525e89e99SAndrei Emeltchenko 		break;
413625e89e99SAndrei Emeltchenko 
41371da177e4SLinus Torvalds 	default:
41389f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
41391da177e4SLinus Torvalds 		break;
41401da177e4SLinus Torvalds 	}
41411da177e4SLinus Torvalds 
41421da177e4SLinus Torvalds 	kfree_skb(skb);
41431da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
41441da177e4SLinus Torvalds }
4145