xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 2177bab5)
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;
205bbaf444aSJohan Hedberg 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
206bbaf444aSJohan Hedberg 	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
2073f0f524bSJohan Hedberg 
2083f0f524bSJohan Hedberg 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
2093f0f524bSJohan Hedberg 	hdev->adv_data_len = 0;
210a9de9248SMarcel Holtmann }
211a9de9248SMarcel Holtmann 
212a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
213a9de9248SMarcel Holtmann {
214a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2151da177e4SLinus Torvalds 	void *sent;
2161da177e4SLinus Torvalds 
2179f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2181da177e4SLinus Torvalds 
219a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2201da177e4SLinus Torvalds 	if (!sent)
221a9de9248SMarcel Holtmann 		return;
2221da177e4SLinus Torvalds 
22356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
22456e5cb86SJohan Hedberg 
225f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
226f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
22728cc7bdeSJohan Hedberg 	else if (!status)
22828cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
229f51d5b24SJohan Hedberg 
23056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
2313159d384SJohan Hedberg 
2323f0f524bSJohan Hedberg 	if (!status && !test_bit(HCI_INIT, &hdev->flags))
2333f0f524bSJohan Hedberg 		hci_update_ad(hdev);
2343f0f524bSJohan Hedberg 
2353159d384SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
236a9de9248SMarcel Holtmann }
237a9de9248SMarcel Holtmann 
238a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
239a9de9248SMarcel Holtmann {
240a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
241a9de9248SMarcel Holtmann 
2429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
243a9de9248SMarcel Holtmann 
244a9de9248SMarcel Holtmann 	if (rp->status)
245a9de9248SMarcel Holtmann 		return;
246a9de9248SMarcel Holtmann 
247db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2481f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
249a9de9248SMarcel Holtmann }
250a9de9248SMarcel Holtmann 
251a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
252a9de9248SMarcel Holtmann {
253a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
254a9de9248SMarcel Holtmann 	void *sent;
255a9de9248SMarcel Holtmann 
2569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
257a9de9248SMarcel Holtmann 
258a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
259a9de9248SMarcel Holtmann 	if (!sent)
260a9de9248SMarcel Holtmann 		return;
2611da177e4SLinus Torvalds 
2621da177e4SLinus Torvalds 	if (!status) {
263a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
264a9de9248SMarcel Holtmann 
2651da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2661da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2671da177e4SLinus Torvalds 		else
2681da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2691da177e4SLinus Torvalds 	}
270a9de9248SMarcel Holtmann 
27133ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
27233ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
27333ef95edSJohan Hedberg 
27423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
275a9de9248SMarcel Holtmann }
2761da177e4SLinus Torvalds 
277a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
278a9de9248SMarcel Holtmann {
279a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
280a9de9248SMarcel Holtmann 	void *sent;
281a9de9248SMarcel Holtmann 
2829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
283a9de9248SMarcel Holtmann 
284a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2851da177e4SLinus Torvalds 	if (!sent)
286a9de9248SMarcel Holtmann 		return;
2871da177e4SLinus Torvalds 
2881da177e4SLinus Torvalds 	if (!status) {
289a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
290a9de9248SMarcel Holtmann 
2911da177e4SLinus Torvalds 		if (param)
2921da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2931da177e4SLinus Torvalds 		else
2941da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2951da177e4SLinus Torvalds 	}
296a9de9248SMarcel Holtmann 
29723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2981da177e4SLinus Torvalds }
2991da177e4SLinus Torvalds 
300a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
301a9de9248SMarcel Holtmann {
30236f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
30336f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
304a9de9248SMarcel Holtmann 	void *sent;
3051da177e4SLinus Torvalds 
3069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
307a9de9248SMarcel Holtmann 
308a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3091da177e4SLinus Torvalds 	if (!sent)
310a9de9248SMarcel Holtmann 		return;
3111da177e4SLinus Torvalds 
31236f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
313a9de9248SMarcel Holtmann 
31456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
31556e5cb86SJohan Hedberg 
316fa1bd918SMikel Astiz 	if (status) {
317744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3182d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3192d7cee58SJohan Hedberg 		goto done;
3202d7cee58SJohan Hedberg 	}
3212d7cee58SJohan Hedberg 
3229fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3239fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
324a9de9248SMarcel Holtmann 
32573f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3261da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3279fbcbb45SJohan Hedberg 		if (!old_iscan)
328744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
32916ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
33016ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
33116ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
33216ab91abSJohan Hedberg 					   to);
33316ab91abSJohan Hedberg 		}
3349fbcbb45SJohan Hedberg 	} else if (old_iscan)
335744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3361da177e4SLinus Torvalds 
3379fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3381da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3399fbcbb45SJohan Hedberg 		if (!old_pscan)
340744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3419fbcbb45SJohan Hedberg 	} else if (old_pscan)
342744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
343a9de9248SMarcel Holtmann 
34436f7fc7eSJohan Hedberg done:
34556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
34623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3471da177e4SLinus Torvalds }
3481da177e4SLinus Torvalds 
349a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
350a9de9248SMarcel Holtmann {
351a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
352a9de9248SMarcel Holtmann 
3539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
354a9de9248SMarcel Holtmann 
355a9de9248SMarcel Holtmann 	if (rp->status)
356a9de9248SMarcel Holtmann 		return;
357a9de9248SMarcel Holtmann 
358a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
359a9de9248SMarcel Holtmann 
360a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
361a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
362a9de9248SMarcel Holtmann }
363a9de9248SMarcel Holtmann 
364a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
365a9de9248SMarcel Holtmann {
366a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
367a9de9248SMarcel Holtmann 	void *sent;
368a9de9248SMarcel Holtmann 
3699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
370a9de9248SMarcel Holtmann 
371a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
372a9de9248SMarcel Holtmann 	if (!sent)
373a9de9248SMarcel Holtmann 		return;
374a9de9248SMarcel Holtmann 
3757f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3767f9a903cSMarcel Holtmann 
3777f9a903cSMarcel Holtmann 	if (status == 0)
378a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3797f9a903cSMarcel Holtmann 
3807f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3817f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3827f9a903cSMarcel Holtmann 
3837f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
384a9de9248SMarcel Holtmann }
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
387a9de9248SMarcel Holtmann {
388a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
389a9de9248SMarcel Holtmann 	__u16 setting;
390a9de9248SMarcel Holtmann 
3919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
392a9de9248SMarcel Holtmann 
393a9de9248SMarcel Holtmann 	if (rp->status)
394a9de9248SMarcel Holtmann 		return;
395a9de9248SMarcel Holtmann 
396a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
397a9de9248SMarcel Holtmann 
398a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
399a9de9248SMarcel Holtmann 		return;
400a9de9248SMarcel Holtmann 
401a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
402a9de9248SMarcel Holtmann 
4039f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
404a9de9248SMarcel Holtmann 
4053c54711cSGustavo F. Padovan 	if (hdev->notify)
406a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
407a9de9248SMarcel Holtmann }
408a9de9248SMarcel Holtmann 
4098fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
4108fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
411a9de9248SMarcel Holtmann {
412a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
413f383f275SMarcel Holtmann 	__u16 setting;
414a9de9248SMarcel Holtmann 	void *sent;
415a9de9248SMarcel Holtmann 
4169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
417a9de9248SMarcel Holtmann 
418f383f275SMarcel Holtmann 	if (status)
419f383f275SMarcel Holtmann 		return;
420f383f275SMarcel Holtmann 
421a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
422a9de9248SMarcel Holtmann 	if (!sent)
423a9de9248SMarcel Holtmann 		return;
424a9de9248SMarcel Holtmann 
425f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4261da177e4SLinus Torvalds 
427f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
428f383f275SMarcel Holtmann 		return;
429f383f275SMarcel Holtmann 
4301da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4311da177e4SLinus Torvalds 
4329f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4331da177e4SLinus Torvalds 
4343c54711cSGustavo F. Padovan 	if (hdev->notify)
4351da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4361da177e4SLinus Torvalds }
4371da177e4SLinus Torvalds 
438a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4391da177e4SLinus Torvalds {
440a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4411da177e4SLinus Torvalds 
4429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
4431da177e4SLinus Torvalds 
44423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4451143e5a6SMarcel Holtmann }
4461143e5a6SMarcel Holtmann 
447333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
448333140b5SMarcel Holtmann {
449333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4505ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *sent;
451333140b5SMarcel Holtmann 
4529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
453333140b5SMarcel Holtmann 
454333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
455333140b5SMarcel Holtmann 	if (!sent)
456333140b5SMarcel Holtmann 		return;
457333140b5SMarcel Holtmann 
4585ed8eb2fSJohan Hedberg 	if (!status) {
4595ed8eb2fSJohan Hedberg 		if (sent->mode)
4605ed8eb2fSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_SSP;
4615ed8eb2fSJohan Hedberg 		else
4625ed8eb2fSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_SSP;
4635ed8eb2fSJohan Hedberg 	}
4645ed8eb2fSJohan Hedberg 
465c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4665ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
467c0ecddc2SJohan Hedberg 	else if (!status) {
4685ed8eb2fSJohan Hedberg 		if (sent->mode)
46984bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
47084bde9d6SJohan Hedberg 		else
47184bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
472c0ecddc2SJohan Hedberg 	}
473333140b5SMarcel Holtmann }
474333140b5SMarcel Holtmann 
475a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
476a9de9248SMarcel Holtmann {
477a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
4781143e5a6SMarcel Holtmann 
4799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
4801143e5a6SMarcel Holtmann 
481a9de9248SMarcel Holtmann 	if (rp->status)
48228b8df77SAndrei Emeltchenko 		goto done;
4831143e5a6SMarcel Holtmann 
484a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
485e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
486d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
487e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
488d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
4891da177e4SLinus Torvalds 
4909f1db00cSAndrei Emeltchenko 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
491807deac2SGustavo Padovan 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
492d5859e22SJohan Hedberg 
49328b8df77SAndrei Emeltchenko done:
49428b8df77SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
495d5859e22SJohan Hedberg }
496d5859e22SJohan Hedberg 
4978fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
4988fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
499a9de9248SMarcel Holtmann {
500a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
501a9de9248SMarcel Holtmann 
5029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
503a9de9248SMarcel Holtmann 
5042177bab5SJohan Hedberg 	if (!rp->status)
505a9de9248SMarcel Holtmann 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
506d5859e22SJohan Hedberg 
507d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
508a9de9248SMarcel Holtmann }
509a9de9248SMarcel Holtmann 
5108fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
5118fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
512a9de9248SMarcel Holtmann {
513a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
514a9de9248SMarcel Holtmann 
5159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
516a9de9248SMarcel Holtmann 
517a9de9248SMarcel Holtmann 	if (rp->status)
518a9de9248SMarcel Holtmann 		return;
519a9de9248SMarcel Holtmann 
520a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
5211da177e4SLinus Torvalds 
5221da177e4SLinus Torvalds 	/* Adjust default settings according to features
5231da177e4SLinus Torvalds 	 * supported by device. */
524a9de9248SMarcel Holtmann 
5251da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
5261da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
5271da177e4SLinus Torvalds 
5281da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
5291da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
5301da177e4SLinus Torvalds 
5315b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
5321da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
5335b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
5345b7f9909SMarcel Holtmann 	}
5351da177e4SLinus Torvalds 
5365b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
5371da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
5385b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
5395b7f9909SMarcel Holtmann 	}
5405b7f9909SMarcel Holtmann 
54145db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
5425b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
5435b7f9909SMarcel Holtmann 
5445b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
5455b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
5465b7f9909SMarcel Holtmann 
5475b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
5485b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
5491da177e4SLinus Torvalds 
550efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
551efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
552efc7688bSMarcel Holtmann 
553efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
554efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
555efc7688bSMarcel Holtmann 
556efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
557efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
558efc7688bSMarcel Holtmann 
559a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
560a9de9248SMarcel Holtmann 	       hdev->features[0], hdev->features[1],
561a9de9248SMarcel Holtmann 	       hdev->features[2], hdev->features[3],
562a9de9248SMarcel Holtmann 	       hdev->features[4], hdev->features[5],
563a9de9248SMarcel Holtmann 	       hdev->features[6], hdev->features[7]);
5641da177e4SLinus Torvalds }
5651da177e4SLinus Torvalds 
566971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
567971e3a4bSAndre Guedes 					   struct sk_buff *skb)
568971e3a4bSAndre Guedes {
569971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
570971e3a4bSAndre Guedes 
5719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
572971e3a4bSAndre Guedes 
573971e3a4bSAndre Guedes 	if (rp->status)
5748f984dfaSJohan Hedberg 		goto done;
575971e3a4bSAndre Guedes 
576b5b32b65SAndre Guedes 	switch (rp->page) {
577b5b32b65SAndre Guedes 	case 0:
578b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
579b5b32b65SAndre Guedes 		break;
580b5b32b65SAndre Guedes 	case 1:
58159e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
582b5b32b65SAndre Guedes 		break;
583b5b32b65SAndre Guedes 	}
584971e3a4bSAndre Guedes 
5858f984dfaSJohan Hedberg done:
586971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
587971e3a4bSAndre Guedes }
588971e3a4bSAndre Guedes 
5891e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
5901e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
5911e89cffbSAndrei Emeltchenko {
5921e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
5931e89cffbSAndrei Emeltchenko 
5949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
5951e89cffbSAndrei Emeltchenko 
5961e89cffbSAndrei Emeltchenko 	if (rp->status)
5971e89cffbSAndrei Emeltchenko 		return;
5981e89cffbSAndrei Emeltchenko 
5991e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
6001e89cffbSAndrei Emeltchenko 
6011e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
6021e89cffbSAndrei Emeltchenko }
6031e89cffbSAndrei Emeltchenko 
604a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
605a9de9248SMarcel Holtmann {
606a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
607a9de9248SMarcel Holtmann 
6089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
609a9de9248SMarcel Holtmann 
610a9de9248SMarcel Holtmann 	if (rp->status)
611a9de9248SMarcel Holtmann 		return;
612a9de9248SMarcel Holtmann 
613a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
614a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
615a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
616a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
617da1f5198SMarcel Holtmann 
618da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
619da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
620da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
621da1f5198SMarcel Holtmann 	}
622da1f5198SMarcel Holtmann 
623da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
624da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
6251da177e4SLinus Torvalds 
626807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
627807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
6281da177e4SLinus Torvalds }
6291da177e4SLinus Torvalds 
630a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
631a9de9248SMarcel Holtmann {
632a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
6331da177e4SLinus Torvalds 
6349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
635a9de9248SMarcel Holtmann 
636a9de9248SMarcel Holtmann 	if (!rp->status)
637a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
638a9de9248SMarcel Holtmann 
63923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
64023bb5763SJohan Hedberg }
64123bb5763SJohan Hedberg 
642350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
643350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
644350ee4cfSAndrei Emeltchenko {
645350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
646350ee4cfSAndrei Emeltchenko 
6479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
648350ee4cfSAndrei Emeltchenko 
649350ee4cfSAndrei Emeltchenko 	if (rp->status)
650350ee4cfSAndrei Emeltchenko 		return;
651350ee4cfSAndrei Emeltchenko 
652350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
653350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
654350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
655350ee4cfSAndrei Emeltchenko 
656350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
657350ee4cfSAndrei Emeltchenko 
658350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
659350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
660350ee4cfSAndrei Emeltchenko 
661350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
662350ee4cfSAndrei Emeltchenko }
663350ee4cfSAndrei Emeltchenko 
66423bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
66523bb5763SJohan Hedberg {
66623bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
66723bb5763SJohan Hedberg 
6689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
66923bb5763SJohan Hedberg 
67023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
6711da177e4SLinus Torvalds }
6721da177e4SLinus Torvalds 
673928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
674928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
675928abaa7SAndrei Emeltchenko {
676928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
677928abaa7SAndrei Emeltchenko 
6789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
679928abaa7SAndrei Emeltchenko 
680928abaa7SAndrei Emeltchenko 	if (rp->status)
6818e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
682928abaa7SAndrei Emeltchenko 
683928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
684928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
685928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
686928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
687928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
688928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
689928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
690928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
691928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
692928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
693928abaa7SAndrei Emeltchenko 
694928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
6958e2a0d92SAndrei Emeltchenko 
6968e2a0d92SAndrei Emeltchenko a2mp_rsp:
6978e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
698928abaa7SAndrei Emeltchenko }
699928abaa7SAndrei Emeltchenko 
700903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
701903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
702903e4541SAndrei Emeltchenko {
703903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
704903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
705903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
706903e4541SAndrei Emeltchenko 
707903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
708903e4541SAndrei Emeltchenko 
709903e4541SAndrei Emeltchenko 	if (rp->status)
710903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
711903e4541SAndrei Emeltchenko 
712903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
713903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
714903e4541SAndrei Emeltchenko 
715903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
7162e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
717903e4541SAndrei Emeltchenko 
718903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
719903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
720903e4541SAndrei Emeltchenko 
721903e4541SAndrei Emeltchenko 		/* Read other fragments */
722903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
723903e4541SAndrei Emeltchenko 
724903e4541SAndrei Emeltchenko 		return;
725903e4541SAndrei Emeltchenko 	}
726903e4541SAndrei Emeltchenko 
727903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
728903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
729903e4541SAndrei Emeltchenko 	assoc->offset = 0;
730903e4541SAndrei Emeltchenko 
731903e4541SAndrei Emeltchenko a2mp_rsp:
732903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
733903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
7349495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
735903e4541SAndrei Emeltchenko }
736903e4541SAndrei Emeltchenko 
737b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
738b0916ea0SJohan Hedberg 					  struct sk_buff *skb)
739b0916ea0SJohan Hedberg {
740b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
741b0916ea0SJohan Hedberg 
7429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
743b0916ea0SJohan Hedberg 
744b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
745b0916ea0SJohan Hedberg }
746b0916ea0SJohan Hedberg 
747d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
748d5859e22SJohan Hedberg {
749d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
750d5859e22SJohan Hedberg 
7519f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
752d5859e22SJohan Hedberg 
753d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
754d5859e22SJohan Hedberg }
755d5859e22SJohan Hedberg 
756d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
757d5859e22SJohan Hedberg 				      struct sk_buff *skb)
758d5859e22SJohan Hedberg {
759d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
760d5859e22SJohan Hedberg 
7619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
762d5859e22SJohan Hedberg 
763d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
764d5859e22SJohan Hedberg }
765d5859e22SJohan Hedberg 
766d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
767d5859e22SJohan Hedberg 					 struct sk_buff *skb)
768d5859e22SJohan Hedberg {
76991c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
770d5859e22SJohan Hedberg 
7719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
772d5859e22SJohan Hedberg 
77391c4e9b1SMarcel Holtmann 	if (!rp->status)
77491c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
77591c4e9b1SMarcel Holtmann 
77691c4e9b1SMarcel Holtmann 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
777d5859e22SJohan Hedberg }
778d5859e22SJohan Hedberg 
779d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
780d5859e22SJohan Hedberg {
781d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
782d5859e22SJohan Hedberg 
7839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
784d5859e22SJohan Hedberg 
785d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
786d5859e22SJohan Hedberg }
787d5859e22SJohan Hedberg 
788980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
789980e1a53SJohan Hedberg {
790980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
791980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
792980e1a53SJohan Hedberg 	struct hci_conn *conn;
793980e1a53SJohan Hedberg 
7949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
795980e1a53SJohan Hedberg 
79656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
79756e5cb86SJohan Hedberg 
798a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
799744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
800980e1a53SJohan Hedberg 
801fa1bd918SMikel Astiz 	if (rp->status)
80256e5cb86SJohan Hedberg 		goto unlock;
803980e1a53SJohan Hedberg 
804980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
805980e1a53SJohan Hedberg 	if (!cp)
80656e5cb86SJohan Hedberg 		goto unlock;
807980e1a53SJohan Hedberg 
808980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
809980e1a53SJohan Hedberg 	if (conn)
810980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
81156e5cb86SJohan Hedberg 
81256e5cb86SJohan Hedberg unlock:
81356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
814980e1a53SJohan Hedberg }
815980e1a53SJohan Hedberg 
816980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
817980e1a53SJohan Hedberg {
818980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
819980e1a53SJohan Hedberg 
8209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
821980e1a53SJohan Hedberg 
82256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
82356e5cb86SJohan Hedberg 
824a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
825744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
826980e1a53SJohan Hedberg 						 rp->status);
82756e5cb86SJohan Hedberg 
82856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
829980e1a53SJohan Hedberg }
83056e5cb86SJohan Hedberg 
8316ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
8326ed58ec5SVille Tervo 				       struct sk_buff *skb)
8336ed58ec5SVille Tervo {
8346ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
8356ed58ec5SVille Tervo 
8369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8376ed58ec5SVille Tervo 
8386ed58ec5SVille Tervo 	if (rp->status)
8396ed58ec5SVille Tervo 		return;
8406ed58ec5SVille Tervo 
8416ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
8426ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
8436ed58ec5SVille Tervo 
8446ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
8456ed58ec5SVille Tervo 
8466ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
8476ed58ec5SVille Tervo 
8486ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
8496ed58ec5SVille Tervo }
850980e1a53SJohan Hedberg 
85160e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev,
85260e77321SJohan Hedberg 					  struct sk_buff *skb)
85360e77321SJohan Hedberg {
85460e77321SJohan Hedberg 	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
85560e77321SJohan Hedberg 
85660e77321SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
85760e77321SJohan Hedberg 
85860e77321SJohan Hedberg 	if (!rp->status)
85960e77321SJohan Hedberg 		memcpy(hdev->le_features, rp->features, 8);
86060e77321SJohan Hedberg 
86160e77321SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status);
86260e77321SJohan Hedberg }
86360e77321SJohan Hedberg 
8648fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
8658fa19098SJohan Hedberg 					struct sk_buff *skb)
8668fa19098SJohan Hedberg {
8678fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
8688fa19098SJohan Hedberg 
8698fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8708fa19098SJohan Hedberg 
8713f0f524bSJohan Hedberg 	if (!rp->status) {
8728fa19098SJohan Hedberg 		hdev->adv_tx_power = rp->tx_power;
8733f0f524bSJohan Hedberg 		if (!test_bit(HCI_INIT, &hdev->flags))
8743f0f524bSJohan Hedberg 			hci_update_ad(hdev);
8753f0f524bSJohan Hedberg 	}
8768fa19098SJohan Hedberg 
8778fa19098SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
8788fa19098SJohan Hedberg }
8798fa19098SJohan Hedberg 
880e36b04c8SJohan Hedberg static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
881e36b04c8SJohan Hedberg {
882e36b04c8SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
883e36b04c8SJohan Hedberg 
884e36b04c8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
885e36b04c8SJohan Hedberg 
886e36b04c8SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
887e36b04c8SJohan Hedberg }
888e36b04c8SJohan Hedberg 
889a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
890a5c29683SJohan Hedberg {
891a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
892a5c29683SJohan Hedberg 
8939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
894a5c29683SJohan Hedberg 
89556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
89656e5cb86SJohan Hedberg 
897a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
89804124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
89904124681SGustavo F. Padovan 						 rp->status);
90056e5cb86SJohan Hedberg 
90156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
902a5c29683SJohan Hedberg }
903a5c29683SJohan Hedberg 
904a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
905a5c29683SJohan Hedberg 					  struct sk_buff *skb)
906a5c29683SJohan Hedberg {
907a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
908a5c29683SJohan Hedberg 
9099f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
910a5c29683SJohan Hedberg 
91156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
91256e5cb86SJohan Hedberg 
913a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
914744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
91504124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
91656e5cb86SJohan Hedberg 
91756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
918a5c29683SJohan Hedberg }
919a5c29683SJohan Hedberg 
9201143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
9211143d458SBrian Gix {
9221143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9231143d458SBrian Gix 
9249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9251143d458SBrian Gix 
9261143d458SBrian Gix 	hci_dev_lock(hdev);
9271143d458SBrian Gix 
928a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
929272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
930272d90dfSJohan Hedberg 						 0, rp->status);
9311143d458SBrian Gix 
9321143d458SBrian Gix 	hci_dev_unlock(hdev);
9331143d458SBrian Gix }
9341143d458SBrian Gix 
9351143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
9361143d458SBrian Gix 					  struct sk_buff *skb)
9371143d458SBrian Gix {
9381143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
9391143d458SBrian Gix 
9409f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9411143d458SBrian Gix 
9421143d458SBrian Gix 	hci_dev_lock(hdev);
9431143d458SBrian Gix 
944a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
9451143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
94604124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
9471143d458SBrian Gix 
9481143d458SBrian Gix 	hci_dev_unlock(hdev);
9491143d458SBrian Gix }
9501143d458SBrian Gix 
951c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
952c35938b2SSzymon Janc 					     struct sk_buff *skb)
953c35938b2SSzymon Janc {
954c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
955c35938b2SSzymon Janc 
9569f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
957c35938b2SSzymon Janc 
95856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
959744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
960c35938b2SSzymon Janc 						rp->randomizer, rp->status);
96156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
962c35938b2SSzymon Janc }
963c35938b2SSzymon Janc 
964c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
965c1d5dc4aSJohan Hedberg {
966c1d5dc4aSJohan Hedberg 	__u8 *sent, status = *((__u8 *) skb->data);
967c1d5dc4aSJohan Hedberg 
968c1d5dc4aSJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
969c1d5dc4aSJohan Hedberg 
970c1d5dc4aSJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
971c1d5dc4aSJohan Hedberg 	if (!sent)
972c1d5dc4aSJohan Hedberg 		return;
973c1d5dc4aSJohan Hedberg 
974c1d5dc4aSJohan Hedberg 	hci_dev_lock(hdev);
975c1d5dc4aSJohan Hedberg 
976c1d5dc4aSJohan Hedberg 	if (!status) {
977c1d5dc4aSJohan Hedberg 		if (*sent)
978c1d5dc4aSJohan Hedberg 			set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
979c1d5dc4aSJohan Hedberg 		else
980c1d5dc4aSJohan Hedberg 			clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
981c1d5dc4aSJohan Hedberg 	}
982c1d5dc4aSJohan Hedberg 
983c1d5dc4aSJohan Hedberg 	hci_dev_unlock(hdev);
984c1d5dc4aSJohan Hedberg 
985c1d5dc4aSJohan Hedberg 	if (!test_bit(HCI_INIT, &hdev->flags))
986c1d5dc4aSJohan Hedberg 		hci_update_ad(hdev);
987c1d5dc4aSJohan Hedberg 
988c1d5dc4aSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
989c1d5dc4aSJohan Hedberg }
990c1d5dc4aSJohan Hedberg 
99107f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
99207f7fa5dSAndre Guedes {
99307f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
99407f7fa5dSAndre Guedes 
9959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
9967ba8b4beSAndre Guedes 
9977ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
9983fd24153SAndre Guedes 
9993fd24153SAndre Guedes 	if (status) {
10003fd24153SAndre Guedes 		hci_dev_lock(hdev);
10013fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
10023fd24153SAndre Guedes 		hci_dev_unlock(hdev);
10033fd24153SAndre Guedes 		return;
10043fd24153SAndre Guedes 	}
100507f7fa5dSAndre Guedes }
100607f7fa5dSAndre Guedes 
1007eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1008eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1009eb9d91f5SAndre Guedes {
1010eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1011eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1012eb9d91f5SAndre Guedes 
10139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1014eb9d91f5SAndre Guedes 
1015eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1016eb9d91f5SAndre Guedes 	if (!cp)
1017eb9d91f5SAndre Guedes 		return;
1018eb9d91f5SAndre Guedes 
101968a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
102068a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
10217ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
10227ba8b4beSAndre Guedes 
10233fd24153SAndre Guedes 		if (status) {
10243fd24153SAndre Guedes 			hci_dev_lock(hdev);
10253fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
10263fd24153SAndre Guedes 			hci_dev_unlock(hdev);
10277ba8b4beSAndre Guedes 			return;
10283fd24153SAndre Guedes 		}
10297ba8b4beSAndre Guedes 
1030d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1031d23264a8SAndre Guedes 
1032a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1033343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1034a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
103568a8aea4SAndrei Emeltchenko 		break;
103668a8aea4SAndrei Emeltchenko 
103768a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1038c9ecc48eSAndre Guedes 		if (status) {
1039c9ecc48eSAndre Guedes 			hci_dev_lock(hdev);
1040c9ecc48eSAndre Guedes 			mgmt_stop_discovery_failed(hdev, status);
1041c9ecc48eSAndre Guedes 			hci_dev_unlock(hdev);
10427ba8b4beSAndre Guedes 			return;
1043c9ecc48eSAndre Guedes 		}
10447ba8b4beSAndre Guedes 
1045d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1046d23264a8SAndre Guedes 
1047bc3dd33cSAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1048bc3dd33cSAndre Guedes 		    hdev->discovery.state == DISCOVERY_FINDING) {
10495e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
10505e0452c0SAndre Guedes 		} else {
1051c599008fSAndre Guedes 			hci_dev_lock(hdev);
1052c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1053c599008fSAndre Guedes 			hci_dev_unlock(hdev);
10545e0452c0SAndre Guedes 		}
1055c599008fSAndre Guedes 
105668a8aea4SAndrei Emeltchenko 		break;
105768a8aea4SAndrei Emeltchenko 
105868a8aea4SAndrei Emeltchenko 	default:
105968a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
106068a8aea4SAndrei Emeltchenko 		break;
106135815085SAndre Guedes 	}
1062eb9d91f5SAndre Guedes }
1063eb9d91f5SAndre Guedes 
1064cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1065cf1d081fSJohan Hedberg 					   struct sk_buff *skb)
1066cf1d081fSJohan Hedberg {
1067cf1d081fSJohan Hedberg 	struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
1068cf1d081fSJohan Hedberg 
1069cf1d081fSJohan Hedberg 	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
1070cf1d081fSJohan Hedberg 
1071cf1d081fSJohan Hedberg 	if (!rp->status)
1072cf1d081fSJohan Hedberg 		hdev->le_white_list_size = rp->size;
1073cf1d081fSJohan Hedberg 
1074cf1d081fSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status);
1075cf1d081fSJohan Hedberg }
1076cf1d081fSJohan Hedberg 
1077a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1078a7a595f6SVinicius Costa Gomes {
1079a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1080a7a595f6SVinicius Costa Gomes 
10819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1082a7a595f6SVinicius Costa Gomes 
1083a7a595f6SVinicius Costa Gomes 	if (rp->status)
1084a7a595f6SVinicius Costa Gomes 		return;
1085a7a595f6SVinicius Costa Gomes 
1086a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1087a7a595f6SVinicius Costa Gomes }
1088a7a595f6SVinicius Costa Gomes 
1089a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1090a7a595f6SVinicius Costa Gomes {
1091a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1092a7a595f6SVinicius Costa Gomes 
10939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1094a7a595f6SVinicius Costa Gomes 
1095a7a595f6SVinicius Costa Gomes 	if (rp->status)
1096a7a595f6SVinicius Costa Gomes 		return;
1097a7a595f6SVinicius Costa Gomes 
1098a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1099a7a595f6SVinicius Costa Gomes }
1100a7a595f6SVinicius Costa Gomes 
11019b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
11029b008c04SJohan Hedberg 					    struct sk_buff *skb)
11039b008c04SJohan Hedberg {
11049b008c04SJohan Hedberg 	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
11059b008c04SJohan Hedberg 
11069b008c04SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
11079b008c04SJohan Hedberg 
11089b008c04SJohan Hedberg 	if (!rp->status)
11099b008c04SJohan Hedberg 		memcpy(hdev->le_states, rp->le_states, 8);
11109b008c04SJohan Hedberg 
11119b008c04SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, rp->status);
11129b008c04SJohan Hedberg }
11139b008c04SJohan Hedberg 
11146039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1115f9b49306SAndre Guedes 					   struct sk_buff *skb)
1116f9b49306SAndre Guedes {
111706199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1118f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1119f9b49306SAndre Guedes 
11209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1121f9b49306SAndre Guedes 
112206199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
11238f984dfaSJohan Hedberg 	if (!sent)
1124f9b49306SAndre Guedes 		return;
1125f9b49306SAndre Guedes 
11268f984dfaSJohan Hedberg 	if (!status) {
11278f984dfaSJohan Hedberg 		if (sent->le)
11288f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
11298f984dfaSJohan Hedberg 		else
11308f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
113153b2caabSJohan Hedberg 
113253b2caabSJohan Hedberg 		if (sent->simul)
113353b2caabSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE_BREDR;
113453b2caabSJohan Hedberg 		else
113553b2caabSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
11368f984dfaSJohan Hedberg 	}
11378f984dfaSJohan Hedberg 
11388f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
11398f984dfaSJohan Hedberg 	    !test_bit(HCI_INIT, &hdev->flags))
11408f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
11418f984dfaSJohan Hedberg 
11428f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1143f9b49306SAndre Guedes }
1144f9b49306SAndre Guedes 
114593c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
114693c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
114793c284eeSAndrei Emeltchenko {
114893c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
114993c284eeSAndrei Emeltchenko 
115093c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
115193c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
115293c284eeSAndrei Emeltchenko 
115393c284eeSAndrei Emeltchenko 	if (rp->status)
115493c284eeSAndrei Emeltchenko 		return;
115593c284eeSAndrei Emeltchenko 
115693c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
115793c284eeSAndrei Emeltchenko }
115893c284eeSAndrei Emeltchenko 
11596039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1160a9de9248SMarcel Holtmann {
11619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1162a9de9248SMarcel Holtmann 
1163a9de9248SMarcel Holtmann 	if (status) {
116423bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1165a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
116656e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1167a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11687a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
116956e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1170314b2381SJohan Hedberg 		return;
1171314b2381SJohan Hedberg 	}
1172314b2381SJohan Hedberg 
117389352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
117489352e7dSAndre Guedes 
117556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1176343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
117756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1178a9de9248SMarcel Holtmann }
1179a9de9248SMarcel Holtmann 
11806039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
11811da177e4SLinus Torvalds {
1182a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
11831da177e4SLinus Torvalds 	struct hci_conn *conn;
11841da177e4SLinus Torvalds 
11859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1186a9de9248SMarcel Holtmann 
1187a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
11881da177e4SLinus Torvalds 	if (!cp)
11891da177e4SLinus Torvalds 		return;
11901da177e4SLinus Torvalds 
11911da177e4SLinus Torvalds 	hci_dev_lock(hdev);
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
11941da177e4SLinus Torvalds 
11956ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
11961da177e4SLinus Torvalds 
11971da177e4SLinus Torvalds 	if (status) {
11981da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
11994c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
12001da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
12011da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
12021da177e4SLinus Torvalds 				hci_conn_del(conn);
12034c67bc74SMarcel Holtmann 			} else
12044c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
12051da177e4SLinus Torvalds 		}
12061da177e4SLinus Torvalds 	} else {
12071da177e4SLinus Torvalds 		if (!conn) {
12081da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
12091da177e4SLinus Torvalds 			if (conn) {
1210a0c808b3SJohan Hedberg 				conn->out = true;
12111da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
12121da177e4SLinus Torvalds 			} else
1213893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12141da177e4SLinus Torvalds 		}
12151da177e4SLinus Torvalds 	}
12161da177e4SLinus Torvalds 
12171da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12181da177e4SLinus Torvalds }
12191da177e4SLinus Torvalds 
1220a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12211da177e4SLinus Torvalds {
1222a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12231da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12241da177e4SLinus Torvalds 	__u16 handle;
12251da177e4SLinus Torvalds 
12269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1227b6a0dc82SMarcel Holtmann 
1228a9de9248SMarcel Holtmann 	if (!status)
1229a9de9248SMarcel Holtmann 		return;
1230a9de9248SMarcel Holtmann 
1231a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12321da177e4SLinus Torvalds 	if (!cp)
1233a9de9248SMarcel Holtmann 		return;
12341da177e4SLinus Torvalds 
12351da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12361da177e4SLinus Torvalds 
12379f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
12381da177e4SLinus Torvalds 
12391da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12401da177e4SLinus Torvalds 
12411da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12425a08ecceSAndrei Emeltchenko 	if (acl) {
12435a08ecceSAndrei Emeltchenko 		sco = acl->link;
12445a08ecceSAndrei Emeltchenko 		if (sco) {
12451da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12461da177e4SLinus Torvalds 
12471da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12481da177e4SLinus Torvalds 			hci_conn_del(sco);
12491da177e4SLinus Torvalds 		}
12505a08ecceSAndrei Emeltchenko 	}
12511da177e4SLinus Torvalds 
12521da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12531da177e4SLinus Torvalds }
12541da177e4SLinus Torvalds 
1255f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1256f8558555SMarcel Holtmann {
1257f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1258f8558555SMarcel Holtmann 	struct hci_conn *conn;
1259f8558555SMarcel Holtmann 
12609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1261f8558555SMarcel Holtmann 
1262f8558555SMarcel Holtmann 	if (!status)
1263f8558555SMarcel Holtmann 		return;
1264f8558555SMarcel Holtmann 
1265f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1266f8558555SMarcel Holtmann 	if (!cp)
1267f8558555SMarcel Holtmann 		return;
1268f8558555SMarcel Holtmann 
1269f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1270f8558555SMarcel Holtmann 
1271f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1272f8558555SMarcel Holtmann 	if (conn) {
1273f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1274f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1275f8558555SMarcel Holtmann 			hci_conn_put(conn);
1276f8558555SMarcel Holtmann 		}
1277f8558555SMarcel Holtmann 	}
1278f8558555SMarcel Holtmann 
1279f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1280f8558555SMarcel Holtmann }
1281f8558555SMarcel Holtmann 
1282f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1283f8558555SMarcel Holtmann {
1284f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1285f8558555SMarcel Holtmann 	struct hci_conn *conn;
1286f8558555SMarcel Holtmann 
12879f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1288f8558555SMarcel Holtmann 
1289f8558555SMarcel Holtmann 	if (!status)
1290f8558555SMarcel Holtmann 		return;
1291f8558555SMarcel Holtmann 
1292f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1293f8558555SMarcel Holtmann 	if (!cp)
1294f8558555SMarcel Holtmann 		return;
1295f8558555SMarcel Holtmann 
1296f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1297f8558555SMarcel Holtmann 
1298f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1299f8558555SMarcel Holtmann 	if (conn) {
1300f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1301f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1302f8558555SMarcel Holtmann 			hci_conn_put(conn);
1303f8558555SMarcel Holtmann 		}
1304f8558555SMarcel Holtmann 	}
1305f8558555SMarcel Holtmann 
1306f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1307f8558555SMarcel Holtmann }
1308f8558555SMarcel Holtmann 
1309127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1310392599b9SJohan Hedberg 				    struct hci_conn *conn)
1311392599b9SJohan Hedberg {
1312392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1313392599b9SJohan Hedberg 		return 0;
1314392599b9SJohan Hedberg 
1315765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1316392599b9SJohan Hedberg 		return 0;
1317392599b9SJohan Hedberg 
1318392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1319e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1320807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1321807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1322392599b9SJohan Hedberg 		return 0;
1323392599b9SJohan Hedberg 
1324392599b9SJohan Hedberg 	return 1;
1325392599b9SJohan Hedberg }
1326392599b9SJohan Hedberg 
13276039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
132800abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
132930dc78e1SJohan Hedberg {
133030dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
133130dc78e1SJohan Hedberg 
133230dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
133330dc78e1SJohan Hedberg 
133430dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
133530dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
133630dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
133730dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
133830dc78e1SJohan Hedberg 
133930dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
134030dc78e1SJohan Hedberg }
134130dc78e1SJohan Hedberg 
1342b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
134330dc78e1SJohan Hedberg {
134430dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
134530dc78e1SJohan Hedberg 	struct inquiry_entry *e;
134630dc78e1SJohan Hedberg 
1347b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1348b644ba33SJohan Hedberg 		return false;
1349b644ba33SJohan Hedberg 
1350b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1351c810089cSRam Malovany 	if (!e)
1352c810089cSRam Malovany 		return false;
1353c810089cSRam Malovany 
1354b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1355b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1356b644ba33SJohan Hedberg 		return true;
1357b644ba33SJohan Hedberg 	}
1358b644ba33SJohan Hedberg 
1359b644ba33SJohan Hedberg 	return false;
1360b644ba33SJohan Hedberg }
1361b644ba33SJohan Hedberg 
1362b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1363b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1364b644ba33SJohan Hedberg {
1365b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1366b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1367b644ba33SJohan Hedberg 
1368b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
136904124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
137004124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1371b644ba33SJohan Hedberg 
1372b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1373b644ba33SJohan Hedberg 		return;
1374b644ba33SJohan Hedberg 
137530dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
137630dc78e1SJohan Hedberg 		goto discov_complete;
137730dc78e1SJohan Hedberg 
137830dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
137930dc78e1SJohan Hedberg 		return;
138030dc78e1SJohan Hedberg 
138130dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
13827cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
13837cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
13847cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
13857cc8380eSRam Malovany 	 * Event */
13867cc8380eSRam Malovany 	if (!e)
13877cc8380eSRam Malovany 		return;
13887cc8380eSRam Malovany 
138930dc78e1SJohan Hedberg 	list_del(&e->list);
13907cc8380eSRam Malovany 	if (name) {
13917cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1392b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1393b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1394c3e7c0d9SRam Malovany 	} else {
1395c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
139630dc78e1SJohan Hedberg 	}
139730dc78e1SJohan Hedberg 
1398b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
139930dc78e1SJohan Hedberg 		return;
140030dc78e1SJohan Hedberg 
140130dc78e1SJohan Hedberg discov_complete:
140230dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
140330dc78e1SJohan Hedberg }
140430dc78e1SJohan Hedberg 
1405a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
14061da177e4SLinus Torvalds {
1407127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1408127178d2SJohan Hedberg 	struct hci_conn *conn;
1409127178d2SJohan Hedberg 
14109f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1411127178d2SJohan Hedberg 
1412127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1413127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1414127178d2SJohan Hedberg 	if (!status)
1415127178d2SJohan Hedberg 		return;
1416127178d2SJohan Hedberg 
1417127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1418127178d2SJohan Hedberg 	if (!cp)
1419127178d2SJohan Hedberg 		return;
1420127178d2SJohan Hedberg 
1421127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1422127178d2SJohan Hedberg 
1423127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1424b644ba33SJohan Hedberg 
1425b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1426b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1427b644ba33SJohan Hedberg 
142879c6c70cSJohan Hedberg 	if (!conn)
142979c6c70cSJohan Hedberg 		goto unlock;
143079c6c70cSJohan Hedberg 
143179c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
143279c6c70cSJohan Hedberg 		goto unlock;
143379c6c70cSJohan Hedberg 
143451a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1435127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1436127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1437127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1438127178d2SJohan Hedberg 	}
1439127178d2SJohan Hedberg 
144079c6c70cSJohan Hedberg unlock:
1441127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1442a9de9248SMarcel Holtmann }
14431da177e4SLinus Torvalds 
1444769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1445769be974SMarcel Holtmann {
1446769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1447769be974SMarcel Holtmann 	struct hci_conn *conn;
1448769be974SMarcel Holtmann 
14499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1450769be974SMarcel Holtmann 
1451769be974SMarcel Holtmann 	if (!status)
1452769be974SMarcel Holtmann 		return;
1453769be974SMarcel Holtmann 
1454769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1455769be974SMarcel Holtmann 	if (!cp)
1456769be974SMarcel Holtmann 		return;
1457769be974SMarcel Holtmann 
1458769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1459769be974SMarcel Holtmann 
1460769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1461769be974SMarcel Holtmann 	if (conn) {
1462769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1463769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1464769be974SMarcel Holtmann 			hci_conn_put(conn);
1465769be974SMarcel Holtmann 		}
1466769be974SMarcel Holtmann 	}
1467769be974SMarcel Holtmann 
1468769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1469769be974SMarcel Holtmann }
1470769be974SMarcel Holtmann 
1471769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1472769be974SMarcel Holtmann {
1473769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1474769be974SMarcel Holtmann 	struct hci_conn *conn;
1475769be974SMarcel Holtmann 
14769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1477769be974SMarcel Holtmann 
1478769be974SMarcel Holtmann 	if (!status)
1479769be974SMarcel Holtmann 		return;
1480769be974SMarcel Holtmann 
1481769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1482769be974SMarcel Holtmann 	if (!cp)
1483769be974SMarcel Holtmann 		return;
1484769be974SMarcel Holtmann 
1485769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1486769be974SMarcel Holtmann 
1487769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1488769be974SMarcel Holtmann 	if (conn) {
1489769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1490769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1491769be974SMarcel Holtmann 			hci_conn_put(conn);
1492769be974SMarcel Holtmann 		}
1493769be974SMarcel Holtmann 	}
1494769be974SMarcel Holtmann 
1495769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1496769be974SMarcel Holtmann }
1497769be974SMarcel Holtmann 
1498a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1499a9de9248SMarcel Holtmann {
1500b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1501b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1502b6a0dc82SMarcel Holtmann 	__u16 handle;
1503b6a0dc82SMarcel Holtmann 
15049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1505b6a0dc82SMarcel Holtmann 
1506b6a0dc82SMarcel Holtmann 	if (!status)
1507b6a0dc82SMarcel Holtmann 		return;
1508b6a0dc82SMarcel Holtmann 
1509b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1510b6a0dc82SMarcel Holtmann 	if (!cp)
1511b6a0dc82SMarcel Holtmann 		return;
1512b6a0dc82SMarcel Holtmann 
1513b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1514b6a0dc82SMarcel Holtmann 
15159f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1516b6a0dc82SMarcel Holtmann 
1517b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1518b6a0dc82SMarcel Holtmann 
1519b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15205a08ecceSAndrei Emeltchenko 	if (acl) {
15215a08ecceSAndrei Emeltchenko 		sco = acl->link;
15225a08ecceSAndrei Emeltchenko 		if (sco) {
1523b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1524b6a0dc82SMarcel Holtmann 
1525b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1526b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1527b6a0dc82SMarcel Holtmann 		}
15285a08ecceSAndrei Emeltchenko 	}
1529b6a0dc82SMarcel Holtmann 
1530b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1531a9de9248SMarcel Holtmann }
1532a9de9248SMarcel Holtmann 
1533a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1534a9de9248SMarcel Holtmann {
1535a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
153604837f64SMarcel Holtmann 	struct hci_conn *conn;
153704837f64SMarcel Holtmann 
15389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1539a9de9248SMarcel Holtmann 
1540a9de9248SMarcel Holtmann 	if (!status)
1541a9de9248SMarcel Holtmann 		return;
1542a9de9248SMarcel Holtmann 
1543a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
154404837f64SMarcel Holtmann 	if (!cp)
1545a9de9248SMarcel Holtmann 		return;
154604837f64SMarcel Holtmann 
154704837f64SMarcel Holtmann 	hci_dev_lock(hdev);
154804837f64SMarcel Holtmann 
154904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1550e73439d8SMarcel Holtmann 	if (conn) {
155151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
155204837f64SMarcel Holtmann 
155351a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1554e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1555e73439d8SMarcel Holtmann 	}
1556e73439d8SMarcel Holtmann 
155704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
155804837f64SMarcel Holtmann }
155904837f64SMarcel Holtmann 
1560a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1561a9de9248SMarcel Holtmann {
1562a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
156304837f64SMarcel Holtmann 	struct hci_conn *conn;
156404837f64SMarcel Holtmann 
15659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1566a9de9248SMarcel Holtmann 
1567a9de9248SMarcel Holtmann 	if (!status)
1568a9de9248SMarcel Holtmann 		return;
1569a9de9248SMarcel Holtmann 
1570a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
157104837f64SMarcel Holtmann 	if (!cp)
1572a9de9248SMarcel Holtmann 		return;
157304837f64SMarcel Holtmann 
157404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
157504837f64SMarcel Holtmann 
157604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1577e73439d8SMarcel Holtmann 	if (conn) {
157851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
157904837f64SMarcel Holtmann 
158051a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1581e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1582e73439d8SMarcel Holtmann 	}
1583e73439d8SMarcel Holtmann 
158404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
158504837f64SMarcel Holtmann }
158604837f64SMarcel Holtmann 
158788c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
158888c3df13SJohan Hedberg {
158988c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
159088c3df13SJohan Hedberg 	struct hci_conn *conn;
159188c3df13SJohan Hedberg 
159288c3df13SJohan Hedberg 	if (!status)
159388c3df13SJohan Hedberg 		return;
159488c3df13SJohan Hedberg 
159588c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
159688c3df13SJohan Hedberg 	if (!cp)
159788c3df13SJohan Hedberg 		return;
159888c3df13SJohan Hedberg 
159988c3df13SJohan Hedberg 	hci_dev_lock(hdev);
160088c3df13SJohan Hedberg 
160188c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
160288c3df13SJohan Hedberg 	if (conn)
160388c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
160488c3df13SJohan Hedberg 				       conn->dst_type, status);
160588c3df13SJohan Hedberg 
160688c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
160788c3df13SJohan Hedberg }
160888c3df13SJohan Hedberg 
1609fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1610fcd89c09SVille Tervo {
1611fcd89c09SVille Tervo 	struct hci_conn *conn;
1612fcd89c09SVille Tervo 
16139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1614fcd89c09SVille Tervo 
1615f00a06acSAndre Guedes 	if (status) {
1616fcd89c09SVille Tervo 		hci_dev_lock(hdev);
1617fcd89c09SVille Tervo 
16180c95ab78SAndre Guedes 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
1619f00a06acSAndre Guedes 		if (!conn) {
1620f00a06acSAndre Guedes 			hci_dev_unlock(hdev);
1621f00a06acSAndre Guedes 			return;
1622f00a06acSAndre Guedes 		}
1623fcd89c09SVille Tervo 
16246ed93dc6SAndrei Emeltchenko 		BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
1625fcd89c09SVille Tervo 
1626fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
16270c95ab78SAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
1628328c9248SHemant Gupta 				    conn->dst_type, status);
1629fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, status);
1630fcd89c09SVille Tervo 		hci_conn_del(conn);
1631fcd89c09SVille Tervo 
1632fcd89c09SVille Tervo 		hci_dev_unlock(hdev);
1633fcd89c09SVille Tervo 	}
1634f00a06acSAndre Guedes }
1635fcd89c09SVille Tervo 
1636a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1637a7a595f6SVinicius Costa Gomes {
16389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1639a7a595f6SVinicius Costa Gomes }
1640a7a595f6SVinicius Costa Gomes 
1641a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1642a02226d6SAndrei Emeltchenko {
164393c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
164493c284eeSAndrei Emeltchenko 
1645a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
164693c284eeSAndrei Emeltchenko 
164793c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
164893c284eeSAndrei Emeltchenko 	if (!cp)
164993c284eeSAndrei Emeltchenko 		return;
165093c284eeSAndrei Emeltchenko 
1651e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1652e58917b9SAndrei Emeltchenko 
1653e58917b9SAndrei Emeltchenko 	if (status) {
1654e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1655e58917b9SAndrei Emeltchenko 
1656e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1657e58917b9SAndrei Emeltchenko 		if (hcon)
1658e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1659e58917b9SAndrei Emeltchenko 	} else {
166093c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1661a02226d6SAndrei Emeltchenko 	}
1662a02226d6SAndrei Emeltchenko 
1663e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1664e58917b9SAndrei Emeltchenko }
1665e58917b9SAndrei Emeltchenko 
16660b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
16670b26ab9dSAndrei Emeltchenko {
16680b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
16690b26ab9dSAndrei Emeltchenko 
16700b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
16710b26ab9dSAndrei Emeltchenko 
16720b26ab9dSAndrei Emeltchenko 	if (status)
16730b26ab9dSAndrei Emeltchenko 		return;
16740b26ab9dSAndrei Emeltchenko 
16750b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
16760b26ab9dSAndrei Emeltchenko 	if (!cp)
16770b26ab9dSAndrei Emeltchenko 		return;
16780b26ab9dSAndrei Emeltchenko 
16790b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
16800b26ab9dSAndrei Emeltchenko }
16810b26ab9dSAndrei Emeltchenko 
16825ce66b59SAndrei Emeltchenko static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
16835ce66b59SAndrei Emeltchenko {
16845ce66b59SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
16855ce66b59SAndrei Emeltchenko }
16865ce66b59SAndrei Emeltchenko 
16876039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16881da177e4SLinus Torvalds {
16891da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
169030dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
169130dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16921da177e4SLinus Torvalds 
16939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
16941da177e4SLinus Torvalds 
169523bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16966bd57416SMarcel Holtmann 
1697a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
169889352e7dSAndre Guedes 
169989352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
170089352e7dSAndre Guedes 		return;
170189352e7dSAndre Guedes 
1702a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
170330dc78e1SJohan Hedberg 		return;
170430dc78e1SJohan Hedberg 
170556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
170630dc78e1SJohan Hedberg 
1707343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
170830dc78e1SJohan Hedberg 		goto unlock;
170930dc78e1SJohan Hedberg 
171030dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1711ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
171230dc78e1SJohan Hedberg 		goto unlock;
171330dc78e1SJohan Hedberg 	}
171430dc78e1SJohan Hedberg 
171530dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
171630dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
171730dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
171830dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
171930dc78e1SJohan Hedberg 	} else {
172030dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
172130dc78e1SJohan Hedberg 	}
172230dc78e1SJohan Hedberg 
172330dc78e1SJohan Hedberg unlock:
172456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
17251da177e4SLinus Torvalds }
17261da177e4SLinus Torvalds 
17276039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
17281da177e4SLinus Torvalds {
172945bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1730a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
17311da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
17321da177e4SLinus Torvalds 
17331da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
17341da177e4SLinus Torvalds 
173545bb4bf0SMarcel Holtmann 	if (!num_rsp)
173645bb4bf0SMarcel Holtmann 		return;
173745bb4bf0SMarcel Holtmann 
17381519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
17391519cc17SAndre Guedes 		return;
17401519cc17SAndre Guedes 
17411da177e4SLinus Torvalds 	hci_dev_lock(hdev);
174245bb4bf0SMarcel Holtmann 
1743e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1744388fc8faSJohan Hedberg 		bool name_known, ssp;
17453175405bSJohan Hedberg 
17461da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
17471da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
17481da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
17491da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
17501da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
17511da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17521da177e4SLinus Torvalds 		data.rssi		= 0x00;
175341a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17543175405bSJohan Hedberg 
1755388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
175648264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
175704124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
175804124681SGustavo F. Padovan 				  0);
17591da177e4SLinus Torvalds 	}
176045bb4bf0SMarcel Holtmann 
17611da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17621da177e4SLinus Torvalds }
17631da177e4SLinus Torvalds 
17646039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17651da177e4SLinus Torvalds {
1766a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1767a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17681da177e4SLinus Torvalds 
1769a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
177045bb4bf0SMarcel Holtmann 
17711da177e4SLinus Torvalds 	hci_dev_lock(hdev);
177245bb4bf0SMarcel Holtmann 
1773a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17749499237aSMarcel Holtmann 	if (!conn) {
17759499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17769499237aSMarcel Holtmann 			goto unlock;
17779499237aSMarcel Holtmann 
17789499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1779a9de9248SMarcel Holtmann 		if (!conn)
1780a9de9248SMarcel Holtmann 			goto unlock;
178145bb4bf0SMarcel Holtmann 
17829499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17839499237aSMarcel Holtmann 	}
17849499237aSMarcel Holtmann 
1785a9de9248SMarcel Holtmann 	if (!ev->status) {
1786a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1787769be974SMarcel Holtmann 
1788769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1789769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1790769be974SMarcel Holtmann 			hci_conn_hold(conn);
1791a9ea3ed9SSzymon Janc 
1792a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1793a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1794a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1795a9ea3ed9SSzymon Janc 			else
1796052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1797769be974SMarcel Holtmann 		} else
1798a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1799a9de9248SMarcel Holtmann 
18009eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
18017d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
18027d0db0a3SMarcel Holtmann 
1803a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1804a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1805a9de9248SMarcel Holtmann 
1806a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1807a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1808a9de9248SMarcel Holtmann 
1809a9de9248SMarcel Holtmann 		/* Get remote features */
1810a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1811a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1812a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1813769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1814769be974SMarcel Holtmann 				     sizeof(cp), &cp);
181545bb4bf0SMarcel Holtmann 		}
1816a9de9248SMarcel Holtmann 
1817a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1818d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1819a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1820a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1821a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
182204124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
182304124681SGustavo F. Padovan 				     &cp);
1824a9de9248SMarcel Holtmann 		}
182517d5c04cSJohan Hedberg 	} else {
1826a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
182717d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1828744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
182948264f06SJohan Hedberg 					    conn->dst_type, ev->status);
183017d5c04cSJohan Hedberg 	}
183145bb4bf0SMarcel Holtmann 
1832e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1833e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
183445bb4bf0SMarcel Holtmann 
1835769be974SMarcel Holtmann 	if (ev->status) {
1836a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1837a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1838c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1839c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1840a9de9248SMarcel Holtmann 
1841a9de9248SMarcel Holtmann unlock:
18421da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1843a9de9248SMarcel Holtmann 
1844a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
18451da177e4SLinus Torvalds }
18461da177e4SLinus Torvalds 
184720714bfeSFrédéric Dalleau void hci_conn_accept(struct hci_conn *conn, int mask)
184820714bfeSFrédéric Dalleau {
184920714bfeSFrédéric Dalleau 	struct hci_dev *hdev = conn->hdev;
185020714bfeSFrédéric Dalleau 
185120714bfeSFrédéric Dalleau 	BT_DBG("conn %p", conn);
185220714bfeSFrédéric Dalleau 
185320714bfeSFrédéric Dalleau 	conn->state = BT_CONFIG;
185420714bfeSFrédéric Dalleau 
185520714bfeSFrédéric Dalleau 	if (!lmp_esco_capable(hdev)) {
185620714bfeSFrédéric Dalleau 		struct hci_cp_accept_conn_req cp;
185720714bfeSFrédéric Dalleau 
185820714bfeSFrédéric Dalleau 		bacpy(&cp.bdaddr, &conn->dst);
185920714bfeSFrédéric Dalleau 
186020714bfeSFrédéric Dalleau 		if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
186120714bfeSFrédéric Dalleau 			cp.role = 0x00; /* Become master */
186220714bfeSFrédéric Dalleau 		else
186320714bfeSFrédéric Dalleau 			cp.role = 0x01; /* Remain slave */
186420714bfeSFrédéric Dalleau 
186520714bfeSFrédéric Dalleau 		hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
186620714bfeSFrédéric Dalleau 	} else /* lmp_esco_capable(hdev)) */ {
186720714bfeSFrédéric Dalleau 		struct hci_cp_accept_sync_conn_req cp;
186820714bfeSFrédéric Dalleau 
186920714bfeSFrédéric Dalleau 		bacpy(&cp.bdaddr, &conn->dst);
187020714bfeSFrédéric Dalleau 		cp.pkt_type = cpu_to_le16(conn->pkt_type);
187120714bfeSFrédéric Dalleau 
187220714bfeSFrédéric Dalleau 		cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
187320714bfeSFrédéric Dalleau 		cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
187420714bfeSFrédéric Dalleau 		cp.max_latency    = __constant_cpu_to_le16(0xffff);
187520714bfeSFrédéric Dalleau 		cp.content_format = cpu_to_le16(hdev->voice_setting);
187620714bfeSFrédéric Dalleau 		cp.retrans_effort = 0xff;
187720714bfeSFrédéric Dalleau 
187820714bfeSFrédéric Dalleau 		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
187920714bfeSFrédéric Dalleau 			     sizeof(cp), &cp);
188020714bfeSFrédéric Dalleau 	}
188120714bfeSFrédéric Dalleau }
188220714bfeSFrédéric Dalleau 
18836039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18841da177e4SLinus Torvalds {
1885a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
18861da177e4SLinus Torvalds 	int mask = hdev->link_mode;
188720714bfeSFrédéric Dalleau 	__u8 flags = 0;
18881da177e4SLinus Torvalds 
18896ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
1890807deac2SGustavo Padovan 	       ev->link_type);
18911da177e4SLinus Torvalds 
189220714bfeSFrédéric Dalleau 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
189320714bfeSFrédéric Dalleau 				      &flags);
18941da177e4SLinus Torvalds 
1895138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1896138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
18971da177e4SLinus Torvalds 		/* Connection accepted */
1898c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
18991da177e4SLinus Torvalds 		struct hci_conn *conn;
19001da177e4SLinus Torvalds 
19011da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1902b6a0dc82SMarcel Holtmann 
1903cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1904cc11b9c1SAndrei Emeltchenko 		if (ie)
1905c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1906c7bdd502SMarcel Holtmann 
19078fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
19088fc9ced3SGustavo Padovan 					       &ev->bdaddr);
19091da177e4SLinus Torvalds 		if (!conn) {
1910cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1911cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1912893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
19131da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
19141da177e4SLinus Torvalds 				return;
19151da177e4SLinus Torvalds 			}
19161da177e4SLinus Torvalds 		}
1917b6a0dc82SMarcel Holtmann 
19181da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
1919b6a0dc82SMarcel Holtmann 
19201da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
19211da177e4SLinus Torvalds 
192220714bfeSFrédéric Dalleau 		if (ev->link_type == ACL_LINK ||
192320714bfeSFrédéric Dalleau 		    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
1924b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
192520714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1926b6a0dc82SMarcel Holtmann 
19271da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
19281da177e4SLinus Torvalds 
19291da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
19301da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
19311da177e4SLinus Torvalds 			else
19321da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
19331da177e4SLinus Torvalds 
193404124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
193504124681SGustavo F. Padovan 				     &cp);
193620714bfeSFrédéric Dalleau 		} else if (!(flags & HCI_PROTO_DEFER)) {
1937b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
193820714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT;
1939b6a0dc82SMarcel Holtmann 
1940b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1941a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1942b6a0dc82SMarcel Holtmann 
194382781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
194482781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
194582781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1946b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1947b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1948b6a0dc82SMarcel Holtmann 
1949b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1950b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
195120714bfeSFrédéric Dalleau 		} else {
195220714bfeSFrédéric Dalleau 			conn->state = BT_CONNECT2;
195320714bfeSFrédéric Dalleau 			hci_proto_connect_cfm(conn, 0);
195420714bfeSFrédéric Dalleau 			hci_conn_put(conn);
1955b6a0dc82SMarcel Holtmann 		}
19561da177e4SLinus Torvalds 	} else {
19571da177e4SLinus Torvalds 		/* Connection rejected */
19581da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
19591da177e4SLinus Torvalds 
19601da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
19619f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1962a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
19631da177e4SLinus Torvalds 	}
19641da177e4SLinus Torvalds }
19651da177e4SLinus Torvalds 
1966f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
1967f0d6a0eaSMikel Astiz {
1968f0d6a0eaSMikel Astiz 	switch (err) {
1969f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
1970f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
1971f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
1972f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
1973f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
1974f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
1975f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
1976f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
1977f0d6a0eaSMikel Astiz 	default:
1978f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
1979f0d6a0eaSMikel Astiz 	}
1980f0d6a0eaSMikel Astiz }
1981f0d6a0eaSMikel Astiz 
19826039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19831da177e4SLinus Torvalds {
1984a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
198504837f64SMarcel Holtmann 	struct hci_conn *conn;
19861da177e4SLinus Torvalds 
19879f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
19881da177e4SLinus Torvalds 
19891da177e4SLinus Torvalds 	hci_dev_lock(hdev);
19901da177e4SLinus Torvalds 
199104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1992f7520543SJohan Hedberg 	if (!conn)
1993f7520543SJohan Hedberg 		goto unlock;
1994f7520543SJohan Hedberg 
199537d9ef76SJohan Hedberg 	if (ev->status == 0)
19961da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
19977d0db0a3SMarcel Holtmann 
1998b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1999b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
2000f0d6a0eaSMikel Astiz 		if (ev->status) {
200188c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
200288c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
2003f0d6a0eaSMikel Astiz 		} else {
2004f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
2005f0d6a0eaSMikel Astiz 
2006afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
2007f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
2008f0d6a0eaSMikel Astiz 		}
200937d9ef76SJohan Hedberg 	}
2010f7520543SJohan Hedberg 
201137d9ef76SJohan Hedberg 	if (ev->status == 0) {
20126ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
20136ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
20142950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
20151da177e4SLinus Torvalds 		hci_conn_del(conn);
201637d9ef76SJohan Hedberg 	}
20171da177e4SLinus Torvalds 
2018f7520543SJohan Hedberg unlock:
20191da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
20201da177e4SLinus Torvalds }
20211da177e4SLinus Torvalds 
20226039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2023a9de9248SMarcel Holtmann {
2024a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2025a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2026a9de9248SMarcel Holtmann 
20279f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2028a9de9248SMarcel Holtmann 
2029a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2030a9de9248SMarcel Holtmann 
2031a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2032d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2033d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2034d7556e20SWaldemar Rymarkiewicz 
2035765c2a96SJohan Hedberg 	if (!ev->status) {
2036aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
203751a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2038d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
203919f8def0SWaldemar Rymarkiewicz 		} else {
2040a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2041765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
204219f8def0SWaldemar Rymarkiewicz 		}
20432a611692SJohan Hedberg 	} else {
2044bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
2045bab73cb6SJohan Hedberg 				 ev->status);
20462a611692SJohan Hedberg 	}
2047a9de9248SMarcel Holtmann 
204851a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
204951a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2050a9de9248SMarcel Holtmann 
2051f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2052aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2053f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2054f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2055f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2056d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2057d7556e20SWaldemar Rymarkiewicz 				     &cp);
2058f8558555SMarcel Holtmann 		} else {
2059f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2060f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2061f8558555SMarcel Holtmann 			hci_conn_put(conn);
2062f8558555SMarcel Holtmann 		}
2063052b30b0SMarcel Holtmann 	} else {
2064a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2065a9de9248SMarcel Holtmann 
2066052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2067052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2068052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2069052b30b0SMarcel Holtmann 	}
2070052b30b0SMarcel Holtmann 
207151a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2072a9de9248SMarcel Holtmann 		if (!ev->status) {
2073a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2074f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2075f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2076d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2077d7556e20SWaldemar Rymarkiewicz 				     &cp);
2078a9de9248SMarcel Holtmann 		} else {
207951a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2080a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2081a9de9248SMarcel Holtmann 		}
2082a9de9248SMarcel Holtmann 	}
2083a9de9248SMarcel Holtmann 
2084d7556e20SWaldemar Rymarkiewicz unlock:
2085a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2086a9de9248SMarcel Holtmann }
2087a9de9248SMarcel Holtmann 
20886039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2089a9de9248SMarcel Holtmann {
2090127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2091127178d2SJohan Hedberg 	struct hci_conn *conn;
2092127178d2SJohan Hedberg 
2093a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2094a9de9248SMarcel Holtmann 
2095a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2096127178d2SJohan Hedberg 
2097127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2098127178d2SJohan Hedberg 
2099127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2100b644ba33SJohan Hedberg 
2101b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2102b644ba33SJohan Hedberg 		goto check_auth;
2103b644ba33SJohan Hedberg 
2104b644ba33SJohan Hedberg 	if (ev->status == 0)
2105b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2106b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2107b644ba33SJohan Hedberg 	else
2108b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2109b644ba33SJohan Hedberg 
2110b644ba33SJohan Hedberg check_auth:
211179c6c70cSJohan Hedberg 	if (!conn)
211279c6c70cSJohan Hedberg 		goto unlock;
211379c6c70cSJohan Hedberg 
211479c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
211579c6c70cSJohan Hedberg 		goto unlock;
211679c6c70cSJohan Hedberg 
211751a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2118127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2119127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2120127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2121127178d2SJohan Hedberg 	}
2122127178d2SJohan Hedberg 
212379c6c70cSJohan Hedberg unlock:
2124127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2125a9de9248SMarcel Holtmann }
2126a9de9248SMarcel Holtmann 
21276039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2128a9de9248SMarcel Holtmann {
2129a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2130a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2131a9de9248SMarcel Holtmann 
21329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2133a9de9248SMarcel Holtmann 
2134a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2135a9de9248SMarcel Holtmann 
2136a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2137a9de9248SMarcel Holtmann 	if (conn) {
2138a9de9248SMarcel Holtmann 		if (!ev->status) {
2139ae293196SMarcel Holtmann 			if (ev->encrypt) {
2140ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2141ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2142a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2143da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2144ae293196SMarcel Holtmann 			} else
2145a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2146a9de9248SMarcel Holtmann 		}
2147a9de9248SMarcel Holtmann 
214851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2149a9de9248SMarcel Holtmann 
2150a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2151bed71748SAndre Guedes 			hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
2152a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2153a7d7723aSGustavo Padovan 			goto unlock;
2154a7d7723aSGustavo Padovan 		}
2155a7d7723aSGustavo Padovan 
2156f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2157f8558555SMarcel Holtmann 			if (!ev->status)
2158f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2159f8558555SMarcel Holtmann 
2160f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2161f8558555SMarcel Holtmann 			hci_conn_put(conn);
2162f8558555SMarcel Holtmann 		} else
2163a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2164a9de9248SMarcel Holtmann 	}
2165a9de9248SMarcel Holtmann 
2166a7d7723aSGustavo Padovan unlock:
2167a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2168a9de9248SMarcel Holtmann }
2169a9de9248SMarcel Holtmann 
21706039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2171807deac2SGustavo Padovan 					     struct sk_buff *skb)
2172a9de9248SMarcel Holtmann {
2173a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2174a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2175a9de9248SMarcel Holtmann 
21769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2177a9de9248SMarcel Holtmann 
2178a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2179a9de9248SMarcel Holtmann 
2180a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2181a9de9248SMarcel Holtmann 	if (conn) {
2182a9de9248SMarcel Holtmann 		if (!ev->status)
2183a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2184a9de9248SMarcel Holtmann 
218551a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2186a9de9248SMarcel Holtmann 
2187a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2188a9de9248SMarcel Holtmann 	}
2189a9de9248SMarcel Holtmann 
2190a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2191a9de9248SMarcel Holtmann }
2192a9de9248SMarcel Holtmann 
21936039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2194807deac2SGustavo Padovan 				    struct sk_buff *skb)
2195a9de9248SMarcel Holtmann {
2196a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2197a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2198a9de9248SMarcel Holtmann 
21999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2200a9de9248SMarcel Holtmann 
2201a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2202a9de9248SMarcel Holtmann 
2203a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2204ccd556feSJohan Hedberg 	if (!conn)
2205ccd556feSJohan Hedberg 		goto unlock;
2206ccd556feSJohan Hedberg 
2207769be974SMarcel Holtmann 	if (!ev->status)
2208a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2209a9de9248SMarcel Holtmann 
2210ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2211ccd556feSJohan Hedberg 		goto unlock;
2212ccd556feSJohan Hedberg 
2213ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2214769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2215769be974SMarcel Holtmann 		cp.handle = ev->handle;
2216769be974SMarcel Holtmann 		cp.page = 0x01;
2217ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2218769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2219392599b9SJohan Hedberg 		goto unlock;
2220392599b9SJohan Hedberg 	}
2221392599b9SJohan Hedberg 
2222671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2223127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2224127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2225127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2226127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2227127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2228b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2229b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
223008c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2231b644ba33SJohan Hedberg 				      conn->dev_class);
2232392599b9SJohan Hedberg 
2233127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2234769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2235769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2236769be974SMarcel Holtmann 		hci_conn_put(conn);
2237769be974SMarcel Holtmann 	}
2238769be974SMarcel Holtmann 
2239ccd556feSJohan Hedberg unlock:
2240a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2241a9de9248SMarcel Holtmann }
2242a9de9248SMarcel Holtmann 
22436039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
22446039aa73SGustavo Padovan {
22456039aa73SGustavo Padovan 	BT_DBG("%s", hdev->name);
22466039aa73SGustavo Padovan }
22476039aa73SGustavo Padovan 
22486039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2249807deac2SGustavo Padovan 				       struct sk_buff *skb)
2250a9de9248SMarcel Holtmann {
2251a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2252a9de9248SMarcel Holtmann }
2253a9de9248SMarcel Holtmann 
22546039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2255a9de9248SMarcel Holtmann {
2256a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2257a9de9248SMarcel Holtmann 	__u16 opcode;
2258a9de9248SMarcel Holtmann 
2259a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2260a9de9248SMarcel Holtmann 
2261a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2262a9de9248SMarcel Holtmann 
2263a9de9248SMarcel Holtmann 	switch (opcode) {
2264a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2265a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2266a9de9248SMarcel Holtmann 		break;
2267a9de9248SMarcel Holtmann 
22684d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
22694d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
22704d93483bSAndre Guedes 		break;
22714d93483bSAndre Guedes 
2272a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2273a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2274a9de9248SMarcel Holtmann 		break;
2275a9de9248SMarcel Holtmann 
2276a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2277a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2278a9de9248SMarcel Holtmann 		break;
2279a9de9248SMarcel Holtmann 
2280a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2281a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2282a9de9248SMarcel Holtmann 		break;
2283a9de9248SMarcel Holtmann 
2284e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2285e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2286e4e8e37cSMarcel Holtmann 		break;
2287e4e8e37cSMarcel Holtmann 
2288a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2289a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2290a9de9248SMarcel Holtmann 		break;
2291a9de9248SMarcel Holtmann 
2292e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2293e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2294e4e8e37cSMarcel Holtmann 		break;
2295e4e8e37cSMarcel Holtmann 
2296e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2297e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2298e4e8e37cSMarcel Holtmann 		break;
2299e4e8e37cSMarcel Holtmann 
2300a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2301a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2302a9de9248SMarcel Holtmann 		break;
2303a9de9248SMarcel Holtmann 
2304a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2305a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2306a9de9248SMarcel Holtmann 		break;
2307a9de9248SMarcel Holtmann 
2308a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2309a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2310a9de9248SMarcel Holtmann 		break;
2311a9de9248SMarcel Holtmann 
2312a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2313a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2314a9de9248SMarcel Holtmann 		break;
2315a9de9248SMarcel Holtmann 
2316a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2317a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2318a9de9248SMarcel Holtmann 		break;
2319a9de9248SMarcel Holtmann 
2320a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2321a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2322a9de9248SMarcel Holtmann 		break;
2323a9de9248SMarcel Holtmann 
2324a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2325a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2326a9de9248SMarcel Holtmann 		break;
2327a9de9248SMarcel Holtmann 
2328a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2329a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2330a9de9248SMarcel Holtmann 		break;
2331a9de9248SMarcel Holtmann 
2332a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2333a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2334a9de9248SMarcel Holtmann 		break;
2335a9de9248SMarcel Holtmann 
2336a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2337a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2338a9de9248SMarcel Holtmann 		break;
2339a9de9248SMarcel Holtmann 
2340a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2341a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2342a9de9248SMarcel Holtmann 		break;
2343a9de9248SMarcel Holtmann 
2344333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2345333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2346333140b5SMarcel Holtmann 		break;
2347333140b5SMarcel Holtmann 
2348a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2349a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2350a9de9248SMarcel Holtmann 		break;
2351a9de9248SMarcel Holtmann 
2352a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2353a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2354a9de9248SMarcel Holtmann 		break;
2355a9de9248SMarcel Holtmann 
2356a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2357a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2358a9de9248SMarcel Holtmann 		break;
2359a9de9248SMarcel Holtmann 
2360971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2361971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2362971e3a4bSAndre Guedes 		break;
2363971e3a4bSAndre Guedes 
2364a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2365a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2366a9de9248SMarcel Holtmann 		break;
2367a9de9248SMarcel Holtmann 
2368a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2369a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2370a9de9248SMarcel Holtmann 		break;
2371a9de9248SMarcel Holtmann 
2372350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2373350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2374350ee4cfSAndrei Emeltchenko 		break;
2375350ee4cfSAndrei Emeltchenko 
237623bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
237723bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
237823bb5763SJohan Hedberg 		break;
237923bb5763SJohan Hedberg 
23801e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
23811e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
23821e89cffbSAndrei Emeltchenko 		break;
23831e89cffbSAndrei Emeltchenko 
2384928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2385928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2386928abaa7SAndrei Emeltchenko 		break;
2387928abaa7SAndrei Emeltchenko 
2388903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2389903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2390903e4541SAndrei Emeltchenko 		break;
2391903e4541SAndrei Emeltchenko 
2392b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2393b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2394b0916ea0SJohan Hedberg 		break;
2395b0916ea0SJohan Hedberg 
2396d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2397d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2398d5859e22SJohan Hedberg 		break;
2399d5859e22SJohan Hedberg 
2400d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2401d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2402d5859e22SJohan Hedberg 		break;
2403d5859e22SJohan Hedberg 
2404d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2405d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2406d5859e22SJohan Hedberg 		break;
2407d5859e22SJohan Hedberg 
2408d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2409d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2410d5859e22SJohan Hedberg 		break;
2411d5859e22SJohan Hedberg 
2412980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2413980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2414980e1a53SJohan Hedberg 		break;
2415980e1a53SJohan Hedberg 
2416980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2417980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2418980e1a53SJohan Hedberg 		break;
2419980e1a53SJohan Hedberg 
2420c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2421c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2422c35938b2SSzymon Janc 		break;
2423c35938b2SSzymon Janc 
24246ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
24256ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
24266ed58ec5SVille Tervo 		break;
24276ed58ec5SVille Tervo 
242860e77321SJohan Hedberg 	case HCI_OP_LE_READ_LOCAL_FEATURES:
242960e77321SJohan Hedberg 		hci_cc_le_read_local_features(hdev, skb);
243060e77321SJohan Hedberg 		break;
243160e77321SJohan Hedberg 
24328fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
24338fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
24348fa19098SJohan Hedberg 		break;
24358fa19098SJohan Hedberg 
2436e36b04c8SJohan Hedberg 	case HCI_OP_LE_SET_EVENT_MASK:
2437e36b04c8SJohan Hedberg 		hci_cc_le_set_event_mask(hdev, skb);
2438e36b04c8SJohan Hedberg 		break;
2439e36b04c8SJohan Hedberg 
2440a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2441a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2442a5c29683SJohan Hedberg 		break;
2443a5c29683SJohan Hedberg 
2444a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2445a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2446a5c29683SJohan Hedberg 		break;
2447a5c29683SJohan Hedberg 
24481143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
24491143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
24501143d458SBrian Gix 		break;
24511143d458SBrian Gix 
24521143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
24531143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
245416cde993SSzymon Janc 		break;
245507f7fa5dSAndre Guedes 
245607f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
245707f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
24581143d458SBrian Gix 		break;
24591143d458SBrian Gix 
2460c1d5dc4aSJohan Hedberg 	case HCI_OP_LE_SET_ADV_ENABLE:
2461c1d5dc4aSJohan Hedberg 		hci_cc_le_set_adv_enable(hdev, skb);
2462c1d5dc4aSJohan Hedberg 		break;
2463c1d5dc4aSJohan Hedberg 
2464eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2465eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2466eb9d91f5SAndre Guedes 		break;
2467eb9d91f5SAndre Guedes 
2468cf1d081fSJohan Hedberg 	case HCI_OP_LE_READ_WHITE_LIST_SIZE:
2469cf1d081fSJohan Hedberg 		hci_cc_le_read_white_list_size(hdev, skb);
2470cf1d081fSJohan Hedberg 		break;
2471cf1d081fSJohan Hedberg 
2472a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2473a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2474a7a595f6SVinicius Costa Gomes 		break;
2475a7a595f6SVinicius Costa Gomes 
2476a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2477a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2478a7a595f6SVinicius Costa Gomes 		break;
2479a7a595f6SVinicius Costa Gomes 
24809b008c04SJohan Hedberg 	case HCI_OP_LE_READ_SUPPORTED_STATES:
24819b008c04SJohan Hedberg 		hci_cc_le_read_supported_states(hdev, skb);
24829b008c04SJohan Hedberg 		break;
24839b008c04SJohan Hedberg 
2484f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2485f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2486f9b49306SAndre Guedes 		break;
2487f9b49306SAndre Guedes 
248893c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
248993c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
249093c284eeSAndrei Emeltchenko 		break;
249193c284eeSAndrei Emeltchenko 
2492a9de9248SMarcel Holtmann 	default:
24939f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2494a9de9248SMarcel Holtmann 		break;
2495a9de9248SMarcel Holtmann 	}
2496a9de9248SMarcel Holtmann 
24976bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
24986bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24996bd32326SVille Tervo 
2500dbccd791SSzymon Janc 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2501a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2502a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2503c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2504a9de9248SMarcel Holtmann 	}
2505a9de9248SMarcel Holtmann }
2506a9de9248SMarcel Holtmann 
25076039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2508a9de9248SMarcel Holtmann {
2509a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2510a9de9248SMarcel Holtmann 	__u16 opcode;
2511a9de9248SMarcel Holtmann 
2512a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2513a9de9248SMarcel Holtmann 
2514a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2515a9de9248SMarcel Holtmann 
2516a9de9248SMarcel Holtmann 	switch (opcode) {
2517a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2518a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2519a9de9248SMarcel Holtmann 		break;
2520a9de9248SMarcel Holtmann 
2521a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2522a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2523a9de9248SMarcel Holtmann 		break;
2524a9de9248SMarcel Holtmann 
2525a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2526a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2527a9de9248SMarcel Holtmann 		break;
2528a9de9248SMarcel Holtmann 
2529f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2530f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2531f8558555SMarcel Holtmann 		break;
2532f8558555SMarcel Holtmann 
2533f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2534f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2535f8558555SMarcel Holtmann 		break;
2536f8558555SMarcel Holtmann 
2537a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2538a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2539a9de9248SMarcel Holtmann 		break;
2540a9de9248SMarcel Holtmann 
2541769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2542769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2543769be974SMarcel Holtmann 		break;
2544769be974SMarcel Holtmann 
2545769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2546769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2547769be974SMarcel Holtmann 		break;
2548769be974SMarcel Holtmann 
2549a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2550a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2551a9de9248SMarcel Holtmann 		break;
2552a9de9248SMarcel Holtmann 
2553a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2554a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2555a9de9248SMarcel Holtmann 		break;
2556a9de9248SMarcel Holtmann 
2557a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2558a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2559a9de9248SMarcel Holtmann 		break;
2560a9de9248SMarcel Holtmann 
25618962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
256288c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
25638962ee74SJohan Hedberg 		break;
25648962ee74SJohan Hedberg 
2565fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2566fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2567fcd89c09SVille Tervo 		break;
2568fcd89c09SVille Tervo 
2569a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2570a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2571a7a595f6SVinicius Costa Gomes 		break;
2572a7a595f6SVinicius Costa Gomes 
2573a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2574a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2575a02226d6SAndrei Emeltchenko 		break;
2576a02226d6SAndrei Emeltchenko 
25770b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
25780b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
25790b26ab9dSAndrei Emeltchenko 		break;
25800b26ab9dSAndrei Emeltchenko 
25815ce66b59SAndrei Emeltchenko 	case HCI_OP_CREATE_LOGICAL_LINK:
25825ce66b59SAndrei Emeltchenko 		hci_cs_create_logical_link(hdev, ev->status);
25835ce66b59SAndrei Emeltchenko 		break;
25845ce66b59SAndrei Emeltchenko 
2585a9de9248SMarcel Holtmann 	default:
25869f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2587a9de9248SMarcel Holtmann 		break;
2588a9de9248SMarcel Holtmann 	}
2589a9de9248SMarcel Holtmann 
25906bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
25916bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
25926bd32326SVille Tervo 
259310572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2594a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2595a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2596c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2597a9de9248SMarcel Holtmann 	}
2598a9de9248SMarcel Holtmann }
2599a9de9248SMarcel Holtmann 
26006039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2601a9de9248SMarcel Holtmann {
2602a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2603a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2604a9de9248SMarcel Holtmann 
26059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2606a9de9248SMarcel Holtmann 
2607a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2608a9de9248SMarcel Holtmann 
2609a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2610a9de9248SMarcel Holtmann 	if (conn) {
2611a9de9248SMarcel Holtmann 		if (!ev->status) {
2612a9de9248SMarcel Holtmann 			if (ev->role)
2613a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2614a9de9248SMarcel Holtmann 			else
2615a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2616a9de9248SMarcel Holtmann 		}
2617a9de9248SMarcel Holtmann 
261851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2619a9de9248SMarcel Holtmann 
2620a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2621a9de9248SMarcel Holtmann 	}
2622a9de9248SMarcel Holtmann 
2623a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2624a9de9248SMarcel Holtmann }
2625a9de9248SMarcel Holtmann 
26266039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
26271da177e4SLinus Torvalds {
2628a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
26291da177e4SLinus Torvalds 	int i;
26301da177e4SLinus Torvalds 
263132ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
263232ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
263332ac5b9bSAndrei Emeltchenko 		return;
263432ac5b9bSAndrei Emeltchenko 	}
263532ac5b9bSAndrei Emeltchenko 
2636c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2637c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
26381da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
26391da177e4SLinus Torvalds 		return;
26401da177e4SLinus Torvalds 	}
26411da177e4SLinus Torvalds 
2642c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2643c5993de8SAndrei Emeltchenko 
2644613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2645613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
26461da177e4SLinus Torvalds 		struct hci_conn *conn;
26471da177e4SLinus Torvalds 		__u16  handle, count;
26481da177e4SLinus Torvalds 
2649613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2650613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
26511da177e4SLinus Torvalds 
26521da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2653f4280918SAndrei Emeltchenko 		if (!conn)
2654f4280918SAndrei Emeltchenko 			continue;
2655f4280918SAndrei Emeltchenko 
26561da177e4SLinus Torvalds 		conn->sent -= count;
26571da177e4SLinus Torvalds 
2658f4280918SAndrei Emeltchenko 		switch (conn->type) {
2659f4280918SAndrei Emeltchenko 		case ACL_LINK:
266070f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
266170f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
26621da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2663f4280918SAndrei Emeltchenko 			break;
2664f4280918SAndrei Emeltchenko 
2665f4280918SAndrei Emeltchenko 		case LE_LINK:
26666ed58ec5SVille Tervo 			if (hdev->le_pkts) {
26676ed58ec5SVille Tervo 				hdev->le_cnt += count;
26686ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
26696ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
26706ed58ec5SVille Tervo 			} else {
26716ed58ec5SVille Tervo 				hdev->acl_cnt += count;
26726ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
26736ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
26746ed58ec5SVille Tervo 			}
2675f4280918SAndrei Emeltchenko 			break;
2676f4280918SAndrei Emeltchenko 
2677f4280918SAndrei Emeltchenko 		case SCO_LINK:
267870f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
267970f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
26805b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2681f4280918SAndrei Emeltchenko 			break;
2682f4280918SAndrei Emeltchenko 
2683f4280918SAndrei Emeltchenko 		default:
2684f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2685f4280918SAndrei Emeltchenko 			break;
26861da177e4SLinus Torvalds 		}
26871da177e4SLinus Torvalds 	}
2688a9de9248SMarcel Holtmann 
26893eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
26901da177e4SLinus Torvalds }
26911da177e4SLinus Torvalds 
269276ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
269376ef7cf7SAndrei Emeltchenko 						 __u16 handle)
269476ef7cf7SAndrei Emeltchenko {
269576ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
269676ef7cf7SAndrei Emeltchenko 
269776ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
269876ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
269976ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
270076ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
270176ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
270276ef7cf7SAndrei Emeltchenko 		if (chan)
270376ef7cf7SAndrei Emeltchenko 			return chan->conn;
270476ef7cf7SAndrei Emeltchenko 		break;
270576ef7cf7SAndrei Emeltchenko 	default:
270676ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
270776ef7cf7SAndrei Emeltchenko 		break;
270876ef7cf7SAndrei Emeltchenko 	}
270976ef7cf7SAndrei Emeltchenko 
271076ef7cf7SAndrei Emeltchenko 	return NULL;
271176ef7cf7SAndrei Emeltchenko }
271276ef7cf7SAndrei Emeltchenko 
27136039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
271425e89e99SAndrei Emeltchenko {
271525e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
271625e89e99SAndrei Emeltchenko 	int i;
271725e89e99SAndrei Emeltchenko 
271825e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
271925e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
272025e89e99SAndrei Emeltchenko 		return;
272125e89e99SAndrei Emeltchenko 	}
272225e89e99SAndrei Emeltchenko 
272325e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
272425e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
272525e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
272625e89e99SAndrei Emeltchenko 		return;
272725e89e99SAndrei Emeltchenko 	}
272825e89e99SAndrei Emeltchenko 
272925e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
273025e89e99SAndrei Emeltchenko 	       ev->num_hndl);
273125e89e99SAndrei Emeltchenko 
273225e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
273325e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
273476ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
273525e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
273625e89e99SAndrei Emeltchenko 
273725e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
273825e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
273925e89e99SAndrei Emeltchenko 
274076ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
274125e89e99SAndrei Emeltchenko 		if (!conn)
274225e89e99SAndrei Emeltchenko 			continue;
274325e89e99SAndrei Emeltchenko 
274425e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
274525e89e99SAndrei Emeltchenko 
274625e89e99SAndrei Emeltchenko 		switch (conn->type) {
274725e89e99SAndrei Emeltchenko 		case ACL_LINK:
2748bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
274925e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
275025e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
275125e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
275225e89e99SAndrei Emeltchenko 			break;
275325e89e99SAndrei Emeltchenko 
275425e89e99SAndrei Emeltchenko 		default:
275525e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
275625e89e99SAndrei Emeltchenko 			break;
275725e89e99SAndrei Emeltchenko 		}
275825e89e99SAndrei Emeltchenko 	}
275925e89e99SAndrei Emeltchenko 
276025e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
276125e89e99SAndrei Emeltchenko }
276225e89e99SAndrei Emeltchenko 
27636039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
27641da177e4SLinus Torvalds {
2765a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
276604837f64SMarcel Holtmann 	struct hci_conn *conn;
27671da177e4SLinus Torvalds 
27689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
27691da177e4SLinus Torvalds 
27701da177e4SLinus Torvalds 	hci_dev_lock(hdev);
27711da177e4SLinus Torvalds 
277204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
277304837f64SMarcel Holtmann 	if (conn) {
277404837f64SMarcel Holtmann 		conn->mode = ev->mode;
277504837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
277604837f64SMarcel Holtmann 
27778fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
27788fc9ced3SGustavo Padovan 					&conn->flags)) {
277904837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
278058a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
278104837f64SMarcel Holtmann 			else
278258a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
278304837f64SMarcel Holtmann 		}
2784e73439d8SMarcel Holtmann 
278551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2786e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
278704837f64SMarcel Holtmann 	}
278804837f64SMarcel Holtmann 
278904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
279004837f64SMarcel Holtmann }
279104837f64SMarcel Holtmann 
27926039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
27931da177e4SLinus Torvalds {
2794052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2795052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2796052b30b0SMarcel Holtmann 
2797a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2798052b30b0SMarcel Holtmann 
2799052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2800052b30b0SMarcel Holtmann 
2801052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2802b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2803b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2804b6f98044SWaldemar Rymarkiewicz 
2805b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2806052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2807052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2808052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2809052b30b0SMarcel Holtmann 	}
2810052b30b0SMarcel Holtmann 
2811a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
281203b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
281303b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2814a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2815a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2816a770bb5aSWaldemar Rymarkiewicz 
2817a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2818a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2819a770bb5aSWaldemar Rymarkiewicz 		else
2820a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2821a770bb5aSWaldemar Rymarkiewicz 
2822744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2823a770bb5aSWaldemar Rymarkiewicz 	}
2824980e1a53SJohan Hedberg 
2825b6f98044SWaldemar Rymarkiewicz unlock:
2826052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
28271da177e4SLinus Torvalds }
28281da177e4SLinus Torvalds 
28296039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
28301da177e4SLinus Torvalds {
283155ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
283255ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
283355ed8ca1SJohan Hedberg 	struct hci_conn *conn;
283455ed8ca1SJohan Hedberg 	struct link_key *key;
283555ed8ca1SJohan Hedberg 
2836a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
283755ed8ca1SJohan Hedberg 
2838a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
283955ed8ca1SJohan Hedberg 		return;
284055ed8ca1SJohan Hedberg 
284155ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
284255ed8ca1SJohan Hedberg 
284355ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
284455ed8ca1SJohan Hedberg 	if (!key) {
28456ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
28466ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
284755ed8ca1SJohan Hedberg 		goto not_found;
284855ed8ca1SJohan Hedberg 	}
284955ed8ca1SJohan Hedberg 
28506ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
28516ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
285255ed8ca1SJohan Hedberg 
2853a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2854b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
285555ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
285655ed8ca1SJohan Hedberg 		goto not_found;
285755ed8ca1SJohan Hedberg 	}
285855ed8ca1SJohan Hedberg 
285955ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
286060b83f57SWaldemar Rymarkiewicz 	if (conn) {
286160b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2862807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
286355ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
286455ed8ca1SJohan Hedberg 			goto not_found;
286555ed8ca1SJohan Hedberg 		}
286655ed8ca1SJohan Hedberg 
286760b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
286860b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
28698fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
28708fc9ced3SGustavo Padovan 			       hdev->name);
287160b83f57SWaldemar Rymarkiewicz 			goto not_found;
287260b83f57SWaldemar Rymarkiewicz 		}
287360b83f57SWaldemar Rymarkiewicz 
287460b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
287560b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
287660b83f57SWaldemar Rymarkiewicz 	}
287760b83f57SWaldemar Rymarkiewicz 
287855ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
28799b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
288055ed8ca1SJohan Hedberg 
288155ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
288255ed8ca1SJohan Hedberg 
288355ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
288455ed8ca1SJohan Hedberg 
288555ed8ca1SJohan Hedberg 	return;
288655ed8ca1SJohan Hedberg 
288755ed8ca1SJohan Hedberg not_found:
288855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
288955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
28901da177e4SLinus Torvalds }
28911da177e4SLinus Torvalds 
28926039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
28931da177e4SLinus Torvalds {
2894052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2895052b30b0SMarcel Holtmann 	struct hci_conn *conn;
289655ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2897052b30b0SMarcel Holtmann 
2898a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2899052b30b0SMarcel Holtmann 
2900052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2901052b30b0SMarcel Holtmann 
2902052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2903052b30b0SMarcel Holtmann 	if (conn) {
2904052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2905052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2906980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
290713d39315SWaldemar Rymarkiewicz 
290813d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
290913d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
291013d39315SWaldemar Rymarkiewicz 
2911052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2912052b30b0SMarcel Holtmann 	}
2913052b30b0SMarcel Holtmann 
2914a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2915d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
291655ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
291755ed8ca1SJohan Hedberg 
2918052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
29191da177e4SLinus Torvalds }
29201da177e4SLinus Torvalds 
29216039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
292204837f64SMarcel Holtmann {
2923a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
292404837f64SMarcel Holtmann 	struct hci_conn *conn;
292504837f64SMarcel Holtmann 
29269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
292704837f64SMarcel Holtmann 
292804837f64SMarcel Holtmann 	hci_dev_lock(hdev);
292904837f64SMarcel Holtmann 
293004837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
29311da177e4SLinus Torvalds 	if (conn && !ev->status) {
29321da177e4SLinus Torvalds 		struct inquiry_entry *ie;
29331da177e4SLinus Torvalds 
2934cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2935cc11b9c1SAndrei Emeltchenko 		if (ie) {
29361da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
29371da177e4SLinus Torvalds 			ie->timestamp = jiffies;
29381da177e4SLinus Torvalds 		}
29391da177e4SLinus Torvalds 	}
29401da177e4SLinus Torvalds 
29411da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
29421da177e4SLinus Torvalds }
29431da177e4SLinus Torvalds 
29446039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2945a8746417SMarcel Holtmann {
2946a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2947a8746417SMarcel Holtmann 	struct hci_conn *conn;
2948a8746417SMarcel Holtmann 
29499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2950a8746417SMarcel Holtmann 
2951a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2952a8746417SMarcel Holtmann 
2953a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2954a8746417SMarcel Holtmann 	if (conn && !ev->status)
2955a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2956a8746417SMarcel Holtmann 
2957a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2958a8746417SMarcel Holtmann }
2959a8746417SMarcel Holtmann 
29606039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
296185a1e930SMarcel Holtmann {
2962a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
296385a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
296485a1e930SMarcel Holtmann 
296585a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
296685a1e930SMarcel Holtmann 
296785a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
296885a1e930SMarcel Holtmann 
2969cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2970cc11b9c1SAndrei Emeltchenko 	if (ie) {
297185a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
297285a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
297385a1e930SMarcel Holtmann 	}
297485a1e930SMarcel Holtmann 
297585a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
297685a1e930SMarcel Holtmann }
297785a1e930SMarcel Holtmann 
29786039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2979807deac2SGustavo Padovan 					     struct sk_buff *skb)
2980a9de9248SMarcel Holtmann {
2981a9de9248SMarcel Holtmann 	struct inquiry_data data;
2982a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2983388fc8faSJohan Hedberg 	bool name_known, ssp;
2984a9de9248SMarcel Holtmann 
2985a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2986a9de9248SMarcel Holtmann 
2987a9de9248SMarcel Holtmann 	if (!num_rsp)
2988a9de9248SMarcel Holtmann 		return;
2989a9de9248SMarcel Holtmann 
29901519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
29911519cc17SAndre Guedes 		return;
29921519cc17SAndre Guedes 
2993a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2994a9de9248SMarcel Holtmann 
2995a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2996138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2997138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2998a9de9248SMarcel Holtmann 
2999e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3000a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3001a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3002a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3003a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3004a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3005a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3006a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
300741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
30083175405bSJohan Hedberg 
30093175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3010388fc8faSJohan Hedberg 							      false, &ssp);
301148264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3012e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3013388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3014a9de9248SMarcel Holtmann 		}
3015a9de9248SMarcel Holtmann 	} else {
3016a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3017a9de9248SMarcel Holtmann 
3018e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3019a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3020a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3021a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3022a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3023a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3024a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3025a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
302641a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
30273175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3028388fc8faSJohan Hedberg 							      false, &ssp);
302948264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3030e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3031388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3032a9de9248SMarcel Holtmann 		}
3033a9de9248SMarcel Holtmann 	}
3034a9de9248SMarcel Holtmann 
3035a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3036a9de9248SMarcel Holtmann }
3037a9de9248SMarcel Holtmann 
30386039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3039807deac2SGustavo Padovan 					struct sk_buff *skb)
3040a9de9248SMarcel Holtmann {
304141a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
304241a96212SMarcel Holtmann 	struct hci_conn *conn;
304341a96212SMarcel Holtmann 
3044a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
304541a96212SMarcel Holtmann 
304641a96212SMarcel Holtmann 	hci_dev_lock(hdev);
304741a96212SMarcel Holtmann 
304841a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3049ccd556feSJohan Hedberg 	if (!conn)
3050ccd556feSJohan Hedberg 		goto unlock;
3051ccd556feSJohan Hedberg 
3052769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
305341a96212SMarcel Holtmann 		struct inquiry_entry *ie;
305441a96212SMarcel Holtmann 
3055cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3056cc11b9c1SAndrei Emeltchenko 		if (ie)
305702b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
305841a96212SMarcel Holtmann 
305902b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
306058a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
306141a96212SMarcel Holtmann 	}
306241a96212SMarcel Holtmann 
3063ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3064ccd556feSJohan Hedberg 		goto unlock;
3065ccd556feSJohan Hedberg 
3066671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3067127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3068127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3069127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3070127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3071127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3072b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3073b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
307408c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
3075b644ba33SJohan Hedberg 				      conn->dev_class);
3076392599b9SJohan Hedberg 
3077127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3078769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3079769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
3080769be974SMarcel Holtmann 		hci_conn_put(conn);
3081769be974SMarcel Holtmann 	}
3082769be974SMarcel Holtmann 
3083ccd556feSJohan Hedberg unlock:
308441a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3085a9de9248SMarcel Holtmann }
3086a9de9248SMarcel Holtmann 
30876039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3088807deac2SGustavo Padovan 				       struct sk_buff *skb)
3089a9de9248SMarcel Holtmann {
3090b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3091b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3092b6a0dc82SMarcel Holtmann 
30939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3094b6a0dc82SMarcel Holtmann 
3095b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3096b6a0dc82SMarcel Holtmann 
3097b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
30989dc0a3afSMarcel Holtmann 	if (!conn) {
30999dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
31009dc0a3afSMarcel Holtmann 			goto unlock;
31019dc0a3afSMarcel Holtmann 
31029dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3103b6a0dc82SMarcel Holtmann 		if (!conn)
3104b6a0dc82SMarcel Holtmann 			goto unlock;
3105b6a0dc82SMarcel Holtmann 
31069dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
31079dc0a3afSMarcel Holtmann 	}
31089dc0a3afSMarcel Holtmann 
3109732547f9SMarcel Holtmann 	switch (ev->status) {
3110732547f9SMarcel Holtmann 	case 0x00:
3111732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3112732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3113732547f9SMarcel Holtmann 
31149eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
3115732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3116732547f9SMarcel Holtmann 		break;
3117732547f9SMarcel Holtmann 
3118705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3119732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
31201038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3121732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
3122732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
3123efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3124efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
3125efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
3126efc7688bSMarcel Holtmann 			goto unlock;
3127efc7688bSMarcel Holtmann 		}
3128732547f9SMarcel Holtmann 		/* fall through */
3129efc7688bSMarcel Holtmann 
3130732547f9SMarcel Holtmann 	default:
3131b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3132732547f9SMarcel Holtmann 		break;
3133732547f9SMarcel Holtmann 	}
3134b6a0dc82SMarcel Holtmann 
3135b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3136b6a0dc82SMarcel Holtmann 	if (ev->status)
3137b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3138b6a0dc82SMarcel Holtmann 
3139b6a0dc82SMarcel Holtmann unlock:
3140b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3141a9de9248SMarcel Holtmann }
3142a9de9248SMarcel Holtmann 
31436039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
3144a9de9248SMarcel Holtmann {
3145a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3146a9de9248SMarcel Holtmann }
3147a9de9248SMarcel Holtmann 
31486039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
314904837f64SMarcel Holtmann {
3150a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
315104837f64SMarcel Holtmann 
31529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
315304837f64SMarcel Holtmann }
315404837f64SMarcel Holtmann 
31556039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3156807deac2SGustavo Padovan 					    struct sk_buff *skb)
3157a9de9248SMarcel Holtmann {
3158a9de9248SMarcel Holtmann 	struct inquiry_data data;
3159a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3160a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
31619d939d94SVishal Agarwal 	size_t eir_len;
3162a9de9248SMarcel Holtmann 
3163a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3164a9de9248SMarcel Holtmann 
3165a9de9248SMarcel Holtmann 	if (!num_rsp)
3166a9de9248SMarcel Holtmann 		return;
3167a9de9248SMarcel Holtmann 
31681519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
31691519cc17SAndre Guedes 		return;
31701519cc17SAndre Guedes 
3171a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3172a9de9248SMarcel Holtmann 
3173e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3174388fc8faSJohan Hedberg 		bool name_known, ssp;
3175561aafbcSJohan Hedberg 
3176a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3177a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3178a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3179a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3180a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3181a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3182a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
318341a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3184561aafbcSJohan Hedberg 
3185a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
31864ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
31874ddb1930SJohan Hedberg 						       sizeof(info->data),
31884ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3189561aafbcSJohan Hedberg 		else
3190561aafbcSJohan Hedberg 			name_known = true;
3191561aafbcSJohan Hedberg 
3192388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3193388fc8faSJohan Hedberg 						      &ssp);
31949d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
319548264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
319604124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
31979d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3198a9de9248SMarcel Holtmann 	}
3199a9de9248SMarcel Holtmann 
3200a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3201a9de9248SMarcel Holtmann }
3202a9de9248SMarcel Holtmann 
32031c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
32041c2e0041SJohan Hedberg 					 struct sk_buff *skb)
32051c2e0041SJohan Hedberg {
32061c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
32071c2e0041SJohan Hedberg 	struct hci_conn *conn;
32081c2e0041SJohan Hedberg 
32099f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
32101c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
32111c2e0041SJohan Hedberg 
32121c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
32131c2e0041SJohan Hedberg 
32141c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
32151c2e0041SJohan Hedberg 	if (!conn)
32161c2e0041SJohan Hedberg 		goto unlock;
32171c2e0041SJohan Hedberg 
32181c2e0041SJohan Hedberg 	if (!ev->status)
32191c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
32201c2e0041SJohan Hedberg 
32211c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
32221c2e0041SJohan Hedberg 
32231c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
3224bed71748SAndre Guedes 		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
32251c2e0041SJohan Hedberg 		hci_conn_put(conn);
32261c2e0041SJohan Hedberg 		goto unlock;
32271c2e0041SJohan Hedberg 	}
32281c2e0041SJohan Hedberg 
32291c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
32301c2e0041SJohan Hedberg 		if (!ev->status)
32311c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
32321c2e0041SJohan Hedberg 
32331c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
32341c2e0041SJohan Hedberg 		hci_conn_put(conn);
32351c2e0041SJohan Hedberg 	} else {
32361c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
32371c2e0041SJohan Hedberg 
32381c2e0041SJohan Hedberg 		hci_conn_hold(conn);
32391c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
32401c2e0041SJohan Hedberg 		hci_conn_put(conn);
32411c2e0041SJohan Hedberg 	}
32421c2e0041SJohan Hedberg 
32431c2e0041SJohan Hedberg unlock:
32441c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
32451c2e0041SJohan Hedberg }
32461c2e0041SJohan Hedberg 
32476039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
324817fa4b9dSJohan Hedberg {
324917fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
325017fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
325117fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
325217fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
325317fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
325417fa4b9dSJohan Hedberg 			return 0x02;
325517fa4b9dSJohan Hedberg 		else
325617fa4b9dSJohan Hedberg 			return 0x03;
325717fa4b9dSJohan Hedberg 	}
325817fa4b9dSJohan Hedberg 
325917fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
326017fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
326158797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
326217fa4b9dSJohan Hedberg 
326317fa4b9dSJohan Hedberg 	return conn->auth_type;
326417fa4b9dSJohan Hedberg }
326517fa4b9dSJohan Hedberg 
32666039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
32670493684eSMarcel Holtmann {
32680493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
32690493684eSMarcel Holtmann 	struct hci_conn *conn;
32700493684eSMarcel Holtmann 
32710493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
32720493684eSMarcel Holtmann 
32730493684eSMarcel Holtmann 	hci_dev_lock(hdev);
32740493684eSMarcel Holtmann 
32750493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
327603b555e1SJohan Hedberg 	if (!conn)
327703b555e1SJohan Hedberg 		goto unlock;
327803b555e1SJohan Hedberg 
32790493684eSMarcel Holtmann 	hci_conn_hold(conn);
32800493684eSMarcel Holtmann 
3281a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
328203b555e1SJohan Hedberg 		goto unlock;
328303b555e1SJohan Hedberg 
3284a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
328503b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
328617fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
328717fa4b9dSJohan Hedberg 
328817fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
32897a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
32907a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
32917a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
32927a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
32937cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
32947cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
329517fa4b9dSJohan Hedberg 
32968fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
32978fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3298ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3299ce85ee13SSzymon Janc 		else
3300ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3301ce85ee13SSzymon Janc 
330217fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
330317fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
330403b555e1SJohan Hedberg 	} else {
330503b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
330603b555e1SJohan Hedberg 
330703b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
33089f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
330903b555e1SJohan Hedberg 
331003b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
331103b555e1SJohan Hedberg 			     sizeof(cp), &cp);
331203b555e1SJohan Hedberg 	}
331303b555e1SJohan Hedberg 
331403b555e1SJohan Hedberg unlock:
331503b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
331603b555e1SJohan Hedberg }
331703b555e1SJohan Hedberg 
33186039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
331903b555e1SJohan Hedberg {
332003b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
332103b555e1SJohan Hedberg 	struct hci_conn *conn;
332203b555e1SJohan Hedberg 
332303b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
332403b555e1SJohan Hedberg 
332503b555e1SJohan Hedberg 	hci_dev_lock(hdev);
332603b555e1SJohan Hedberg 
332703b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
332803b555e1SJohan Hedberg 	if (!conn)
332903b555e1SJohan Hedberg 		goto unlock;
333003b555e1SJohan Hedberg 
333103b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
333203b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
333358a681efSJohan Hedberg 	if (ev->oob_data)
333458a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
333503b555e1SJohan Hedberg 
333603b555e1SJohan Hedberg unlock:
33370493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
33380493684eSMarcel Holtmann }
33390493684eSMarcel Holtmann 
33406039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3341a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3342a5c29683SJohan Hedberg {
3343a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
334455bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
33457a828908SJohan Hedberg 	struct hci_conn *conn;
3346a5c29683SJohan Hedberg 
3347a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3348a5c29683SJohan Hedberg 
3349a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3350a5c29683SJohan Hedberg 
3351a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
33527a828908SJohan Hedberg 		goto unlock;
33537a828908SJohan Hedberg 
33547a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
33557a828908SJohan Hedberg 	if (!conn)
33567a828908SJohan Hedberg 		goto unlock;
33577a828908SJohan Hedberg 
33587a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
33597a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
33607a828908SJohan Hedberg 
33617a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
33627a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
33637a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
33647a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
33657a828908SJohan Hedberg 	 * bit set. */
33667a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
33677a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
33687a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
33697a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
33707a828908SJohan Hedberg 		goto unlock;
33717a828908SJohan Hedberg 	}
33727a828908SJohan Hedberg 
33737a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
33747a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
33757a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
337655bc1a37SJohan Hedberg 
337755bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
337855bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
337955bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
338051a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
338155bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
338255bc1a37SJohan Hedberg 			confirm_hint = 1;
338355bc1a37SJohan Hedberg 			goto confirm;
338455bc1a37SJohan Hedberg 		}
338555bc1a37SJohan Hedberg 
33869f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
33879f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
33889f61656aSJohan Hedberg 
33899f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
33909f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
33919f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
33929f61656aSJohan Hedberg 			goto unlock;
33939f61656aSJohan Hedberg 		}
33949f61656aSJohan Hedberg 
33957a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
33967a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
33977a828908SJohan Hedberg 		goto unlock;
33987a828908SJohan Hedberg 	}
33997a828908SJohan Hedberg 
340055bc1a37SJohan Hedberg confirm:
3401272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
340255bc1a37SJohan Hedberg 				  confirm_hint);
3403a5c29683SJohan Hedberg 
34047a828908SJohan Hedberg unlock:
3405a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3406a5c29683SJohan Hedberg }
3407a5c29683SJohan Hedberg 
34086039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
34091143d458SBrian Gix 					 struct sk_buff *skb)
34101143d458SBrian Gix {
34111143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
34121143d458SBrian Gix 
34131143d458SBrian Gix 	BT_DBG("%s", hdev->name);
34141143d458SBrian Gix 
3415a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3416272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
34171143d458SBrian Gix }
34181143d458SBrian Gix 
341992a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
342092a25256SJohan Hedberg 					struct sk_buff *skb)
342192a25256SJohan Hedberg {
342292a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
342392a25256SJohan Hedberg 	struct hci_conn *conn;
342492a25256SJohan Hedberg 
342592a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
342692a25256SJohan Hedberg 
342792a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
342892a25256SJohan Hedberg 	if (!conn)
342992a25256SJohan Hedberg 		return;
343092a25256SJohan Hedberg 
343192a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
343292a25256SJohan Hedberg 	conn->passkey_entered = 0;
343392a25256SJohan Hedberg 
343492a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
343592a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
343692a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
343792a25256SJohan Hedberg 					 conn->passkey_entered);
343892a25256SJohan Hedberg }
343992a25256SJohan Hedberg 
344092a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
344192a25256SJohan Hedberg {
344292a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
344392a25256SJohan Hedberg 	struct hci_conn *conn;
344492a25256SJohan Hedberg 
344592a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
344692a25256SJohan Hedberg 
344792a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
344892a25256SJohan Hedberg 	if (!conn)
344992a25256SJohan Hedberg 		return;
345092a25256SJohan Hedberg 
345192a25256SJohan Hedberg 	switch (ev->type) {
345292a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
345392a25256SJohan Hedberg 		conn->passkey_entered = 0;
345492a25256SJohan Hedberg 		return;
345592a25256SJohan Hedberg 
345692a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
345792a25256SJohan Hedberg 		conn->passkey_entered++;
345892a25256SJohan Hedberg 		break;
345992a25256SJohan Hedberg 
346092a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
346192a25256SJohan Hedberg 		conn->passkey_entered--;
346292a25256SJohan Hedberg 		break;
346392a25256SJohan Hedberg 
346492a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
346592a25256SJohan Hedberg 		conn->passkey_entered = 0;
346692a25256SJohan Hedberg 		break;
346792a25256SJohan Hedberg 
346892a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
346992a25256SJohan Hedberg 		return;
347092a25256SJohan Hedberg 	}
347192a25256SJohan Hedberg 
347292a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
347392a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
347492a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
347592a25256SJohan Hedberg 					 conn->passkey_entered);
347692a25256SJohan Hedberg }
347792a25256SJohan Hedberg 
34786039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3479807deac2SGustavo Padovan 					 struct sk_buff *skb)
34800493684eSMarcel Holtmann {
34810493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
34820493684eSMarcel Holtmann 	struct hci_conn *conn;
34830493684eSMarcel Holtmann 
34840493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
34850493684eSMarcel Holtmann 
34860493684eSMarcel Holtmann 	hci_dev_lock(hdev);
34870493684eSMarcel Holtmann 
34880493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
34892a611692SJohan Hedberg 	if (!conn)
34902a611692SJohan Hedberg 		goto unlock;
34912a611692SJohan Hedberg 
34922a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
34932a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
34942a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
34952a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
34962a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3497fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3498bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3499bab73cb6SJohan Hedberg 				 ev->status);
35002a611692SJohan Hedberg 
35010493684eSMarcel Holtmann 	hci_conn_put(conn);
35020493684eSMarcel Holtmann 
35032a611692SJohan Hedberg unlock:
35040493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
35050493684eSMarcel Holtmann }
35060493684eSMarcel Holtmann 
35076039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3508807deac2SGustavo Padovan 					 struct sk_buff *skb)
350941a96212SMarcel Holtmann {
351041a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
351141a96212SMarcel Holtmann 	struct inquiry_entry *ie;
351241a96212SMarcel Holtmann 
351341a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
351441a96212SMarcel Holtmann 
351541a96212SMarcel Holtmann 	hci_dev_lock(hdev);
351641a96212SMarcel Holtmann 
3517cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3518cc11b9c1SAndrei Emeltchenko 	if (ie)
351902b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
352041a96212SMarcel Holtmann 
352141a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
352241a96212SMarcel Holtmann }
352341a96212SMarcel Holtmann 
35246039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
35252763eda6SSzymon Janc 					    struct sk_buff *skb)
35262763eda6SSzymon Janc {
35272763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
35282763eda6SSzymon Janc 	struct oob_data *data;
35292763eda6SSzymon Janc 
35302763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
35312763eda6SSzymon Janc 
35322763eda6SSzymon Janc 	hci_dev_lock(hdev);
35332763eda6SSzymon Janc 
3534a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3535e1ba1f15SSzymon Janc 		goto unlock;
3536e1ba1f15SSzymon Janc 
35372763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
35382763eda6SSzymon Janc 	if (data) {
35392763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
35402763eda6SSzymon Janc 
35412763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
35422763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
35432763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
35442763eda6SSzymon Janc 
35452763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
35462763eda6SSzymon Janc 			     &cp);
35472763eda6SSzymon Janc 	} else {
35482763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
35492763eda6SSzymon Janc 
35502763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
35512763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
35522763eda6SSzymon Janc 			     &cp);
35532763eda6SSzymon Janc 	}
35542763eda6SSzymon Janc 
3555e1ba1f15SSzymon Janc unlock:
35562763eda6SSzymon Janc 	hci_dev_unlock(hdev);
35572763eda6SSzymon Janc }
35582763eda6SSzymon Janc 
3559d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3560d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3561d5e91192SAndrei Emeltchenko {
3562d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3563d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3564d5e91192SAndrei Emeltchenko 
3565d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3566d5e91192SAndrei Emeltchenko 	       ev->status);
3567d5e91192SAndrei Emeltchenko 
3568d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3569d5e91192SAndrei Emeltchenko 
3570d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3571d5e91192SAndrei Emeltchenko 	if (!hcon) {
3572d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3573d5e91192SAndrei Emeltchenko 		return;
3574d5e91192SAndrei Emeltchenko 	}
3575d5e91192SAndrei Emeltchenko 
3576d5e91192SAndrei Emeltchenko 	if (ev->status) {
3577d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3578d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3579d5e91192SAndrei Emeltchenko 		return;
3580d5e91192SAndrei Emeltchenko 	}
3581d5e91192SAndrei Emeltchenko 
3582d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3583d5e91192SAndrei Emeltchenko 
3584d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3585d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3586d5e91192SAndrei Emeltchenko 
3587d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3588d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3589d5e91192SAndrei Emeltchenko 	hci_conn_put(hcon);
3590d5e91192SAndrei Emeltchenko 
3591d5e91192SAndrei Emeltchenko 	hci_conn_hold_device(hcon);
3592d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3593d5e91192SAndrei Emeltchenko 
3594cf70ff22SAndrei Emeltchenko 	amp_physical_cfm(bredr_hcon, hcon);
3595cf70ff22SAndrei Emeltchenko 
3596d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3597d5e91192SAndrei Emeltchenko }
3598d5e91192SAndrei Emeltchenko 
359927695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
360027695fb4SAndrei Emeltchenko {
360127695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
360227695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
360327695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
360427695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
360527695fb4SAndrei Emeltchenko 
360627695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
360727695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
360827695fb4SAndrei Emeltchenko 	       ev->status);
360927695fb4SAndrei Emeltchenko 
361027695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
361127695fb4SAndrei Emeltchenko 	if (!hcon)
361227695fb4SAndrei Emeltchenko 		return;
361327695fb4SAndrei Emeltchenko 
361427695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
361527695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
361627695fb4SAndrei Emeltchenko 	if (!hchan)
361727695fb4SAndrei Emeltchenko 		return;
361827695fb4SAndrei Emeltchenko 
361927695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
362027695fb4SAndrei Emeltchenko 
362127695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
362227695fb4SAndrei Emeltchenko 
362327695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
362427695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
362527695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
362627695fb4SAndrei Emeltchenko 
362727695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
362827695fb4SAndrei Emeltchenko 
362927695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
363027695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
363127695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
363227695fb4SAndrei Emeltchenko 
363327695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
363427695fb4SAndrei Emeltchenko 	}
363527695fb4SAndrei Emeltchenko }
363627695fb4SAndrei Emeltchenko 
3637606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3638606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3639606e2a10SAndrei Emeltchenko {
3640606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3641606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3642606e2a10SAndrei Emeltchenko 
3643606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3644606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3645606e2a10SAndrei Emeltchenko 
3646606e2a10SAndrei Emeltchenko 	if (ev->status)
3647606e2a10SAndrei Emeltchenko 		return;
3648606e2a10SAndrei Emeltchenko 
3649606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3650606e2a10SAndrei Emeltchenko 
3651606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3652606e2a10SAndrei Emeltchenko 	if (!hchan)
3653606e2a10SAndrei Emeltchenko 		goto unlock;
3654606e2a10SAndrei Emeltchenko 
3655606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3656606e2a10SAndrei Emeltchenko 
3657606e2a10SAndrei Emeltchenko unlock:
3658606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3659606e2a10SAndrei Emeltchenko }
3660606e2a10SAndrei Emeltchenko 
36619eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
36629eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
36639eef6b3aSAndrei Emeltchenko {
36649eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
36659eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
36669eef6b3aSAndrei Emeltchenko 
36679eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
36689eef6b3aSAndrei Emeltchenko 
36699eef6b3aSAndrei Emeltchenko 	if (ev->status)
36709eef6b3aSAndrei Emeltchenko 		return;
36719eef6b3aSAndrei Emeltchenko 
36729eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
36739eef6b3aSAndrei Emeltchenko 
36749eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
36759eef6b3aSAndrei Emeltchenko 	if (hcon) {
36769eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
36779eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
36789eef6b3aSAndrei Emeltchenko 	}
36799eef6b3aSAndrei Emeltchenko 
36809eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
36819eef6b3aSAndrei Emeltchenko }
36829eef6b3aSAndrei Emeltchenko 
36836039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3684fcd89c09SVille Tervo {
3685fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3686fcd89c09SVille Tervo 	struct hci_conn *conn;
3687fcd89c09SVille Tervo 
36889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3689fcd89c09SVille Tervo 
3690fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3691fcd89c09SVille Tervo 
36924f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3693b62f328bSVille Tervo 	if (!conn) {
3694b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3695b62f328bSVille Tervo 		if (!conn) {
3696b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3697230fd16aSAndre Guedes 			goto unlock;
3698b62f328bSVille Tervo 		}
369929b7988aSAndre Guedes 
370029b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3701b9b343d2SAndre Guedes 
3702b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3703b9b343d2SAndre Guedes 			conn->out = true;
3704b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3705b9b343d2SAndre Guedes 		}
3706b62f328bSVille Tervo 	}
3707fcd89c09SVille Tervo 
3708cd17decbSAndre Guedes 	if (ev->status) {
3709cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3710cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3711cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3712cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3713cd17decbSAndre Guedes 		hci_conn_del(conn);
3714cd17decbSAndre Guedes 		goto unlock;
3715cd17decbSAndre Guedes 	}
3716cd17decbSAndre Guedes 
3717b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3718b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
371995b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
372083bc71b4SVinicius Costa Gomes 
37217b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3722fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3723fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3724fcd89c09SVille Tervo 
3725fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3726fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3727fcd89c09SVille Tervo 
3728fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3729fcd89c09SVille Tervo 
3730fcd89c09SVille Tervo unlock:
3731fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3732fcd89c09SVille Tervo }
3733fcd89c09SVille Tervo 
37346039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
37359aa04c91SAndre Guedes {
3736e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3737e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
37383c9e9195SAndre Guedes 	s8 rssi;
37399aa04c91SAndre Guedes 
3740e95beb41SAndre Guedes 	while (num_reports--) {
3741e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3742e95beb41SAndre Guedes 
37433c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
37443c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
374504124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
37463c9e9195SAndre Guedes 
3747e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
37489aa04c91SAndre Guedes 	}
37499aa04c91SAndre Guedes }
37509aa04c91SAndre Guedes 
37516039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3752a7a595f6SVinicius Costa Gomes {
3753a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3754a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3755bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3756a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3757c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3758a7a595f6SVinicius Costa Gomes 
37599f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3760a7a595f6SVinicius Costa Gomes 
3761a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3762a7a595f6SVinicius Costa Gomes 
3763a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3764bea710feSVinicius Costa Gomes 	if (conn == NULL)
3765bea710feSVinicius Costa Gomes 		goto not_found;
3766a7a595f6SVinicius Costa Gomes 
3767bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3768bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3769bea710feSVinicius Costa Gomes 		goto not_found;
3770bea710feSVinicius Costa Gomes 
3771bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3772a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3773c9839a11SVinicius Costa Gomes 
3774c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3775c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3776a7a595f6SVinicius Costa Gomes 
3777a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3778a7a595f6SVinicius Costa Gomes 
3779c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3780c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3781c9839a11SVinicius Costa Gomes 		kfree(ltk);
3782c9839a11SVinicius Costa Gomes 	}
3783c9839a11SVinicius Costa Gomes 
3784a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3785bea710feSVinicius Costa Gomes 
3786bea710feSVinicius Costa Gomes 	return;
3787bea710feSVinicius Costa Gomes 
3788bea710feSVinicius Costa Gomes not_found:
3789bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3790bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3791bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3792a7a595f6SVinicius Costa Gomes }
3793a7a595f6SVinicius Costa Gomes 
37946039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3795fcd89c09SVille Tervo {
3796fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3797fcd89c09SVille Tervo 
3798fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3799fcd89c09SVille Tervo 
3800fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3801fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3802fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3803fcd89c09SVille Tervo 		break;
3804fcd89c09SVille Tervo 
38059aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
38069aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
38079aa04c91SAndre Guedes 		break;
38089aa04c91SAndre Guedes 
3809a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3810a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3811a7a595f6SVinicius Costa Gomes 		break;
3812a7a595f6SVinicius Costa Gomes 
3813fcd89c09SVille Tervo 	default:
3814fcd89c09SVille Tervo 		break;
3815fcd89c09SVille Tervo 	}
3816fcd89c09SVille Tervo }
3817fcd89c09SVille Tervo 
38189495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
38199495b2eeSAndrei Emeltchenko {
38209495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
38219495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
38229495b2eeSAndrei Emeltchenko 
38239495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
38249495b2eeSAndrei Emeltchenko 
38259495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
38269495b2eeSAndrei Emeltchenko 
38279495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
38289495b2eeSAndrei Emeltchenko 	if (!hcon)
38299495b2eeSAndrei Emeltchenko 		return;
38309495b2eeSAndrei Emeltchenko 
38319495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
38329495b2eeSAndrei Emeltchenko }
38339495b2eeSAndrei Emeltchenko 
38341da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
38351da177e4SLinus Torvalds {
3836a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3837a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
38381da177e4SLinus Torvalds 
38391da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
38401da177e4SLinus Torvalds 
3841a9de9248SMarcel Holtmann 	switch (event) {
38421da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
38431da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
38441da177e4SLinus Torvalds 		break;
38451da177e4SLinus Torvalds 
38461da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
38471da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
38481da177e4SLinus Torvalds 		break;
38491da177e4SLinus Torvalds 
3850a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3851a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
385221d9e30eSMarcel Holtmann 		break;
385321d9e30eSMarcel Holtmann 
38541da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
38551da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
38561da177e4SLinus Torvalds 		break;
38571da177e4SLinus Torvalds 
38581da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
38591da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
38601da177e4SLinus Torvalds 		break;
38611da177e4SLinus Torvalds 
38621da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
38631da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
38641da177e4SLinus Torvalds 		break;
38651da177e4SLinus Torvalds 
3866a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3867a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3868a9de9248SMarcel Holtmann 		break;
3869a9de9248SMarcel Holtmann 
38701da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
38711da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
38721da177e4SLinus Torvalds 		break;
38731da177e4SLinus Torvalds 
3874a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3875a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3876a9de9248SMarcel Holtmann 		break;
3877a9de9248SMarcel Holtmann 
3878a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3879a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3880a9de9248SMarcel Holtmann 		break;
3881a9de9248SMarcel Holtmann 
3882a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3883a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3884a9de9248SMarcel Holtmann 		break;
3885a9de9248SMarcel Holtmann 
3886a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3887a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3888a9de9248SMarcel Holtmann 		break;
3889a9de9248SMarcel Holtmann 
3890a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3891a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3892a9de9248SMarcel Holtmann 		break;
3893a9de9248SMarcel Holtmann 
3894a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3895a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3896a9de9248SMarcel Holtmann 		break;
3897a9de9248SMarcel Holtmann 
3898a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3899a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3900a9de9248SMarcel Holtmann 		break;
3901a9de9248SMarcel Holtmann 
3902a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3903a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3904a9de9248SMarcel Holtmann 		break;
3905a9de9248SMarcel Holtmann 
3906a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3907a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
39081da177e4SLinus Torvalds 		break;
39091da177e4SLinus Torvalds 
39101da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
39111da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
39121da177e4SLinus Torvalds 		break;
39131da177e4SLinus Torvalds 
39141da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
39151da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
39161da177e4SLinus Torvalds 		break;
39171da177e4SLinus Torvalds 
39181da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
39191da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
39201da177e4SLinus Torvalds 		break;
39211da177e4SLinus Torvalds 
39221da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
39231da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
39241da177e4SLinus Torvalds 		break;
39251da177e4SLinus Torvalds 
3926a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3927a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3928a8746417SMarcel Holtmann 		break;
3929a8746417SMarcel Holtmann 
393085a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
393185a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
393285a1e930SMarcel Holtmann 		break;
393385a1e930SMarcel Holtmann 
3934a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3935a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3936a9de9248SMarcel Holtmann 		break;
3937a9de9248SMarcel Holtmann 
3938a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3939a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3940a9de9248SMarcel Holtmann 		break;
3941a9de9248SMarcel Holtmann 
3942a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3943a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3944a9de9248SMarcel Holtmann 		break;
3945a9de9248SMarcel Holtmann 
3946a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3947a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3948a9de9248SMarcel Holtmann 		break;
3949a9de9248SMarcel Holtmann 
395004837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
395104837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
395204837f64SMarcel Holtmann 		break;
395304837f64SMarcel Holtmann 
3954a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3955a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
39561da177e4SLinus Torvalds 		break;
39571da177e4SLinus Torvalds 
39581c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
39591c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
39601c2e0041SJohan Hedberg 		break;
39611c2e0041SJohan Hedberg 
39620493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
39630493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
39640493684eSMarcel Holtmann 		break;
39650493684eSMarcel Holtmann 
396603b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
396703b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
396803b555e1SJohan Hedberg 		break;
396903b555e1SJohan Hedberg 
3970a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3971a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3972a5c29683SJohan Hedberg 		break;
3973a5c29683SJohan Hedberg 
39741143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
39751143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
39761143d458SBrian Gix 		break;
39771143d458SBrian Gix 
397892a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
397992a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
398092a25256SJohan Hedberg 		break;
398192a25256SJohan Hedberg 
398292a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
398392a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
398492a25256SJohan Hedberg 		break;
398592a25256SJohan Hedberg 
39860493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
39870493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
39880493684eSMarcel Holtmann 		break;
39890493684eSMarcel Holtmann 
399041a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
399141a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
399241a96212SMarcel Holtmann 		break;
399341a96212SMarcel Holtmann 
3994fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3995fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3996fcd89c09SVille Tervo 		break;
3997fcd89c09SVille Tervo 
39989495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
39999495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
40009495b2eeSAndrei Emeltchenko 		break;
40019495b2eeSAndrei Emeltchenko 
40022763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
40032763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
40042763eda6SSzymon Janc 		break;
40052763eda6SSzymon Janc 
4006d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
4007d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
4008d5e91192SAndrei Emeltchenko 		break;
4009d5e91192SAndrei Emeltchenko 
401027695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
401127695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
401227695fb4SAndrei Emeltchenko 		break;
401327695fb4SAndrei Emeltchenko 
4014606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4015606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
4016606e2a10SAndrei Emeltchenko 		break;
4017606e2a10SAndrei Emeltchenko 
40189eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
40199eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
40209eef6b3aSAndrei Emeltchenko 		break;
40219eef6b3aSAndrei Emeltchenko 
402225e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
402325e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
402425e89e99SAndrei Emeltchenko 		break;
402525e89e99SAndrei Emeltchenko 
40261da177e4SLinus Torvalds 	default:
40279f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
40281da177e4SLinus Torvalds 		break;
40291da177e4SLinus Torvalds 	}
40301da177e4SLinus Torvalds 
40311da177e4SLinus Torvalds 	kfree_skb(skb);
40321da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
40331da177e4SLinus Torvalds }
4034