xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 8e2a0d92)
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 
278c520a59SGustavo Padovan #include <linux/export.h>
281da177e4SLinus Torvalds #include <asm/unaligned.h>
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
311da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
32f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h>
338e2a0d92SAndrei Emeltchenko #include <net/bluetooth/a2mp.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;
205a9de9248SMarcel Holtmann }
206a9de9248SMarcel Holtmann 
207a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
208a9de9248SMarcel Holtmann {
209a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2101da177e4SLinus Torvalds 	void *sent;
2111da177e4SLinus Torvalds 
2129f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2131da177e4SLinus Torvalds 
214a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2151da177e4SLinus Torvalds 	if (!sent)
216a9de9248SMarcel Holtmann 		return;
2171da177e4SLinus Torvalds 
21856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
21956e5cb86SJohan Hedberg 
220f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
221f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
22228cc7bdeSJohan Hedberg 	else if (!status)
22328cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
224f51d5b24SJohan Hedberg 
22556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
2263159d384SJohan Hedberg 
2273159d384SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
228a9de9248SMarcel Holtmann }
229a9de9248SMarcel Holtmann 
230a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
231a9de9248SMarcel Holtmann {
232a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
233a9de9248SMarcel Holtmann 
2349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
235a9de9248SMarcel Holtmann 
236a9de9248SMarcel Holtmann 	if (rp->status)
237a9de9248SMarcel Holtmann 		return;
238a9de9248SMarcel Holtmann 
239db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2401f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
241a9de9248SMarcel Holtmann }
242a9de9248SMarcel Holtmann 
243a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
244a9de9248SMarcel Holtmann {
245a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
246a9de9248SMarcel Holtmann 	void *sent;
247a9de9248SMarcel Holtmann 
2489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
249a9de9248SMarcel Holtmann 
250a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
251a9de9248SMarcel Holtmann 	if (!sent)
252a9de9248SMarcel Holtmann 		return;
2531da177e4SLinus Torvalds 
2541da177e4SLinus Torvalds 	if (!status) {
255a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
256a9de9248SMarcel Holtmann 
2571da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2581da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2591da177e4SLinus Torvalds 		else
2601da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2611da177e4SLinus Torvalds 	}
262a9de9248SMarcel Holtmann 
26333ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
26433ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
26533ef95edSJohan Hedberg 
26623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
267a9de9248SMarcel Holtmann }
2681da177e4SLinus Torvalds 
269a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
270a9de9248SMarcel Holtmann {
271a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
272a9de9248SMarcel Holtmann 	void *sent;
273a9de9248SMarcel Holtmann 
2749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
275a9de9248SMarcel Holtmann 
276a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2771da177e4SLinus Torvalds 	if (!sent)
278a9de9248SMarcel Holtmann 		return;
2791da177e4SLinus Torvalds 
2801da177e4SLinus Torvalds 	if (!status) {
281a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
282a9de9248SMarcel Holtmann 
2831da177e4SLinus Torvalds 		if (param)
2841da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2851da177e4SLinus Torvalds 		else
2861da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2871da177e4SLinus Torvalds 	}
288a9de9248SMarcel Holtmann 
28923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2901da177e4SLinus Torvalds }
2911da177e4SLinus Torvalds 
292a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
293a9de9248SMarcel Holtmann {
29436f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
29536f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
296a9de9248SMarcel Holtmann 	void *sent;
2971da177e4SLinus Torvalds 
2989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
299a9de9248SMarcel Holtmann 
300a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3011da177e4SLinus Torvalds 	if (!sent)
302a9de9248SMarcel Holtmann 		return;
3031da177e4SLinus Torvalds 
30436f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
305a9de9248SMarcel Holtmann 
30656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
30756e5cb86SJohan Hedberg 
308fa1bd918SMikel Astiz 	if (status) {
309744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3102d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3112d7cee58SJohan Hedberg 		goto done;
3122d7cee58SJohan Hedberg 	}
3132d7cee58SJohan Hedberg 
3149fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3159fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
316a9de9248SMarcel Holtmann 
31773f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3181da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3199fbcbb45SJohan Hedberg 		if (!old_iscan)
320744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
32116ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
32216ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
32316ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
32416ab91abSJohan Hedberg 					   to);
32516ab91abSJohan Hedberg 		}
3269fbcbb45SJohan Hedberg 	} else if (old_iscan)
327744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3281da177e4SLinus Torvalds 
3299fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3301da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3319fbcbb45SJohan Hedberg 		if (!old_pscan)
332744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3339fbcbb45SJohan Hedberg 	} else if (old_pscan)
334744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
335a9de9248SMarcel Holtmann 
33636f7fc7eSJohan Hedberg done:
33756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
33823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3391da177e4SLinus Torvalds }
3401da177e4SLinus Torvalds 
341a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
342a9de9248SMarcel Holtmann {
343a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
344a9de9248SMarcel Holtmann 
3459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
346a9de9248SMarcel Holtmann 
347a9de9248SMarcel Holtmann 	if (rp->status)
348a9de9248SMarcel Holtmann 		return;
349a9de9248SMarcel Holtmann 
350a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
351a9de9248SMarcel Holtmann 
352a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
353a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
354a9de9248SMarcel Holtmann }
355a9de9248SMarcel Holtmann 
356a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
357a9de9248SMarcel Holtmann {
358a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
359a9de9248SMarcel Holtmann 	void *sent;
360a9de9248SMarcel Holtmann 
3619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
362a9de9248SMarcel Holtmann 
363a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
364a9de9248SMarcel Holtmann 	if (!sent)
365a9de9248SMarcel Holtmann 		return;
366a9de9248SMarcel Holtmann 
3677f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3687f9a903cSMarcel Holtmann 
3697f9a903cSMarcel Holtmann 	if (status == 0)
370a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3717f9a903cSMarcel Holtmann 
3727f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3737f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3747f9a903cSMarcel Holtmann 
3757f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
376a9de9248SMarcel Holtmann }
377a9de9248SMarcel Holtmann 
378a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
379a9de9248SMarcel Holtmann {
380a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
381a9de9248SMarcel Holtmann 	__u16 setting;
382a9de9248SMarcel Holtmann 
3839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
384a9de9248SMarcel Holtmann 
385a9de9248SMarcel Holtmann 	if (rp->status)
386a9de9248SMarcel Holtmann 		return;
387a9de9248SMarcel Holtmann 
388a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
389a9de9248SMarcel Holtmann 
390a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
391a9de9248SMarcel Holtmann 		return;
392a9de9248SMarcel Holtmann 
393a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
394a9de9248SMarcel Holtmann 
3959f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
396a9de9248SMarcel Holtmann 
3973c54711cSGustavo F. Padovan 	if (hdev->notify)
398a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
399a9de9248SMarcel Holtmann }
400a9de9248SMarcel Holtmann 
4018fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
4028fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
403a9de9248SMarcel Holtmann {
404a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
405f383f275SMarcel Holtmann 	__u16 setting;
406a9de9248SMarcel Holtmann 	void *sent;
407a9de9248SMarcel Holtmann 
4089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
409a9de9248SMarcel Holtmann 
410f383f275SMarcel Holtmann 	if (status)
411f383f275SMarcel Holtmann 		return;
412f383f275SMarcel Holtmann 
413a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
414a9de9248SMarcel Holtmann 	if (!sent)
415a9de9248SMarcel Holtmann 		return;
416a9de9248SMarcel Holtmann 
417f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4181da177e4SLinus Torvalds 
419f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
420f383f275SMarcel Holtmann 		return;
421f383f275SMarcel Holtmann 
4221da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4231da177e4SLinus Torvalds 
4249f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4251da177e4SLinus Torvalds 
4263c54711cSGustavo F. Padovan 	if (hdev->notify)
4271da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4281da177e4SLinus Torvalds }
4291da177e4SLinus Torvalds 
430a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4311da177e4SLinus Torvalds {
432a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4331da177e4SLinus Torvalds 
4349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
4351da177e4SLinus Torvalds 
43623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4371143e5a6SMarcel Holtmann }
4381143e5a6SMarcel Holtmann 
439333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
440333140b5SMarcel Holtmann {
441333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
442333140b5SMarcel Holtmann 	void *sent;
443333140b5SMarcel Holtmann 
4449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
445333140b5SMarcel Holtmann 
446333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
447333140b5SMarcel Holtmann 	if (!sent)
448333140b5SMarcel Holtmann 		return;
449333140b5SMarcel Holtmann 
450c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
451c0ecddc2SJohan Hedberg 		mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
452c0ecddc2SJohan Hedberg 	else if (!status) {
45384bde9d6SJohan Hedberg 		if (*((u8 *) sent))
45484bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
45584bde9d6SJohan Hedberg 		else
45684bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
457c0ecddc2SJohan Hedberg 	}
458333140b5SMarcel Holtmann }
459333140b5SMarcel Holtmann 
460d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
461d5859e22SJohan Hedberg {
462d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
463d5859e22SJohan Hedberg 		return 2;
464d5859e22SJohan Hedberg 
465d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
466d5859e22SJohan Hedberg 		return 1;
467d5859e22SJohan Hedberg 
468d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
469d5859e22SJohan Hedberg 	    hdev->lmp_subver == 0x0757)
470d5859e22SJohan Hedberg 		return 1;
471d5859e22SJohan Hedberg 
472d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
473d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
474d5859e22SJohan Hedberg 			return 1;
475d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
476d5859e22SJohan Hedberg 			return 1;
477d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
478d5859e22SJohan Hedberg 			return 1;
479d5859e22SJohan Hedberg 	}
480d5859e22SJohan Hedberg 
481d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
482d5859e22SJohan Hedberg 	    hdev->lmp_subver == 0x1805)
483d5859e22SJohan Hedberg 		return 1;
484d5859e22SJohan Hedberg 
485d5859e22SJohan Hedberg 	return 0;
486d5859e22SJohan Hedberg }
487d5859e22SJohan Hedberg 
488d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
489d5859e22SJohan Hedberg {
490d5859e22SJohan Hedberg 	u8 mode;
491d5859e22SJohan Hedberg 
492d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
493d5859e22SJohan Hedberg 
494d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
495d5859e22SJohan Hedberg }
496d5859e22SJohan Hedberg 
497d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
498d5859e22SJohan Hedberg {
499d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
500d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
501d5859e22SJohan Hedberg 	 * command otherwise */
502d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
503d5859e22SJohan Hedberg 
5046de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5056de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5065a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
5076de6c18dSVille Tervo 		return;
5086de6c18dSVille Tervo 
509d5859e22SJohan Hedberg 	events[4] |= 0x01; /* Flow Specification Complete */
510d5859e22SJohan Hedberg 	events[4] |= 0x02; /* Inquiry Result with RSSI */
511d5859e22SJohan Hedberg 	events[4] |= 0x04; /* Read Remote Extended Features Complete */
512d5859e22SJohan Hedberg 	events[5] |= 0x08; /* Synchronous Connection Complete */
513d5859e22SJohan Hedberg 	events[5] |= 0x10; /* Synchronous Connection Changed */
514d5859e22SJohan Hedberg 
515d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
516a24299e6SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
517d5859e22SJohan Hedberg 
518999dcd10SAndre Guedes 	if (lmp_sniffsubr_capable(hdev))
519d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
520d5859e22SJohan Hedberg 
521d5859e22SJohan Hedberg 	if (hdev->features[5] & LMP_PAUSE_ENC)
522d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
523d5859e22SJohan Hedberg 
524d5859e22SJohan Hedberg 	if (hdev->features[6] & LMP_EXT_INQ)
525d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
526d5859e22SJohan Hedberg 
527c58e810eSAndre Guedes 	if (lmp_no_flush_capable(hdev))
528d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
529d5859e22SJohan Hedberg 
530d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_LSTO)
531d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
532d5859e22SJohan Hedberg 
5339a1a1996SAndre Guedes 	if (lmp_ssp_capable(hdev)) {
534d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
535d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
536d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
537d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
538d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
539d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
540d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
541d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
542d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
543d5859e22SJohan Hedberg 					 * Features Notification */
544d5859e22SJohan Hedberg 	}
545d5859e22SJohan Hedberg 
546c383ddc4SAndre Guedes 	if (lmp_le_capable(hdev))
547d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
548d5859e22SJohan Hedberg 
549d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
550d5859e22SJohan Hedberg }
551d5859e22SJohan Hedberg 
552d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
553d5859e22SJohan Hedberg {
554e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
555e61ef499SAndrei Emeltchenko 		return;
556e61ef499SAndrei Emeltchenko 
557d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
558d5859e22SJohan Hedberg 
559d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
560d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
561d5859e22SJohan Hedberg 
5626d3c730fSGustavo Padovan 	if (lmp_ssp_capable(hdev)) {
56354d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
564d5859e22SJohan Hedberg 			u8 mode = 0x01;
56554d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
56654d04dbbSJohan Hedberg 				     sizeof(mode), &mode);
56754d04dbbSJohan Hedberg 		} else {
56854d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
56954d04dbbSJohan Hedberg 
57054d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
57154d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
57254d04dbbSJohan Hedberg 
57354d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
57454d04dbbSJohan Hedberg 		}
575d5859e22SJohan Hedberg 	}
576d5859e22SJohan Hedberg 
577d5859e22SJohan Hedberg 	if (hdev->features[3] & LMP_RSSI_INQ)
578d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
579d5859e22SJohan Hedberg 
580d5859e22SJohan Hedberg 	if (hdev->features[7] & LMP_INQ_TX_PWR)
581d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
582971e3a4bSAndre Guedes 
583971e3a4bSAndre Guedes 	if (hdev->features[7] & LMP_EXTFEATURES) {
584971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
585971e3a4bSAndre Guedes 
586971e3a4bSAndre Guedes 		cp.page = 0x01;
58704124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
58804124681SGustavo F. Padovan 			     &cp);
589971e3a4bSAndre Guedes 	}
590e6100a25SAndre Guedes 
59147990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
59247990ea0SJohan Hedberg 		u8 enable = 1;
59304124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
59404124681SGustavo F. Padovan 			     &enable);
59547990ea0SJohan Hedberg 	}
596d5859e22SJohan Hedberg }
597d5859e22SJohan Hedberg 
598a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
599a9de9248SMarcel Holtmann {
600a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6011143e5a6SMarcel Holtmann 
6029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
6031143e5a6SMarcel Holtmann 
604a9de9248SMarcel Holtmann 	if (rp->status)
60528b8df77SAndrei Emeltchenko 		goto done;
6061143e5a6SMarcel Holtmann 
607a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
608e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
609d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
610e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
611d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6121da177e4SLinus Torvalds 
6139f1db00cSAndrei Emeltchenko 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
614807deac2SGustavo Padovan 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
615d5859e22SJohan Hedberg 
616d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
617d5859e22SJohan Hedberg 		hci_setup(hdev);
61828b8df77SAndrei Emeltchenko 
61928b8df77SAndrei Emeltchenko done:
62028b8df77SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
621d5859e22SJohan Hedberg }
622d5859e22SJohan Hedberg 
623d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
624d5859e22SJohan Hedberg {
625035100c8SAndrei Emeltchenko 	struct hci_cp_write_def_link_policy cp;
626d5859e22SJohan Hedberg 	u16 link_policy = 0;
627d5859e22SJohan Hedberg 
6289f92ebf6SAndre Guedes 	if (lmp_rswitch_capable(hdev))
629d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
630d5859e22SJohan Hedberg 	if (hdev->features[0] & LMP_HOLD)
631d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
6326eded100SAndre Guedes 	if (lmp_sniff_capable(hdev))
633d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
634d5859e22SJohan Hedberg 	if (hdev->features[1] & LMP_PARK)
635d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
636d5859e22SJohan Hedberg 
637035100c8SAndrei Emeltchenko 	cp.policy = cpu_to_le16(link_policy);
638035100c8SAndrei Emeltchenko 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
6391da177e4SLinus Torvalds }
6401da177e4SLinus Torvalds 
6418fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
6428fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
643a9de9248SMarcel Holtmann {
644a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
645a9de9248SMarcel Holtmann 
6469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
647a9de9248SMarcel Holtmann 
648a9de9248SMarcel Holtmann 	if (rp->status)
649d5859e22SJohan Hedberg 		goto done;
650a9de9248SMarcel Holtmann 
651a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
652d5859e22SJohan Hedberg 
653d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
654d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
655d5859e22SJohan Hedberg 
656d5859e22SJohan Hedberg done:
657d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
658a9de9248SMarcel Holtmann }
659a9de9248SMarcel Holtmann 
6608fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
6618fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
662a9de9248SMarcel Holtmann {
663a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
664a9de9248SMarcel Holtmann 
6659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
666a9de9248SMarcel Holtmann 
667a9de9248SMarcel Holtmann 	if (rp->status)
668a9de9248SMarcel Holtmann 		return;
669a9de9248SMarcel Holtmann 
670a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
6711da177e4SLinus Torvalds 
6721da177e4SLinus Torvalds 	/* Adjust default settings according to features
6731da177e4SLinus Torvalds 	 * supported by device. */
674a9de9248SMarcel Holtmann 
6751da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
6761da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
6771da177e4SLinus Torvalds 
6781da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
6791da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
6801da177e4SLinus Torvalds 
6815b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
6821da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
6835b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
6845b7f9909SMarcel Holtmann 	}
6851da177e4SLinus Torvalds 
6865b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
6871da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
6885b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
6895b7f9909SMarcel Holtmann 	}
6905b7f9909SMarcel Holtmann 
69145db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
6925b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
6935b7f9909SMarcel Holtmann 
6945b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
6955b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
6965b7f9909SMarcel Holtmann 
6975b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
6985b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
6991da177e4SLinus Torvalds 
700efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
701efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
702efc7688bSMarcel Holtmann 
703efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
704efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
705efc7688bSMarcel Holtmann 
706efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
707efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
708efc7688bSMarcel Holtmann 
709a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
710a9de9248SMarcel Holtmann 	       hdev->features[0], hdev->features[1],
711a9de9248SMarcel Holtmann 	       hdev->features[2], hdev->features[3],
712a9de9248SMarcel Holtmann 	       hdev->features[4], hdev->features[5],
713a9de9248SMarcel Holtmann 	       hdev->features[6], hdev->features[7]);
7141da177e4SLinus Torvalds }
7151da177e4SLinus Torvalds 
7168f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev)
7178f984dfaSJohan Hedberg {
7188f984dfaSJohan Hedberg 	struct hci_cp_write_le_host_supported cp;
7198f984dfaSJohan Hedberg 
7208f984dfaSJohan Hedberg 	memset(&cp, 0, sizeof(cp));
7218f984dfaSJohan Hedberg 
7229d42820fSMarcel Holtmann 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
7238f984dfaSJohan Hedberg 		cp.le = 1;
7248f984dfaSJohan Hedberg 		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
7258f984dfaSJohan Hedberg 	}
7268f984dfaSJohan Hedberg 
7278f984dfaSJohan Hedberg 	if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
72804124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
72904124681SGustavo F. Padovan 			     &cp);
7308f984dfaSJohan Hedberg }
7318f984dfaSJohan Hedberg 
732971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
733971e3a4bSAndre Guedes 					   struct sk_buff *skb)
734971e3a4bSAndre Guedes {
735971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
736971e3a4bSAndre Guedes 
7379f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
738971e3a4bSAndre Guedes 
739971e3a4bSAndre Guedes 	if (rp->status)
7408f984dfaSJohan Hedberg 		goto done;
741971e3a4bSAndre Guedes 
742b5b32b65SAndre Guedes 	switch (rp->page) {
743b5b32b65SAndre Guedes 	case 0:
744b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
745b5b32b65SAndre Guedes 		break;
746b5b32b65SAndre Guedes 	case 1:
74759e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
748b5b32b65SAndre Guedes 		break;
749b5b32b65SAndre Guedes 	}
750971e3a4bSAndre Guedes 
751c383ddc4SAndre Guedes 	if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
7528f984dfaSJohan Hedberg 		hci_set_le_support(hdev);
7538f984dfaSJohan Hedberg 
7548f984dfaSJohan Hedberg done:
755971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
756971e3a4bSAndre Guedes }
757971e3a4bSAndre Guedes 
7581e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
7591e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
7601e89cffbSAndrei Emeltchenko {
7611e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
7621e89cffbSAndrei Emeltchenko 
7639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
7641e89cffbSAndrei Emeltchenko 
7651e89cffbSAndrei Emeltchenko 	if (rp->status)
7661e89cffbSAndrei Emeltchenko 		return;
7671e89cffbSAndrei Emeltchenko 
7681e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
7691e89cffbSAndrei Emeltchenko 
7701e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
7711e89cffbSAndrei Emeltchenko }
7721e89cffbSAndrei Emeltchenko 
773a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
774a9de9248SMarcel Holtmann {
775a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
776a9de9248SMarcel Holtmann 
7779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
778a9de9248SMarcel Holtmann 
779a9de9248SMarcel Holtmann 	if (rp->status)
780a9de9248SMarcel Holtmann 		return;
781a9de9248SMarcel Holtmann 
782a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
783a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
784a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
785a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
786da1f5198SMarcel Holtmann 
787da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
788da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
789da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
790da1f5198SMarcel Holtmann 	}
791da1f5198SMarcel Holtmann 
792da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
793da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
7941da177e4SLinus Torvalds 
795807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
796807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
7971da177e4SLinus Torvalds }
7981da177e4SLinus Torvalds 
799a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
800a9de9248SMarcel Holtmann {
801a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
8021da177e4SLinus Torvalds 
8039f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
804a9de9248SMarcel Holtmann 
805a9de9248SMarcel Holtmann 	if (!rp->status)
806a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
807a9de9248SMarcel Holtmann 
80823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
80923bb5763SJohan Hedberg }
81023bb5763SJohan Hedberg 
811350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
812350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
813350ee4cfSAndrei Emeltchenko {
814350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
815350ee4cfSAndrei Emeltchenko 
8169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
817350ee4cfSAndrei Emeltchenko 
818350ee4cfSAndrei Emeltchenko 	if (rp->status)
819350ee4cfSAndrei Emeltchenko 		return;
820350ee4cfSAndrei Emeltchenko 
821350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
822350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
823350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
824350ee4cfSAndrei Emeltchenko 
825350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
826350ee4cfSAndrei Emeltchenko 
827350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
828350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
829350ee4cfSAndrei Emeltchenko 
830350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
831350ee4cfSAndrei Emeltchenko }
832350ee4cfSAndrei Emeltchenko 
83323bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
83423bb5763SJohan Hedberg {
83523bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
83623bb5763SJohan Hedberg 
8379f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
83823bb5763SJohan Hedberg 
83923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8401da177e4SLinus Torvalds }
8411da177e4SLinus Torvalds 
842928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
843928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
844928abaa7SAndrei Emeltchenko {
845928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
846928abaa7SAndrei Emeltchenko 
8479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
848928abaa7SAndrei Emeltchenko 
849928abaa7SAndrei Emeltchenko 	if (rp->status)
8508e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
851928abaa7SAndrei Emeltchenko 
852928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
853928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
854928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
855928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
856928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
857928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
858928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
859928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
860928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
861928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
862928abaa7SAndrei Emeltchenko 
863928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
8648e2a0d92SAndrei Emeltchenko 
8658e2a0d92SAndrei Emeltchenko a2mp_rsp:
8668e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
867928abaa7SAndrei Emeltchenko }
868928abaa7SAndrei Emeltchenko 
869b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
870b0916ea0SJohan Hedberg 					  struct sk_buff *skb)
871b0916ea0SJohan Hedberg {
872b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
873b0916ea0SJohan Hedberg 
8749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
875b0916ea0SJohan Hedberg 
876b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
877b0916ea0SJohan Hedberg }
878b0916ea0SJohan Hedberg 
879d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
880d5859e22SJohan Hedberg {
881d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
882d5859e22SJohan Hedberg 
8839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
884d5859e22SJohan Hedberg 
885d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
886d5859e22SJohan Hedberg }
887d5859e22SJohan Hedberg 
888d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
889d5859e22SJohan Hedberg 				      struct sk_buff *skb)
890d5859e22SJohan Hedberg {
891d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
892d5859e22SJohan Hedberg 
8939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
894d5859e22SJohan Hedberg 
895d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
896d5859e22SJohan Hedberg }
897d5859e22SJohan Hedberg 
898d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
899d5859e22SJohan Hedberg 					 struct sk_buff *skb)
900d5859e22SJohan Hedberg {
90191c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
902d5859e22SJohan Hedberg 
9039f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
904d5859e22SJohan Hedberg 
90591c4e9b1SMarcel Holtmann 	if (!rp->status)
90691c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
90791c4e9b1SMarcel Holtmann 
90891c4e9b1SMarcel Holtmann 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
909d5859e22SJohan Hedberg }
910d5859e22SJohan Hedberg 
911d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
912d5859e22SJohan Hedberg {
913d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
914d5859e22SJohan Hedberg 
9159f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
916d5859e22SJohan Hedberg 
917d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
918d5859e22SJohan Hedberg }
919d5859e22SJohan Hedberg 
920980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
921980e1a53SJohan Hedberg {
922980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
923980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
924980e1a53SJohan Hedberg 	struct hci_conn *conn;
925980e1a53SJohan Hedberg 
9269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
927980e1a53SJohan Hedberg 
92856e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
92956e5cb86SJohan Hedberg 
930a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
931744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
932980e1a53SJohan Hedberg 
933fa1bd918SMikel Astiz 	if (rp->status)
93456e5cb86SJohan Hedberg 		goto unlock;
935980e1a53SJohan Hedberg 
936980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
937980e1a53SJohan Hedberg 	if (!cp)
93856e5cb86SJohan Hedberg 		goto unlock;
939980e1a53SJohan Hedberg 
940980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
941980e1a53SJohan Hedberg 	if (conn)
942980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
94356e5cb86SJohan Hedberg 
94456e5cb86SJohan Hedberg unlock:
94556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
946980e1a53SJohan Hedberg }
947980e1a53SJohan Hedberg 
948980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
949980e1a53SJohan Hedberg {
950980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
951980e1a53SJohan Hedberg 
9529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
953980e1a53SJohan Hedberg 
95456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
95556e5cb86SJohan Hedberg 
956a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
957744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
958980e1a53SJohan Hedberg 						 rp->status);
95956e5cb86SJohan Hedberg 
96056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
961980e1a53SJohan Hedberg }
96256e5cb86SJohan Hedberg 
9636ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
9646ed58ec5SVille Tervo 				       struct sk_buff *skb)
9656ed58ec5SVille Tervo {
9666ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
9676ed58ec5SVille Tervo 
9689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
9696ed58ec5SVille Tervo 
9706ed58ec5SVille Tervo 	if (rp->status)
9716ed58ec5SVille Tervo 		return;
9726ed58ec5SVille Tervo 
9736ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
9746ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
9756ed58ec5SVille Tervo 
9766ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
9776ed58ec5SVille Tervo 
9786ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
9796ed58ec5SVille Tervo 
9806ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
9816ed58ec5SVille Tervo }
982980e1a53SJohan Hedberg 
983a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
984a5c29683SJohan Hedberg {
985a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
986a5c29683SJohan Hedberg 
9879f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
988a5c29683SJohan Hedberg 
98956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
99056e5cb86SJohan Hedberg 
991a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
99204124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
99304124681SGustavo F. Padovan 						 rp->status);
99456e5cb86SJohan Hedberg 
99556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
996a5c29683SJohan Hedberg }
997a5c29683SJohan Hedberg 
998a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
999a5c29683SJohan Hedberg 					  struct sk_buff *skb)
1000a5c29683SJohan Hedberg {
1001a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1002a5c29683SJohan Hedberg 
10039f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1004a5c29683SJohan Hedberg 
100556e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
100656e5cb86SJohan Hedberg 
1007a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1008744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
100904124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
101056e5cb86SJohan Hedberg 
101156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1012a5c29683SJohan Hedberg }
1013a5c29683SJohan Hedberg 
10141143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
10151143d458SBrian Gix {
10161143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10171143d458SBrian Gix 
10189f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10191143d458SBrian Gix 
10201143d458SBrian Gix 	hci_dev_lock(hdev);
10211143d458SBrian Gix 
1022a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1023272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1024272d90dfSJohan Hedberg 						 0, rp->status);
10251143d458SBrian Gix 
10261143d458SBrian Gix 	hci_dev_unlock(hdev);
10271143d458SBrian Gix }
10281143d458SBrian Gix 
10291143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
10301143d458SBrian Gix 					  struct sk_buff *skb)
10311143d458SBrian Gix {
10321143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
10331143d458SBrian Gix 
10349f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10351143d458SBrian Gix 
10361143d458SBrian Gix 	hci_dev_lock(hdev);
10371143d458SBrian Gix 
1038a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
10391143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
104004124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
10411143d458SBrian Gix 
10421143d458SBrian Gix 	hci_dev_unlock(hdev);
10431143d458SBrian Gix }
10441143d458SBrian Gix 
1045c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1046c35938b2SSzymon Janc 					     struct sk_buff *skb)
1047c35938b2SSzymon Janc {
1048c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1049c35938b2SSzymon Janc 
10509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1051c35938b2SSzymon Janc 
105256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1053744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1054c35938b2SSzymon Janc 						rp->randomizer, rp->status);
105556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1056c35938b2SSzymon Janc }
1057c35938b2SSzymon Janc 
105807f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
105907f7fa5dSAndre Guedes {
106007f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
106107f7fa5dSAndre Guedes 
10629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
10637ba8b4beSAndre Guedes 
10647ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
10653fd24153SAndre Guedes 
10663fd24153SAndre Guedes 	if (status) {
10673fd24153SAndre Guedes 		hci_dev_lock(hdev);
10683fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
10693fd24153SAndre Guedes 		hci_dev_unlock(hdev);
10703fd24153SAndre Guedes 		return;
10713fd24153SAndre Guedes 	}
107207f7fa5dSAndre Guedes }
107307f7fa5dSAndre Guedes 
1074eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1075eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1076eb9d91f5SAndre Guedes {
1077eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1078eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1079eb9d91f5SAndre Guedes 
10809f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1081eb9d91f5SAndre Guedes 
1082eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1083eb9d91f5SAndre Guedes 	if (!cp)
1084eb9d91f5SAndre Guedes 		return;
1085eb9d91f5SAndre Guedes 
108668a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
108768a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
10887ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
10897ba8b4beSAndre Guedes 
10903fd24153SAndre Guedes 		if (status) {
10913fd24153SAndre Guedes 			hci_dev_lock(hdev);
10923fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
10933fd24153SAndre Guedes 			hci_dev_unlock(hdev);
10947ba8b4beSAndre Guedes 			return;
10953fd24153SAndre Guedes 		}
10967ba8b4beSAndre Guedes 
1097d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1098d23264a8SAndre Guedes 
1099a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1100343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1101a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
110268a8aea4SAndrei Emeltchenko 		break;
110368a8aea4SAndrei Emeltchenko 
110468a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1105c9ecc48eSAndre Guedes 		if (status) {
1106c9ecc48eSAndre Guedes 			hci_dev_lock(hdev);
1107c9ecc48eSAndre Guedes 			mgmt_stop_discovery_failed(hdev, status);
1108c9ecc48eSAndre Guedes 			hci_dev_unlock(hdev);
11097ba8b4beSAndre Guedes 			return;
1110c9ecc48eSAndre Guedes 		}
11117ba8b4beSAndre Guedes 
1112d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1113d23264a8SAndre Guedes 
1114bc3dd33cSAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1115bc3dd33cSAndre Guedes 		    hdev->discovery.state == DISCOVERY_FINDING) {
11165e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
11175e0452c0SAndre Guedes 		} else {
1118c599008fSAndre Guedes 			hci_dev_lock(hdev);
1119c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1120c599008fSAndre Guedes 			hci_dev_unlock(hdev);
11215e0452c0SAndre Guedes 		}
1122c599008fSAndre Guedes 
112368a8aea4SAndrei Emeltchenko 		break;
112468a8aea4SAndrei Emeltchenko 
112568a8aea4SAndrei Emeltchenko 	default:
112668a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
112768a8aea4SAndrei Emeltchenko 		break;
112835815085SAndre Guedes 	}
1129eb9d91f5SAndre Guedes }
1130eb9d91f5SAndre Guedes 
1131a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1132a7a595f6SVinicius Costa Gomes {
1133a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1134a7a595f6SVinicius Costa Gomes 
11359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1136a7a595f6SVinicius Costa Gomes 
1137a7a595f6SVinicius Costa Gomes 	if (rp->status)
1138a7a595f6SVinicius Costa Gomes 		return;
1139a7a595f6SVinicius Costa Gomes 
1140a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1141a7a595f6SVinicius Costa Gomes }
1142a7a595f6SVinicius Costa Gomes 
1143a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1144a7a595f6SVinicius Costa Gomes {
1145a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1146a7a595f6SVinicius Costa Gomes 
11479f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1148a7a595f6SVinicius Costa Gomes 
1149a7a595f6SVinicius Costa Gomes 	if (rp->status)
1150a7a595f6SVinicius Costa Gomes 		return;
1151a7a595f6SVinicius Costa Gomes 
1152a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1153a7a595f6SVinicius Costa Gomes }
1154a7a595f6SVinicius Costa Gomes 
11556039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1156f9b49306SAndre Guedes 					   struct sk_buff *skb)
1157f9b49306SAndre Guedes {
115806199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1159f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1160f9b49306SAndre Guedes 
11619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1162f9b49306SAndre Guedes 
116306199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
11648f984dfaSJohan Hedberg 	if (!sent)
1165f9b49306SAndre Guedes 		return;
1166f9b49306SAndre Guedes 
11678f984dfaSJohan Hedberg 	if (!status) {
11688f984dfaSJohan Hedberg 		if (sent->le)
11698f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
11708f984dfaSJohan Hedberg 		else
11718f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
11728f984dfaSJohan Hedberg 	}
11738f984dfaSJohan Hedberg 
11748f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
11758f984dfaSJohan Hedberg 	    !test_bit(HCI_INIT, &hdev->flags))
11768f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
11778f984dfaSJohan Hedberg 
11788f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1179f9b49306SAndre Guedes }
1180f9b49306SAndre Guedes 
11816039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1182a9de9248SMarcel Holtmann {
11839f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1184a9de9248SMarcel Holtmann 
1185a9de9248SMarcel Holtmann 	if (status) {
118623bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1187a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
118856e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1189a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
11907a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
119156e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1192314b2381SJohan Hedberg 		return;
1193314b2381SJohan Hedberg 	}
1194314b2381SJohan Hedberg 
119589352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
119689352e7dSAndre Guedes 
119756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1198343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
119956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1200a9de9248SMarcel Holtmann }
1201a9de9248SMarcel Holtmann 
12026039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
12031da177e4SLinus Torvalds {
1204a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
12051da177e4SLinus Torvalds 	struct hci_conn *conn;
12061da177e4SLinus Torvalds 
12079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1208a9de9248SMarcel Holtmann 
1209a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
12101da177e4SLinus Torvalds 	if (!cp)
12111da177e4SLinus Torvalds 		return;
12121da177e4SLinus Torvalds 
12131da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12141da177e4SLinus Torvalds 
12151da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
12161da177e4SLinus Torvalds 
12179f1db00cSAndrei Emeltchenko 	BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn);
12181da177e4SLinus Torvalds 
12191da177e4SLinus Torvalds 	if (status) {
12201da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
12214c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
12221da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
12231da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
12241da177e4SLinus Torvalds 				hci_conn_del(conn);
12254c67bc74SMarcel Holtmann 			} else
12264c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
12271da177e4SLinus Torvalds 		}
12281da177e4SLinus Torvalds 	} else {
12291da177e4SLinus Torvalds 		if (!conn) {
12301da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
12311da177e4SLinus Torvalds 			if (conn) {
1232a0c808b3SJohan Hedberg 				conn->out = true;
12331da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
12341da177e4SLinus Torvalds 			} else
1235893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
12361da177e4SLinus Torvalds 		}
12371da177e4SLinus Torvalds 	}
12381da177e4SLinus Torvalds 
12391da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12401da177e4SLinus Torvalds }
12411da177e4SLinus Torvalds 
1242a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
12431da177e4SLinus Torvalds {
1244a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
12451da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
12461da177e4SLinus Torvalds 	__u16 handle;
12471da177e4SLinus Torvalds 
12489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1249b6a0dc82SMarcel Holtmann 
1250a9de9248SMarcel Holtmann 	if (!status)
1251a9de9248SMarcel Holtmann 		return;
1252a9de9248SMarcel Holtmann 
1253a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
12541da177e4SLinus Torvalds 	if (!cp)
1255a9de9248SMarcel Holtmann 		return;
12561da177e4SLinus Torvalds 
12571da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
12581da177e4SLinus Torvalds 
12599f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
12601da177e4SLinus Torvalds 
12611da177e4SLinus Torvalds 	hci_dev_lock(hdev);
12621da177e4SLinus Torvalds 
12631da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
12645a08ecceSAndrei Emeltchenko 	if (acl) {
12655a08ecceSAndrei Emeltchenko 		sco = acl->link;
12665a08ecceSAndrei Emeltchenko 		if (sco) {
12671da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
12681da177e4SLinus Torvalds 
12691da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
12701da177e4SLinus Torvalds 			hci_conn_del(sco);
12711da177e4SLinus Torvalds 		}
12725a08ecceSAndrei Emeltchenko 	}
12731da177e4SLinus Torvalds 
12741da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
12751da177e4SLinus Torvalds }
12761da177e4SLinus Torvalds 
1277f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1278f8558555SMarcel Holtmann {
1279f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1280f8558555SMarcel Holtmann 	struct hci_conn *conn;
1281f8558555SMarcel Holtmann 
12829f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1283f8558555SMarcel Holtmann 
1284f8558555SMarcel Holtmann 	if (!status)
1285f8558555SMarcel Holtmann 		return;
1286f8558555SMarcel Holtmann 
1287f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1288f8558555SMarcel Holtmann 	if (!cp)
1289f8558555SMarcel Holtmann 		return;
1290f8558555SMarcel Holtmann 
1291f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1292f8558555SMarcel Holtmann 
1293f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1294f8558555SMarcel Holtmann 	if (conn) {
1295f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1296f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1297f8558555SMarcel Holtmann 			hci_conn_put(conn);
1298f8558555SMarcel Holtmann 		}
1299f8558555SMarcel Holtmann 	}
1300f8558555SMarcel Holtmann 
1301f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1302f8558555SMarcel Holtmann }
1303f8558555SMarcel Holtmann 
1304f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1305f8558555SMarcel Holtmann {
1306f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1307f8558555SMarcel Holtmann 	struct hci_conn *conn;
1308f8558555SMarcel Holtmann 
13099f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1310f8558555SMarcel Holtmann 
1311f8558555SMarcel Holtmann 	if (!status)
1312f8558555SMarcel Holtmann 		return;
1313f8558555SMarcel Holtmann 
1314f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1315f8558555SMarcel Holtmann 	if (!cp)
1316f8558555SMarcel Holtmann 		return;
1317f8558555SMarcel Holtmann 
1318f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1319f8558555SMarcel Holtmann 
1320f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1321f8558555SMarcel Holtmann 	if (conn) {
1322f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1323f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1324f8558555SMarcel Holtmann 			hci_conn_put(conn);
1325f8558555SMarcel Holtmann 		}
1326f8558555SMarcel Holtmann 	}
1327f8558555SMarcel Holtmann 
1328f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1329f8558555SMarcel Holtmann }
1330f8558555SMarcel Holtmann 
1331127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1332392599b9SJohan Hedberg 				    struct hci_conn *conn)
1333392599b9SJohan Hedberg {
1334392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1335392599b9SJohan Hedberg 		return 0;
1336392599b9SJohan Hedberg 
1337765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1338392599b9SJohan Hedberg 		return 0;
1339392599b9SJohan Hedberg 
1340392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1341e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1342807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1343807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1344392599b9SJohan Hedberg 		return 0;
1345392599b9SJohan Hedberg 
1346392599b9SJohan Hedberg 	return 1;
1347392599b9SJohan Hedberg }
1348392599b9SJohan Hedberg 
13496039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
135000abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
135130dc78e1SJohan Hedberg {
135230dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
135330dc78e1SJohan Hedberg 
135430dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
135530dc78e1SJohan Hedberg 
135630dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
135730dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
135830dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
135930dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
136030dc78e1SJohan Hedberg 
136130dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
136230dc78e1SJohan Hedberg }
136330dc78e1SJohan Hedberg 
1364b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
136530dc78e1SJohan Hedberg {
136630dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
136730dc78e1SJohan Hedberg 	struct inquiry_entry *e;
136830dc78e1SJohan Hedberg 
1369b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1370b644ba33SJohan Hedberg 		return false;
1371b644ba33SJohan Hedberg 
1372b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1373c810089cSRam Malovany 	if (!e)
1374c810089cSRam Malovany 		return false;
1375c810089cSRam Malovany 
1376b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1377b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1378b644ba33SJohan Hedberg 		return true;
1379b644ba33SJohan Hedberg 	}
1380b644ba33SJohan Hedberg 
1381b644ba33SJohan Hedberg 	return false;
1382b644ba33SJohan Hedberg }
1383b644ba33SJohan Hedberg 
1384b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1385b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1386b644ba33SJohan Hedberg {
1387b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1388b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1389b644ba33SJohan Hedberg 
1390b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
139104124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
139204124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1393b644ba33SJohan Hedberg 
1394b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1395b644ba33SJohan Hedberg 		return;
1396b644ba33SJohan Hedberg 
139730dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
139830dc78e1SJohan Hedberg 		goto discov_complete;
139930dc78e1SJohan Hedberg 
140030dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
140130dc78e1SJohan Hedberg 		return;
140230dc78e1SJohan Hedberg 
140330dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
14047cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
14057cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
14067cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
14077cc8380eSRam Malovany 	 * Event */
14087cc8380eSRam Malovany 	if (!e)
14097cc8380eSRam Malovany 		return;
14107cc8380eSRam Malovany 
141130dc78e1SJohan Hedberg 	list_del(&e->list);
14127cc8380eSRam Malovany 	if (name) {
14137cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1414b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1415b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1416c3e7c0d9SRam Malovany 	} else {
1417c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
141830dc78e1SJohan Hedberg 	}
141930dc78e1SJohan Hedberg 
1420b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
142130dc78e1SJohan Hedberg 		return;
142230dc78e1SJohan Hedberg 
142330dc78e1SJohan Hedberg discov_complete:
142430dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
142530dc78e1SJohan Hedberg }
142630dc78e1SJohan Hedberg 
1427a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
14281da177e4SLinus Torvalds {
1429127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1430127178d2SJohan Hedberg 	struct hci_conn *conn;
1431127178d2SJohan Hedberg 
14329f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1433127178d2SJohan Hedberg 
1434127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1435127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1436127178d2SJohan Hedberg 	if (!status)
1437127178d2SJohan Hedberg 		return;
1438127178d2SJohan Hedberg 
1439127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1440127178d2SJohan Hedberg 	if (!cp)
1441127178d2SJohan Hedberg 		return;
1442127178d2SJohan Hedberg 
1443127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1444127178d2SJohan Hedberg 
1445127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1446b644ba33SJohan Hedberg 
1447b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1448b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1449b644ba33SJohan Hedberg 
145079c6c70cSJohan Hedberg 	if (!conn)
145179c6c70cSJohan Hedberg 		goto unlock;
145279c6c70cSJohan Hedberg 
145379c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
145479c6c70cSJohan Hedberg 		goto unlock;
145579c6c70cSJohan Hedberg 
145651a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1457127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1458127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1459127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1460127178d2SJohan Hedberg 	}
1461127178d2SJohan Hedberg 
146279c6c70cSJohan Hedberg unlock:
1463127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1464a9de9248SMarcel Holtmann }
14651da177e4SLinus Torvalds 
1466769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1467769be974SMarcel Holtmann {
1468769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1469769be974SMarcel Holtmann 	struct hci_conn *conn;
1470769be974SMarcel Holtmann 
14719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1472769be974SMarcel Holtmann 
1473769be974SMarcel Holtmann 	if (!status)
1474769be974SMarcel Holtmann 		return;
1475769be974SMarcel Holtmann 
1476769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1477769be974SMarcel Holtmann 	if (!cp)
1478769be974SMarcel Holtmann 		return;
1479769be974SMarcel Holtmann 
1480769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1481769be974SMarcel Holtmann 
1482769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1483769be974SMarcel Holtmann 	if (conn) {
1484769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1485769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1486769be974SMarcel Holtmann 			hci_conn_put(conn);
1487769be974SMarcel Holtmann 		}
1488769be974SMarcel Holtmann 	}
1489769be974SMarcel Holtmann 
1490769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1491769be974SMarcel Holtmann }
1492769be974SMarcel Holtmann 
1493769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1494769be974SMarcel Holtmann {
1495769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1496769be974SMarcel Holtmann 	struct hci_conn *conn;
1497769be974SMarcel Holtmann 
14989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1499769be974SMarcel Holtmann 
1500769be974SMarcel Holtmann 	if (!status)
1501769be974SMarcel Holtmann 		return;
1502769be974SMarcel Holtmann 
1503769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1504769be974SMarcel Holtmann 	if (!cp)
1505769be974SMarcel Holtmann 		return;
1506769be974SMarcel Holtmann 
1507769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1508769be974SMarcel Holtmann 
1509769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1510769be974SMarcel Holtmann 	if (conn) {
1511769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1512769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1513769be974SMarcel Holtmann 			hci_conn_put(conn);
1514769be974SMarcel Holtmann 		}
1515769be974SMarcel Holtmann 	}
1516769be974SMarcel Holtmann 
1517769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1518769be974SMarcel Holtmann }
1519769be974SMarcel Holtmann 
1520a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1521a9de9248SMarcel Holtmann {
1522b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1523b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1524b6a0dc82SMarcel Holtmann 	__u16 handle;
1525b6a0dc82SMarcel Holtmann 
15269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1527b6a0dc82SMarcel Holtmann 
1528b6a0dc82SMarcel Holtmann 	if (!status)
1529b6a0dc82SMarcel Holtmann 		return;
1530b6a0dc82SMarcel Holtmann 
1531b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1532b6a0dc82SMarcel Holtmann 	if (!cp)
1533b6a0dc82SMarcel Holtmann 		return;
1534b6a0dc82SMarcel Holtmann 
1535b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1536b6a0dc82SMarcel Holtmann 
15379f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1538b6a0dc82SMarcel Holtmann 
1539b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1540b6a0dc82SMarcel Holtmann 
1541b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
15425a08ecceSAndrei Emeltchenko 	if (acl) {
15435a08ecceSAndrei Emeltchenko 		sco = acl->link;
15445a08ecceSAndrei Emeltchenko 		if (sco) {
1545b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1546b6a0dc82SMarcel Holtmann 
1547b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1548b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1549b6a0dc82SMarcel Holtmann 		}
15505a08ecceSAndrei Emeltchenko 	}
1551b6a0dc82SMarcel Holtmann 
1552b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1553a9de9248SMarcel Holtmann }
1554a9de9248SMarcel Holtmann 
1555a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1556a9de9248SMarcel Holtmann {
1557a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
155804837f64SMarcel Holtmann 	struct hci_conn *conn;
155904837f64SMarcel Holtmann 
15609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1561a9de9248SMarcel Holtmann 
1562a9de9248SMarcel Holtmann 	if (!status)
1563a9de9248SMarcel Holtmann 		return;
1564a9de9248SMarcel Holtmann 
1565a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
156604837f64SMarcel Holtmann 	if (!cp)
1567a9de9248SMarcel Holtmann 		return;
156804837f64SMarcel Holtmann 
156904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
157004837f64SMarcel Holtmann 
157104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1572e73439d8SMarcel Holtmann 	if (conn) {
157351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
157404837f64SMarcel Holtmann 
157551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1576e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1577e73439d8SMarcel Holtmann 	}
1578e73439d8SMarcel Holtmann 
157904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
158004837f64SMarcel Holtmann }
158104837f64SMarcel Holtmann 
1582a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1583a9de9248SMarcel Holtmann {
1584a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
158504837f64SMarcel Holtmann 	struct hci_conn *conn;
158604837f64SMarcel Holtmann 
15879f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1588a9de9248SMarcel Holtmann 
1589a9de9248SMarcel Holtmann 	if (!status)
1590a9de9248SMarcel Holtmann 		return;
1591a9de9248SMarcel Holtmann 
1592a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
159304837f64SMarcel Holtmann 	if (!cp)
1594a9de9248SMarcel Holtmann 		return;
159504837f64SMarcel Holtmann 
159604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
159704837f64SMarcel Holtmann 
159804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1599e73439d8SMarcel Holtmann 	if (conn) {
160051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
160104837f64SMarcel Holtmann 
160251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1603e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1604e73439d8SMarcel Holtmann 	}
1605e73439d8SMarcel Holtmann 
160604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
160704837f64SMarcel Holtmann }
160804837f64SMarcel Holtmann 
160988c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
161088c3df13SJohan Hedberg {
161188c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
161288c3df13SJohan Hedberg 	struct hci_conn *conn;
161388c3df13SJohan Hedberg 
161488c3df13SJohan Hedberg 	if (!status)
161588c3df13SJohan Hedberg 		return;
161688c3df13SJohan Hedberg 
161788c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
161888c3df13SJohan Hedberg 	if (!cp)
161988c3df13SJohan Hedberg 		return;
162088c3df13SJohan Hedberg 
162188c3df13SJohan Hedberg 	hci_dev_lock(hdev);
162288c3df13SJohan Hedberg 
162388c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
162488c3df13SJohan Hedberg 	if (conn)
162588c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
162688c3df13SJohan Hedberg 				       conn->dst_type, status);
162788c3df13SJohan Hedberg 
162888c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
162988c3df13SJohan Hedberg }
163088c3df13SJohan Hedberg 
1631fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1632fcd89c09SVille Tervo {
1633fcd89c09SVille Tervo 	struct hci_conn *conn;
1634fcd89c09SVille Tervo 
16359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1636fcd89c09SVille Tervo 
1637f00a06acSAndre Guedes 	if (status) {
1638fcd89c09SVille Tervo 		hci_dev_lock(hdev);
1639fcd89c09SVille Tervo 
16400c95ab78SAndre Guedes 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
1641f00a06acSAndre Guedes 		if (!conn) {
1642f00a06acSAndre Guedes 			hci_dev_unlock(hdev);
1643f00a06acSAndre Guedes 			return;
1644f00a06acSAndre Guedes 		}
1645fcd89c09SVille Tervo 
16460c95ab78SAndre Guedes 		BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
1647fcd89c09SVille Tervo 		       conn);
1648fcd89c09SVille Tervo 
1649fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
16500c95ab78SAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
1651328c9248SHemant Gupta 				    conn->dst_type, status);
1652fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, status);
1653fcd89c09SVille Tervo 		hci_conn_del(conn);
1654fcd89c09SVille Tervo 
1655fcd89c09SVille Tervo 		hci_dev_unlock(hdev);
1656fcd89c09SVille Tervo 	}
1657f00a06acSAndre Guedes }
1658fcd89c09SVille Tervo 
1659a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1660a7a595f6SVinicius Costa Gomes {
16619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1662a7a595f6SVinicius Costa Gomes }
1663a7a595f6SVinicius Costa Gomes 
16646039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
16651da177e4SLinus Torvalds {
16661da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
166730dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
166830dc78e1SJohan Hedberg 	struct inquiry_entry *e;
16691da177e4SLinus Torvalds 
16709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
16711da177e4SLinus Torvalds 
167223bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
16736bd57416SMarcel Holtmann 
1674a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
167589352e7dSAndre Guedes 
167689352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
167789352e7dSAndre Guedes 		return;
167889352e7dSAndre Guedes 
1679a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
168030dc78e1SJohan Hedberg 		return;
168130dc78e1SJohan Hedberg 
168256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
168330dc78e1SJohan Hedberg 
1684343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
168530dc78e1SJohan Hedberg 		goto unlock;
168630dc78e1SJohan Hedberg 
168730dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1688ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
168930dc78e1SJohan Hedberg 		goto unlock;
169030dc78e1SJohan Hedberg 	}
169130dc78e1SJohan Hedberg 
169230dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
169330dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
169430dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
169530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
169630dc78e1SJohan Hedberg 	} else {
169730dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
169830dc78e1SJohan Hedberg 	}
169930dc78e1SJohan Hedberg 
170030dc78e1SJohan Hedberg unlock:
170156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
17021da177e4SLinus Torvalds }
17031da177e4SLinus Torvalds 
17046039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
17051da177e4SLinus Torvalds {
170645bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1707a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
17081da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
17091da177e4SLinus Torvalds 
17101da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
17111da177e4SLinus Torvalds 
171245bb4bf0SMarcel Holtmann 	if (!num_rsp)
171345bb4bf0SMarcel Holtmann 		return;
171445bb4bf0SMarcel Holtmann 
17151519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
17161519cc17SAndre Guedes 		return;
17171519cc17SAndre Guedes 
17181da177e4SLinus Torvalds 	hci_dev_lock(hdev);
171945bb4bf0SMarcel Holtmann 
1720e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1721388fc8faSJohan Hedberg 		bool name_known, ssp;
17223175405bSJohan Hedberg 
17231da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
17241da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
17251da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
17261da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
17271da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
17281da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
17291da177e4SLinus Torvalds 		data.rssi		= 0x00;
173041a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
17313175405bSJohan Hedberg 
1732388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
173348264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
173404124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
173504124681SGustavo F. Padovan 				  0);
17361da177e4SLinus Torvalds 	}
173745bb4bf0SMarcel Holtmann 
17381da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
17391da177e4SLinus Torvalds }
17401da177e4SLinus Torvalds 
17416039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
17421da177e4SLinus Torvalds {
1743a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1744a9de9248SMarcel Holtmann 	struct hci_conn *conn;
17451da177e4SLinus Torvalds 
1746a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
174745bb4bf0SMarcel Holtmann 
17481da177e4SLinus Torvalds 	hci_dev_lock(hdev);
174945bb4bf0SMarcel Holtmann 
1750a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
17519499237aSMarcel Holtmann 	if (!conn) {
17529499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
17539499237aSMarcel Holtmann 			goto unlock;
17549499237aSMarcel Holtmann 
17559499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1756a9de9248SMarcel Holtmann 		if (!conn)
1757a9de9248SMarcel Holtmann 			goto unlock;
175845bb4bf0SMarcel Holtmann 
17599499237aSMarcel Holtmann 		conn->type = SCO_LINK;
17609499237aSMarcel Holtmann 	}
17619499237aSMarcel Holtmann 
1762a9de9248SMarcel Holtmann 	if (!ev->status) {
1763a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1764769be974SMarcel Holtmann 
1765769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1766769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1767769be974SMarcel Holtmann 			hci_conn_hold(conn);
1768a9ea3ed9SSzymon Janc 
1769a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1770a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1771a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1772a9ea3ed9SSzymon Janc 			else
1773052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1774769be974SMarcel Holtmann 		} else
1775a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1776a9de9248SMarcel Holtmann 
17779eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
17787d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
17797d0db0a3SMarcel Holtmann 
1780a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1781a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1782a9de9248SMarcel Holtmann 
1783a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1784a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1785a9de9248SMarcel Holtmann 
1786a9de9248SMarcel Holtmann 		/* Get remote features */
1787a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1788a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1789a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1790769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1791769be974SMarcel Holtmann 				     sizeof(cp), &cp);
179245bb4bf0SMarcel Holtmann 		}
1793a9de9248SMarcel Holtmann 
1794a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1795d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1796a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1797a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1798a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
179904124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
180004124681SGustavo F. Padovan 				     &cp);
1801a9de9248SMarcel Holtmann 		}
180217d5c04cSJohan Hedberg 	} else {
1803a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
180417d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1805744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
180648264f06SJohan Hedberg 					    conn->dst_type, ev->status);
180717d5c04cSJohan Hedberg 	}
180845bb4bf0SMarcel Holtmann 
1809e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1810e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
181145bb4bf0SMarcel Holtmann 
1812769be974SMarcel Holtmann 	if (ev->status) {
1813a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1814a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1815c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1816c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1817a9de9248SMarcel Holtmann 
1818a9de9248SMarcel Holtmann unlock:
18191da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1820a9de9248SMarcel Holtmann 
1821a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
18221da177e4SLinus Torvalds }
18231da177e4SLinus Torvalds 
18246039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
18251da177e4SLinus Torvalds {
1826a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
18271da177e4SLinus Torvalds 	int mask = hdev->link_mode;
18281da177e4SLinus Torvalds 
1829807deac2SGustavo Padovan 	BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
1830807deac2SGustavo Padovan 	       ev->link_type);
18311da177e4SLinus Torvalds 
18321da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
18331da177e4SLinus Torvalds 
1834138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
1835138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
18361da177e4SLinus Torvalds 		/* Connection accepted */
1837c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
18381da177e4SLinus Torvalds 		struct hci_conn *conn;
18391da177e4SLinus Torvalds 
18401da177e4SLinus Torvalds 		hci_dev_lock(hdev);
1841b6a0dc82SMarcel Holtmann 
1842cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
1843cc11b9c1SAndrei Emeltchenko 		if (ie)
1844c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
1845c7bdd502SMarcel Holtmann 
18468fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
18478fc9ced3SGustavo Padovan 					       &ev->bdaddr);
18481da177e4SLinus Torvalds 		if (!conn) {
1849cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
1850cc11b9c1SAndrei Emeltchenko 			if (!conn) {
1851893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
18521da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
18531da177e4SLinus Torvalds 				return;
18541da177e4SLinus Torvalds 			}
18551da177e4SLinus Torvalds 		}
1856b6a0dc82SMarcel Holtmann 
18571da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
18581da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
1859b6a0dc82SMarcel Holtmann 
18601da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
18611da177e4SLinus Torvalds 
1862b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
1863b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
1864b6a0dc82SMarcel Holtmann 
18651da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
18661da177e4SLinus Torvalds 
18671da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
18681da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
18691da177e4SLinus Torvalds 			else
18701da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
18711da177e4SLinus Torvalds 
187204124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
187304124681SGustavo F. Padovan 				     &cp);
1874b6a0dc82SMarcel Holtmann 		} else {
1875b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
1876b6a0dc82SMarcel Holtmann 
1877b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
1878a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
1879b6a0dc82SMarcel Holtmann 
188082781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
188182781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
188282781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
1883b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
1884b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
1885b6a0dc82SMarcel Holtmann 
1886b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
1887b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
1888b6a0dc82SMarcel Holtmann 		}
18891da177e4SLinus Torvalds 	} else {
18901da177e4SLinus Torvalds 		/* Connection rejected */
18911da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
18921da177e4SLinus Torvalds 
18931da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
18949f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
1895a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
18961da177e4SLinus Torvalds 	}
18971da177e4SLinus Torvalds }
18981da177e4SLinus Torvalds 
1899f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
1900f0d6a0eaSMikel Astiz {
1901f0d6a0eaSMikel Astiz 	switch (err) {
1902f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
1903f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
1904f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
1905f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
1906f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
1907f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
1908f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
1909f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
1910f0d6a0eaSMikel Astiz 	default:
1911f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
1912f0d6a0eaSMikel Astiz 	}
1913f0d6a0eaSMikel Astiz }
1914f0d6a0eaSMikel Astiz 
19156039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19161da177e4SLinus Torvalds {
1917a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
191804837f64SMarcel Holtmann 	struct hci_conn *conn;
19191da177e4SLinus Torvalds 
19209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
19211da177e4SLinus Torvalds 
19221da177e4SLinus Torvalds 	hci_dev_lock(hdev);
19231da177e4SLinus Torvalds 
192404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1925f7520543SJohan Hedberg 	if (!conn)
1926f7520543SJohan Hedberg 		goto unlock;
1927f7520543SJohan Hedberg 
192837d9ef76SJohan Hedberg 	if (ev->status == 0)
19291da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
19307d0db0a3SMarcel Holtmann 
1931b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1932b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
1933f0d6a0eaSMikel Astiz 		if (ev->status) {
193488c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
193588c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
1936f0d6a0eaSMikel Astiz 		} else {
1937f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
1938f0d6a0eaSMikel Astiz 
1939afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
1940f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
1941f0d6a0eaSMikel Astiz 		}
194237d9ef76SJohan Hedberg 	}
1943f7520543SJohan Hedberg 
194437d9ef76SJohan Hedberg 	if (ev->status == 0) {
19456ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
19466ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
19472950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
19481da177e4SLinus Torvalds 		hci_conn_del(conn);
194937d9ef76SJohan Hedberg 	}
19501da177e4SLinus Torvalds 
1951f7520543SJohan Hedberg unlock:
19521da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19531da177e4SLinus Torvalds }
19541da177e4SLinus Torvalds 
19556039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1956a9de9248SMarcel Holtmann {
1957a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
1958a9de9248SMarcel Holtmann 	struct hci_conn *conn;
1959a9de9248SMarcel Holtmann 
19609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
1961a9de9248SMarcel Holtmann 
1962a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
1963a9de9248SMarcel Holtmann 
1964a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
1965d7556e20SWaldemar Rymarkiewicz 	if (!conn)
1966d7556e20SWaldemar Rymarkiewicz 		goto unlock;
1967d7556e20SWaldemar Rymarkiewicz 
1968765c2a96SJohan Hedberg 	if (!ev->status) {
1969aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
197051a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
1971d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
197219f8def0SWaldemar Rymarkiewicz 		} else {
1973a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1974765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
197519f8def0SWaldemar Rymarkiewicz 		}
19762a611692SJohan Hedberg 	} else {
1977bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
1978bab73cb6SJohan Hedberg 				 ev->status);
19792a611692SJohan Hedberg 	}
1980a9de9248SMarcel Holtmann 
198151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
198251a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
1983a9de9248SMarcel Holtmann 
1984f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
1985aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
1986f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
1987f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
1988f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
1989d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
1990d7556e20SWaldemar Rymarkiewicz 				     &cp);
1991f8558555SMarcel Holtmann 		} else {
1992f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
1993f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
1994f8558555SMarcel Holtmann 			hci_conn_put(conn);
1995f8558555SMarcel Holtmann 		}
1996052b30b0SMarcel Holtmann 	} else {
1997a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
1998a9de9248SMarcel Holtmann 
1999052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2000052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2001052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2002052b30b0SMarcel Holtmann 	}
2003052b30b0SMarcel Holtmann 
200451a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2005a9de9248SMarcel Holtmann 		if (!ev->status) {
2006a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2007f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2008f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2009d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2010d7556e20SWaldemar Rymarkiewicz 				     &cp);
2011a9de9248SMarcel Holtmann 		} else {
201251a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2013a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2014a9de9248SMarcel Holtmann 		}
2015a9de9248SMarcel Holtmann 	}
2016a9de9248SMarcel Holtmann 
2017d7556e20SWaldemar Rymarkiewicz unlock:
2018a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2019a9de9248SMarcel Holtmann }
2020a9de9248SMarcel Holtmann 
20216039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2022a9de9248SMarcel Holtmann {
2023127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2024127178d2SJohan Hedberg 	struct hci_conn *conn;
2025127178d2SJohan Hedberg 
2026a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2027a9de9248SMarcel Holtmann 
2028a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2029127178d2SJohan Hedberg 
2030127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2031127178d2SJohan Hedberg 
2032127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2033b644ba33SJohan Hedberg 
2034b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2035b644ba33SJohan Hedberg 		goto check_auth;
2036b644ba33SJohan Hedberg 
2037b644ba33SJohan Hedberg 	if (ev->status == 0)
2038b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2039b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2040b644ba33SJohan Hedberg 	else
2041b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2042b644ba33SJohan Hedberg 
2043b644ba33SJohan Hedberg check_auth:
204479c6c70cSJohan Hedberg 	if (!conn)
204579c6c70cSJohan Hedberg 		goto unlock;
204679c6c70cSJohan Hedberg 
204779c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
204879c6c70cSJohan Hedberg 		goto unlock;
204979c6c70cSJohan Hedberg 
205051a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2051127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2052127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2053127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2054127178d2SJohan Hedberg 	}
2055127178d2SJohan Hedberg 
205679c6c70cSJohan Hedberg unlock:
2057127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2058a9de9248SMarcel Holtmann }
2059a9de9248SMarcel Holtmann 
20606039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2061a9de9248SMarcel Holtmann {
2062a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2063a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2064a9de9248SMarcel Holtmann 
20659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2066a9de9248SMarcel Holtmann 
2067a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2068a9de9248SMarcel Holtmann 
2069a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2070a9de9248SMarcel Holtmann 	if (conn) {
2071a9de9248SMarcel Holtmann 		if (!ev->status) {
2072ae293196SMarcel Holtmann 			if (ev->encrypt) {
2073ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2074ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2075a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2076da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2077ae293196SMarcel Holtmann 			} else
2078a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2079a9de9248SMarcel Holtmann 		}
2080a9de9248SMarcel Holtmann 
208151a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2082a9de9248SMarcel Holtmann 
2083a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2084d839c813SGustavo Padovan 			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
2085a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2086a7d7723aSGustavo Padovan 			goto unlock;
2087a7d7723aSGustavo Padovan 		}
2088a7d7723aSGustavo Padovan 
2089f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2090f8558555SMarcel Holtmann 			if (!ev->status)
2091f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2092f8558555SMarcel Holtmann 
2093f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2094f8558555SMarcel Holtmann 			hci_conn_put(conn);
2095f8558555SMarcel Holtmann 		} else
2096a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2097a9de9248SMarcel Holtmann 	}
2098a9de9248SMarcel Holtmann 
2099a7d7723aSGustavo Padovan unlock:
2100a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2101a9de9248SMarcel Holtmann }
2102a9de9248SMarcel Holtmann 
21036039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2104807deac2SGustavo Padovan 					     struct sk_buff *skb)
2105a9de9248SMarcel Holtmann {
2106a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2107a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2108a9de9248SMarcel Holtmann 
21099f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2110a9de9248SMarcel Holtmann 
2111a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2112a9de9248SMarcel Holtmann 
2113a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2114a9de9248SMarcel Holtmann 	if (conn) {
2115a9de9248SMarcel Holtmann 		if (!ev->status)
2116a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2117a9de9248SMarcel Holtmann 
211851a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2119a9de9248SMarcel Holtmann 
2120a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2121a9de9248SMarcel Holtmann 	}
2122a9de9248SMarcel Holtmann 
2123a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2124a9de9248SMarcel Holtmann }
2125a9de9248SMarcel Holtmann 
21266039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2127807deac2SGustavo Padovan 				    struct sk_buff *skb)
2128a9de9248SMarcel Holtmann {
2129a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *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));
2137ccd556feSJohan Hedberg 	if (!conn)
2138ccd556feSJohan Hedberg 		goto unlock;
2139ccd556feSJohan Hedberg 
2140769be974SMarcel Holtmann 	if (!ev->status)
2141a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2142a9de9248SMarcel Holtmann 
2143ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2144ccd556feSJohan Hedberg 		goto unlock;
2145ccd556feSJohan Hedberg 
2146ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2147769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2148769be974SMarcel Holtmann 		cp.handle = ev->handle;
2149769be974SMarcel Holtmann 		cp.page = 0x01;
2150ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2151769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2152392599b9SJohan Hedberg 		goto unlock;
2153392599b9SJohan Hedberg 	}
2154392599b9SJohan Hedberg 
2155671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2156127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2157127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2158127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2159127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2160127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2161b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2162b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
216308c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2164b644ba33SJohan Hedberg 				      conn->dev_class);
2165392599b9SJohan Hedberg 
2166127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2167769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2168769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2169769be974SMarcel Holtmann 		hci_conn_put(conn);
2170769be974SMarcel Holtmann 	}
2171769be974SMarcel Holtmann 
2172ccd556feSJohan Hedberg unlock:
2173a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2174a9de9248SMarcel Holtmann }
2175a9de9248SMarcel Holtmann 
21766039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
21776039aa73SGustavo Padovan {
21786039aa73SGustavo Padovan 	BT_DBG("%s", hdev->name);
21796039aa73SGustavo Padovan }
21806039aa73SGustavo Padovan 
21816039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2182807deac2SGustavo Padovan 				       struct sk_buff *skb)
2183a9de9248SMarcel Holtmann {
2184a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2185a9de9248SMarcel Holtmann }
2186a9de9248SMarcel Holtmann 
21876039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2188a9de9248SMarcel Holtmann {
2189a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2190a9de9248SMarcel Holtmann 	__u16 opcode;
2191a9de9248SMarcel Holtmann 
2192a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2193a9de9248SMarcel Holtmann 
2194a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2195a9de9248SMarcel Holtmann 
2196a9de9248SMarcel Holtmann 	switch (opcode) {
2197a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2198a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2199a9de9248SMarcel Holtmann 		break;
2200a9de9248SMarcel Holtmann 
22014d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
22024d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
22034d93483bSAndre Guedes 		break;
22044d93483bSAndre Guedes 
2205a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2206a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2207a9de9248SMarcel Holtmann 		break;
2208a9de9248SMarcel Holtmann 
2209a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2210a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2211a9de9248SMarcel Holtmann 		break;
2212a9de9248SMarcel Holtmann 
2213a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2214a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2215a9de9248SMarcel Holtmann 		break;
2216a9de9248SMarcel Holtmann 
2217e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2218e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2219e4e8e37cSMarcel Holtmann 		break;
2220e4e8e37cSMarcel Holtmann 
2221a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2222a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2223a9de9248SMarcel Holtmann 		break;
2224a9de9248SMarcel Holtmann 
2225e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2226e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2227e4e8e37cSMarcel Holtmann 		break;
2228e4e8e37cSMarcel Holtmann 
2229e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2230e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2231e4e8e37cSMarcel Holtmann 		break;
2232e4e8e37cSMarcel Holtmann 
2233a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2234a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2235a9de9248SMarcel Holtmann 		break;
2236a9de9248SMarcel Holtmann 
2237a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2238a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2239a9de9248SMarcel Holtmann 		break;
2240a9de9248SMarcel Holtmann 
2241a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2242a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2243a9de9248SMarcel Holtmann 		break;
2244a9de9248SMarcel Holtmann 
2245a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2246a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2247a9de9248SMarcel Holtmann 		break;
2248a9de9248SMarcel Holtmann 
2249a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2250a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2251a9de9248SMarcel Holtmann 		break;
2252a9de9248SMarcel Holtmann 
2253a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2254a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2255a9de9248SMarcel Holtmann 		break;
2256a9de9248SMarcel Holtmann 
2257a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2258a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2259a9de9248SMarcel Holtmann 		break;
2260a9de9248SMarcel Holtmann 
2261a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2262a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2263a9de9248SMarcel Holtmann 		break;
2264a9de9248SMarcel Holtmann 
2265a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2266a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2267a9de9248SMarcel Holtmann 		break;
2268a9de9248SMarcel Holtmann 
2269a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2270a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2271a9de9248SMarcel Holtmann 		break;
2272a9de9248SMarcel Holtmann 
2273a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2274a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2275a9de9248SMarcel Holtmann 		break;
2276a9de9248SMarcel Holtmann 
2277333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2278333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2279333140b5SMarcel Holtmann 		break;
2280333140b5SMarcel Holtmann 
2281a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2282a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2283a9de9248SMarcel Holtmann 		break;
2284a9de9248SMarcel Holtmann 
2285a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2286a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2287a9de9248SMarcel Holtmann 		break;
2288a9de9248SMarcel Holtmann 
2289a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2290a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2291a9de9248SMarcel Holtmann 		break;
2292a9de9248SMarcel Holtmann 
2293971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2294971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2295971e3a4bSAndre Guedes 		break;
2296971e3a4bSAndre Guedes 
2297a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2298a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2299a9de9248SMarcel Holtmann 		break;
2300a9de9248SMarcel Holtmann 
2301a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2302a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2303a9de9248SMarcel Holtmann 		break;
2304a9de9248SMarcel Holtmann 
2305350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2306350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2307350ee4cfSAndrei Emeltchenko 		break;
2308350ee4cfSAndrei Emeltchenko 
230923bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
231023bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
231123bb5763SJohan Hedberg 		break;
231223bb5763SJohan Hedberg 
23131e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
23141e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
23151e89cffbSAndrei Emeltchenko 		break;
23161e89cffbSAndrei Emeltchenko 
2317928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2318928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2319928abaa7SAndrei Emeltchenko 		break;
2320928abaa7SAndrei Emeltchenko 
2321b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2322b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2323b0916ea0SJohan Hedberg 		break;
2324b0916ea0SJohan Hedberg 
2325d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2326d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2327d5859e22SJohan Hedberg 		break;
2328d5859e22SJohan Hedberg 
2329d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2330d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2331d5859e22SJohan Hedberg 		break;
2332d5859e22SJohan Hedberg 
2333d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2334d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2335d5859e22SJohan Hedberg 		break;
2336d5859e22SJohan Hedberg 
2337d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2338d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2339d5859e22SJohan Hedberg 		break;
2340d5859e22SJohan Hedberg 
2341980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2342980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2343980e1a53SJohan Hedberg 		break;
2344980e1a53SJohan Hedberg 
2345980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2346980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2347980e1a53SJohan Hedberg 		break;
2348980e1a53SJohan Hedberg 
2349c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2350c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2351c35938b2SSzymon Janc 		break;
2352c35938b2SSzymon Janc 
23536ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
23546ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
23556ed58ec5SVille Tervo 		break;
23566ed58ec5SVille Tervo 
2357a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2358a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2359a5c29683SJohan Hedberg 		break;
2360a5c29683SJohan Hedberg 
2361a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2362a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2363a5c29683SJohan Hedberg 		break;
2364a5c29683SJohan Hedberg 
23651143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
23661143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
23671143d458SBrian Gix 		break;
23681143d458SBrian Gix 
23691143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
23701143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
237116cde993SSzymon Janc 		break;
237207f7fa5dSAndre Guedes 
237307f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
237407f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
23751143d458SBrian Gix 		break;
23761143d458SBrian Gix 
2377eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2378eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2379eb9d91f5SAndre Guedes 		break;
2380eb9d91f5SAndre Guedes 
2381a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2382a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2383a7a595f6SVinicius Costa Gomes 		break;
2384a7a595f6SVinicius Costa Gomes 
2385a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2386a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2387a7a595f6SVinicius Costa Gomes 		break;
2388a7a595f6SVinicius Costa Gomes 
2389f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2390f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2391f9b49306SAndre Guedes 		break;
2392f9b49306SAndre Guedes 
2393a9de9248SMarcel Holtmann 	default:
23949f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2395a9de9248SMarcel Holtmann 		break;
2396a9de9248SMarcel Holtmann 	}
2397a9de9248SMarcel Holtmann 
23986bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
23996bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24006bd32326SVille Tervo 
2401a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2402a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2403a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2404c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2405a9de9248SMarcel Holtmann 	}
2406a9de9248SMarcel Holtmann }
2407a9de9248SMarcel Holtmann 
24086039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2409a9de9248SMarcel Holtmann {
2410a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2411a9de9248SMarcel Holtmann 	__u16 opcode;
2412a9de9248SMarcel Holtmann 
2413a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2414a9de9248SMarcel Holtmann 
2415a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2416a9de9248SMarcel Holtmann 
2417a9de9248SMarcel Holtmann 	switch (opcode) {
2418a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2419a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2420a9de9248SMarcel Holtmann 		break;
2421a9de9248SMarcel Holtmann 
2422a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2423a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2424a9de9248SMarcel Holtmann 		break;
2425a9de9248SMarcel Holtmann 
2426a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2427a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2428a9de9248SMarcel Holtmann 		break;
2429a9de9248SMarcel Holtmann 
2430f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2431f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2432f8558555SMarcel Holtmann 		break;
2433f8558555SMarcel Holtmann 
2434f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2435f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2436f8558555SMarcel Holtmann 		break;
2437f8558555SMarcel Holtmann 
2438a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2439a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2440a9de9248SMarcel Holtmann 		break;
2441a9de9248SMarcel Holtmann 
2442769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2443769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2444769be974SMarcel Holtmann 		break;
2445769be974SMarcel Holtmann 
2446769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2447769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2448769be974SMarcel Holtmann 		break;
2449769be974SMarcel Holtmann 
2450a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2451a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2452a9de9248SMarcel Holtmann 		break;
2453a9de9248SMarcel Holtmann 
2454a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2455a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2456a9de9248SMarcel Holtmann 		break;
2457a9de9248SMarcel Holtmann 
2458a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2459a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2460a9de9248SMarcel Holtmann 		break;
2461a9de9248SMarcel Holtmann 
24628962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
246388c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
24648962ee74SJohan Hedberg 		break;
24658962ee74SJohan Hedberg 
2466fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2467fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2468fcd89c09SVille Tervo 		break;
2469fcd89c09SVille Tervo 
2470a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2471a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2472a7a595f6SVinicius Costa Gomes 		break;
2473a7a595f6SVinicius Costa Gomes 
2474a9de9248SMarcel Holtmann 	default:
24759f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2476a9de9248SMarcel Holtmann 		break;
2477a9de9248SMarcel Holtmann 	}
2478a9de9248SMarcel Holtmann 
24796bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
24806bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
24816bd32326SVille Tervo 
248210572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2483a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2484a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2485c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2486a9de9248SMarcel Holtmann 	}
2487a9de9248SMarcel Holtmann }
2488a9de9248SMarcel Holtmann 
24896039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2490a9de9248SMarcel Holtmann {
2491a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2492a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2493a9de9248SMarcel Holtmann 
24949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2495a9de9248SMarcel Holtmann 
2496a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2497a9de9248SMarcel Holtmann 
2498a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2499a9de9248SMarcel Holtmann 	if (conn) {
2500a9de9248SMarcel Holtmann 		if (!ev->status) {
2501a9de9248SMarcel Holtmann 			if (ev->role)
2502a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2503a9de9248SMarcel Holtmann 			else
2504a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2505a9de9248SMarcel Holtmann 		}
2506a9de9248SMarcel Holtmann 
250751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2508a9de9248SMarcel Holtmann 
2509a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2510a9de9248SMarcel Holtmann 	}
2511a9de9248SMarcel Holtmann 
2512a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2513a9de9248SMarcel Holtmann }
2514a9de9248SMarcel Holtmann 
25156039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
25161da177e4SLinus Torvalds {
2517a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
25181da177e4SLinus Torvalds 	int i;
25191da177e4SLinus Torvalds 
252032ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
252132ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
252232ac5b9bSAndrei Emeltchenko 		return;
252332ac5b9bSAndrei Emeltchenko 	}
252432ac5b9bSAndrei Emeltchenko 
2525c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2526c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
25271da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
25281da177e4SLinus Torvalds 		return;
25291da177e4SLinus Torvalds 	}
25301da177e4SLinus Torvalds 
2531c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2532c5993de8SAndrei Emeltchenko 
2533613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2534613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
25351da177e4SLinus Torvalds 		struct hci_conn *conn;
25361da177e4SLinus Torvalds 		__u16  handle, count;
25371da177e4SLinus Torvalds 
2538613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2539613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
25401da177e4SLinus Torvalds 
25411da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2542f4280918SAndrei Emeltchenko 		if (!conn)
2543f4280918SAndrei Emeltchenko 			continue;
2544f4280918SAndrei Emeltchenko 
25451da177e4SLinus Torvalds 		conn->sent -= count;
25461da177e4SLinus Torvalds 
2547f4280918SAndrei Emeltchenko 		switch (conn->type) {
2548f4280918SAndrei Emeltchenko 		case ACL_LINK:
254970f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
255070f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
25511da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2552f4280918SAndrei Emeltchenko 			break;
2553f4280918SAndrei Emeltchenko 
2554f4280918SAndrei Emeltchenko 		case LE_LINK:
25556ed58ec5SVille Tervo 			if (hdev->le_pkts) {
25566ed58ec5SVille Tervo 				hdev->le_cnt += count;
25576ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
25586ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
25596ed58ec5SVille Tervo 			} else {
25606ed58ec5SVille Tervo 				hdev->acl_cnt += count;
25616ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
25626ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
25636ed58ec5SVille Tervo 			}
2564f4280918SAndrei Emeltchenko 			break;
2565f4280918SAndrei Emeltchenko 
2566f4280918SAndrei Emeltchenko 		case SCO_LINK:
256770f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
256870f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
25695b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2570f4280918SAndrei Emeltchenko 			break;
2571f4280918SAndrei Emeltchenko 
2572f4280918SAndrei Emeltchenko 		default:
2573f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2574f4280918SAndrei Emeltchenko 			break;
25751da177e4SLinus Torvalds 		}
25761da177e4SLinus Torvalds 	}
2577a9de9248SMarcel Holtmann 
25783eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
25791da177e4SLinus Torvalds }
25801da177e4SLinus Torvalds 
25816039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
258225e89e99SAndrei Emeltchenko {
258325e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
258425e89e99SAndrei Emeltchenko 	int i;
258525e89e99SAndrei Emeltchenko 
258625e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
258725e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
258825e89e99SAndrei Emeltchenko 		return;
258925e89e99SAndrei Emeltchenko 	}
259025e89e99SAndrei Emeltchenko 
259125e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
259225e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
259325e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
259425e89e99SAndrei Emeltchenko 		return;
259525e89e99SAndrei Emeltchenko 	}
259625e89e99SAndrei Emeltchenko 
259725e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
259825e89e99SAndrei Emeltchenko 	       ev->num_hndl);
259925e89e99SAndrei Emeltchenko 
260025e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
260125e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
260225e89e99SAndrei Emeltchenko 		struct hci_conn *conn;
260325e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
260425e89e99SAndrei Emeltchenko 
260525e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
260625e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
260725e89e99SAndrei Emeltchenko 
260825e89e99SAndrei Emeltchenko 		conn = hci_conn_hash_lookup_handle(hdev, handle);
260925e89e99SAndrei Emeltchenko 		if (!conn)
261025e89e99SAndrei Emeltchenko 			continue;
261125e89e99SAndrei Emeltchenko 
261225e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
261325e89e99SAndrei Emeltchenko 
261425e89e99SAndrei Emeltchenko 		switch (conn->type) {
261525e89e99SAndrei Emeltchenko 		case ACL_LINK:
261625e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
261725e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
261825e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
261925e89e99SAndrei Emeltchenko 			break;
262025e89e99SAndrei Emeltchenko 
262125e89e99SAndrei Emeltchenko 		default:
262225e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
262325e89e99SAndrei Emeltchenko 			break;
262425e89e99SAndrei Emeltchenko 		}
262525e89e99SAndrei Emeltchenko 	}
262625e89e99SAndrei Emeltchenko 
262725e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
262825e89e99SAndrei Emeltchenko }
262925e89e99SAndrei Emeltchenko 
26306039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
26311da177e4SLinus Torvalds {
2632a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
263304837f64SMarcel Holtmann 	struct hci_conn *conn;
26341da177e4SLinus Torvalds 
26359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
26361da177e4SLinus Torvalds 
26371da177e4SLinus Torvalds 	hci_dev_lock(hdev);
26381da177e4SLinus Torvalds 
263904837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
264004837f64SMarcel Holtmann 	if (conn) {
264104837f64SMarcel Holtmann 		conn->mode = ev->mode;
264204837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
264304837f64SMarcel Holtmann 
26448fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
26458fc9ced3SGustavo Padovan 					&conn->flags)) {
264604837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
264758a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
264804837f64SMarcel Holtmann 			else
264958a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
265004837f64SMarcel Holtmann 		}
2651e73439d8SMarcel Holtmann 
265251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2653e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
265404837f64SMarcel Holtmann 	}
265504837f64SMarcel Holtmann 
265604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
265704837f64SMarcel Holtmann }
265804837f64SMarcel Holtmann 
26596039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26601da177e4SLinus Torvalds {
2661052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2662052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2663052b30b0SMarcel Holtmann 
2664a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2665052b30b0SMarcel Holtmann 
2666052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2667052b30b0SMarcel Holtmann 
2668052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2669b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2670b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2671b6f98044SWaldemar Rymarkiewicz 
2672b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2673052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2674052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2675052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2676052b30b0SMarcel Holtmann 	}
2677052b30b0SMarcel Holtmann 
2678a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
267903b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
268003b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2681a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2682a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2683a770bb5aSWaldemar Rymarkiewicz 
2684a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2685a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2686a770bb5aSWaldemar Rymarkiewicz 		else
2687a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2688a770bb5aSWaldemar Rymarkiewicz 
2689744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2690a770bb5aSWaldemar Rymarkiewicz 	}
2691980e1a53SJohan Hedberg 
2692b6f98044SWaldemar Rymarkiewicz unlock:
2693052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
26941da177e4SLinus Torvalds }
26951da177e4SLinus Torvalds 
26966039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
26971da177e4SLinus Torvalds {
269855ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
269955ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
270055ed8ca1SJohan Hedberg 	struct hci_conn *conn;
270155ed8ca1SJohan Hedberg 	struct link_key *key;
270255ed8ca1SJohan Hedberg 
2703a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
270455ed8ca1SJohan Hedberg 
2705a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
270655ed8ca1SJohan Hedberg 		return;
270755ed8ca1SJohan Hedberg 
270855ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
270955ed8ca1SJohan Hedberg 
271055ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
271155ed8ca1SJohan Hedberg 	if (!key) {
271255ed8ca1SJohan Hedberg 		BT_DBG("%s link key not found for %s", hdev->name,
271355ed8ca1SJohan Hedberg 		       batostr(&ev->bdaddr));
271455ed8ca1SJohan Hedberg 		goto not_found;
271555ed8ca1SJohan Hedberg 	}
271655ed8ca1SJohan Hedberg 
271755ed8ca1SJohan Hedberg 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
271855ed8ca1SJohan Hedberg 	       batostr(&ev->bdaddr));
271955ed8ca1SJohan Hedberg 
2720a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2721b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
272255ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
272355ed8ca1SJohan Hedberg 		goto not_found;
272455ed8ca1SJohan Hedberg 	}
272555ed8ca1SJohan Hedberg 
272655ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
272760b83f57SWaldemar Rymarkiewicz 	if (conn) {
272860b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2729807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
273055ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
273155ed8ca1SJohan Hedberg 			goto not_found;
273255ed8ca1SJohan Hedberg 		}
273355ed8ca1SJohan Hedberg 
273460b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
273560b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
27368fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
27378fc9ced3SGustavo Padovan 			       hdev->name);
273860b83f57SWaldemar Rymarkiewicz 			goto not_found;
273960b83f57SWaldemar Rymarkiewicz 		}
274060b83f57SWaldemar Rymarkiewicz 
274160b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
274260b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
274360b83f57SWaldemar Rymarkiewicz 	}
274460b83f57SWaldemar Rymarkiewicz 
274555ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
27469b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
274755ed8ca1SJohan Hedberg 
274855ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
274955ed8ca1SJohan Hedberg 
275055ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
275155ed8ca1SJohan Hedberg 
275255ed8ca1SJohan Hedberg 	return;
275355ed8ca1SJohan Hedberg 
275455ed8ca1SJohan Hedberg not_found:
275555ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
275655ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
27571da177e4SLinus Torvalds }
27581da177e4SLinus Torvalds 
27596039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
27601da177e4SLinus Torvalds {
2761052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2762052b30b0SMarcel Holtmann 	struct hci_conn *conn;
276355ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2764052b30b0SMarcel Holtmann 
2765a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2766052b30b0SMarcel Holtmann 
2767052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2768052b30b0SMarcel Holtmann 
2769052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2770052b30b0SMarcel Holtmann 	if (conn) {
2771052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2772052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2773980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
277413d39315SWaldemar Rymarkiewicz 
277513d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
277613d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
277713d39315SWaldemar Rymarkiewicz 
2778052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2779052b30b0SMarcel Holtmann 	}
2780052b30b0SMarcel Holtmann 
2781a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2782d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
278355ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
278455ed8ca1SJohan Hedberg 
2785052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
27861da177e4SLinus Torvalds }
27871da177e4SLinus Torvalds 
27886039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
278904837f64SMarcel Holtmann {
2790a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
279104837f64SMarcel Holtmann 	struct hci_conn *conn;
279204837f64SMarcel Holtmann 
27939f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
279404837f64SMarcel Holtmann 
279504837f64SMarcel Holtmann 	hci_dev_lock(hdev);
279604837f64SMarcel Holtmann 
279704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
27981da177e4SLinus Torvalds 	if (conn && !ev->status) {
27991da177e4SLinus Torvalds 		struct inquiry_entry *ie;
28001da177e4SLinus Torvalds 
2801cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2802cc11b9c1SAndrei Emeltchenko 		if (ie) {
28031da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
28041da177e4SLinus Torvalds 			ie->timestamp = jiffies;
28051da177e4SLinus Torvalds 		}
28061da177e4SLinus Torvalds 	}
28071da177e4SLinus Torvalds 
28081da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
28091da177e4SLinus Torvalds }
28101da177e4SLinus Torvalds 
28116039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2812a8746417SMarcel Holtmann {
2813a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
2814a8746417SMarcel Holtmann 	struct hci_conn *conn;
2815a8746417SMarcel Holtmann 
28169f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2817a8746417SMarcel Holtmann 
2818a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
2819a8746417SMarcel Holtmann 
2820a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2821a8746417SMarcel Holtmann 	if (conn && !ev->status)
2822a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
2823a8746417SMarcel Holtmann 
2824a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
2825a8746417SMarcel Holtmann }
2826a8746417SMarcel Holtmann 
28276039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
282885a1e930SMarcel Holtmann {
2829a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
283085a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
283185a1e930SMarcel Holtmann 
283285a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
283385a1e930SMarcel Holtmann 
283485a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
283585a1e930SMarcel Holtmann 
2836cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2837cc11b9c1SAndrei Emeltchenko 	if (ie) {
283885a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
283985a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
284085a1e930SMarcel Holtmann 	}
284185a1e930SMarcel Holtmann 
284285a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
284385a1e930SMarcel Holtmann }
284485a1e930SMarcel Holtmann 
28456039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
2846807deac2SGustavo Padovan 					     struct sk_buff *skb)
2847a9de9248SMarcel Holtmann {
2848a9de9248SMarcel Holtmann 	struct inquiry_data data;
2849a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
2850388fc8faSJohan Hedberg 	bool name_known, ssp;
2851a9de9248SMarcel Holtmann 
2852a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
2853a9de9248SMarcel Holtmann 
2854a9de9248SMarcel Holtmann 	if (!num_rsp)
2855a9de9248SMarcel Holtmann 		return;
2856a9de9248SMarcel Holtmann 
28571519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
28581519cc17SAndre Guedes 		return;
28591519cc17SAndre Guedes 
2860a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2861a9de9248SMarcel Holtmann 
2862a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
2863138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
2864138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
2865a9de9248SMarcel Holtmann 
2866e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2867a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2868a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2869a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2870a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
2871a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2872a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2873a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
287441a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28753175405bSJohan Hedberg 
28763175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2877388fc8faSJohan Hedberg 							      false, &ssp);
287848264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2879e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2880388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2881a9de9248SMarcel Holtmann 		}
2882a9de9248SMarcel Holtmann 	} else {
2883a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
2884a9de9248SMarcel Holtmann 
2885e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
2886a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
2887a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
2888a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
2889a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
2890a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
2891a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
2892a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
289341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
28943175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
2895388fc8faSJohan Hedberg 							      false, &ssp);
289648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
2897e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
2898388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
2899a9de9248SMarcel Holtmann 		}
2900a9de9248SMarcel Holtmann 	}
2901a9de9248SMarcel Holtmann 
2902a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2903a9de9248SMarcel Holtmann }
2904a9de9248SMarcel Holtmann 
29056039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
2906807deac2SGustavo Padovan 					struct sk_buff *skb)
2907a9de9248SMarcel Holtmann {
290841a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
290941a96212SMarcel Holtmann 	struct hci_conn *conn;
291041a96212SMarcel Holtmann 
2911a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
291241a96212SMarcel Holtmann 
291341a96212SMarcel Holtmann 	hci_dev_lock(hdev);
291441a96212SMarcel Holtmann 
291541a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2916ccd556feSJohan Hedberg 	if (!conn)
2917ccd556feSJohan Hedberg 		goto unlock;
2918ccd556feSJohan Hedberg 
2919769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
292041a96212SMarcel Holtmann 		struct inquiry_entry *ie;
292141a96212SMarcel Holtmann 
2922cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
2923cc11b9c1SAndrei Emeltchenko 		if (ie)
292402b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
292541a96212SMarcel Holtmann 
292602b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
292758a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
292841a96212SMarcel Holtmann 	}
292941a96212SMarcel Holtmann 
2930ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2931ccd556feSJohan Hedberg 		goto unlock;
2932ccd556feSJohan Hedberg 
2933671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2934127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2935127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2936127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2937127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2938127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2939b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2940b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
294108c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2942b644ba33SJohan Hedberg 				      conn->dev_class);
2943392599b9SJohan Hedberg 
2944127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2945769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2946769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2947769be974SMarcel Holtmann 		hci_conn_put(conn);
2948769be974SMarcel Holtmann 	}
2949769be974SMarcel Holtmann 
2950ccd556feSJohan Hedberg unlock:
295141a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
2952a9de9248SMarcel Holtmann }
2953a9de9248SMarcel Holtmann 
29546039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
2955807deac2SGustavo Padovan 				       struct sk_buff *skb)
2956a9de9248SMarcel Holtmann {
2957b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
2958b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
2959b6a0dc82SMarcel Holtmann 
29609f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2961b6a0dc82SMarcel Holtmann 
2962b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
2963b6a0dc82SMarcel Holtmann 
2964b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
29659dc0a3afSMarcel Holtmann 	if (!conn) {
29669dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
29679dc0a3afSMarcel Holtmann 			goto unlock;
29689dc0a3afSMarcel Holtmann 
29699dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
2970b6a0dc82SMarcel Holtmann 		if (!conn)
2971b6a0dc82SMarcel Holtmann 			goto unlock;
2972b6a0dc82SMarcel Holtmann 
29739dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
29749dc0a3afSMarcel Holtmann 	}
29759dc0a3afSMarcel Holtmann 
2976732547f9SMarcel Holtmann 	switch (ev->status) {
2977732547f9SMarcel Holtmann 	case 0x00:
2978732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
2979732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
2980732547f9SMarcel Holtmann 
29819eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
2982732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
2983732547f9SMarcel Holtmann 		break;
2984732547f9SMarcel Holtmann 
2985705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
2986732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
29871038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
2988732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
2989732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
2990efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
2991efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
2992efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
2993efc7688bSMarcel Holtmann 			goto unlock;
2994efc7688bSMarcel Holtmann 		}
2995732547f9SMarcel Holtmann 		/* fall through */
2996efc7688bSMarcel Holtmann 
2997732547f9SMarcel Holtmann 	default:
2998b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
2999732547f9SMarcel Holtmann 		break;
3000732547f9SMarcel Holtmann 	}
3001b6a0dc82SMarcel Holtmann 
3002b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3003b6a0dc82SMarcel Holtmann 	if (ev->status)
3004b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3005b6a0dc82SMarcel Holtmann 
3006b6a0dc82SMarcel Holtmann unlock:
3007b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3008a9de9248SMarcel Holtmann }
3009a9de9248SMarcel Holtmann 
30106039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
3011a9de9248SMarcel Holtmann {
3012a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3013a9de9248SMarcel Holtmann }
3014a9de9248SMarcel Holtmann 
30156039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
301604837f64SMarcel Holtmann {
3017a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
301804837f64SMarcel Holtmann 
30199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
302004837f64SMarcel Holtmann }
302104837f64SMarcel Holtmann 
30226039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3023807deac2SGustavo Padovan 					    struct sk_buff *skb)
3024a9de9248SMarcel Holtmann {
3025a9de9248SMarcel Holtmann 	struct inquiry_data data;
3026a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3027a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
30289d939d94SVishal Agarwal 	size_t eir_len;
3029a9de9248SMarcel Holtmann 
3030a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3031a9de9248SMarcel Holtmann 
3032a9de9248SMarcel Holtmann 	if (!num_rsp)
3033a9de9248SMarcel Holtmann 		return;
3034a9de9248SMarcel Holtmann 
30351519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30361519cc17SAndre Guedes 		return;
30371519cc17SAndre Guedes 
3038a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3039a9de9248SMarcel Holtmann 
3040e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3041388fc8faSJohan Hedberg 		bool name_known, ssp;
3042561aafbcSJohan Hedberg 
3043a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3044a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3045a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3046a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3047a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3048a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3049a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
305041a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3051561aafbcSJohan Hedberg 
3052a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
30534ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
30544ddb1930SJohan Hedberg 						       sizeof(info->data),
30554ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3056561aafbcSJohan Hedberg 		else
3057561aafbcSJohan Hedberg 			name_known = true;
3058561aafbcSJohan Hedberg 
3059388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3060388fc8faSJohan Hedberg 						      &ssp);
30619d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
306248264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
306304124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
30649d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3065a9de9248SMarcel Holtmann 	}
3066a9de9248SMarcel Holtmann 
3067a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3068a9de9248SMarcel Holtmann }
3069a9de9248SMarcel Holtmann 
30701c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
30711c2e0041SJohan Hedberg 					 struct sk_buff *skb)
30721c2e0041SJohan Hedberg {
30731c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
30741c2e0041SJohan Hedberg 	struct hci_conn *conn;
30751c2e0041SJohan Hedberg 
30769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
30771c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
30781c2e0041SJohan Hedberg 
30791c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
30801c2e0041SJohan Hedberg 
30811c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30821c2e0041SJohan Hedberg 	if (!conn)
30831c2e0041SJohan Hedberg 		goto unlock;
30841c2e0041SJohan Hedberg 
30851c2e0041SJohan Hedberg 	if (!ev->status)
30861c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
30871c2e0041SJohan Hedberg 
30881c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
30891c2e0041SJohan Hedberg 
30901c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
30911c2e0041SJohan Hedberg 		hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
30921c2e0041SJohan Hedberg 		hci_conn_put(conn);
30931c2e0041SJohan Hedberg 		goto unlock;
30941c2e0041SJohan Hedberg 	}
30951c2e0041SJohan Hedberg 
30961c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
30971c2e0041SJohan Hedberg 		if (!ev->status)
30981c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
30991c2e0041SJohan Hedberg 
31001c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
31011c2e0041SJohan Hedberg 		hci_conn_put(conn);
31021c2e0041SJohan Hedberg 	} else {
31031c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
31041c2e0041SJohan Hedberg 
31051c2e0041SJohan Hedberg 		hci_conn_hold(conn);
31061c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
31071c2e0041SJohan Hedberg 		hci_conn_put(conn);
31081c2e0041SJohan Hedberg 	}
31091c2e0041SJohan Hedberg 
31101c2e0041SJohan Hedberg unlock:
31111c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
31121c2e0041SJohan Hedberg }
31131c2e0041SJohan Hedberg 
31146039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
311517fa4b9dSJohan Hedberg {
311617fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
311717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
311817fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
311917fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
312017fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
312117fa4b9dSJohan Hedberg 			return 0x02;
312217fa4b9dSJohan Hedberg 		else
312317fa4b9dSJohan Hedberg 			return 0x03;
312417fa4b9dSJohan Hedberg 	}
312517fa4b9dSJohan Hedberg 
312617fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
312717fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
312858797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
312917fa4b9dSJohan Hedberg 
313017fa4b9dSJohan Hedberg 	return conn->auth_type;
313117fa4b9dSJohan Hedberg }
313217fa4b9dSJohan Hedberg 
31336039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
31340493684eSMarcel Holtmann {
31350493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
31360493684eSMarcel Holtmann 	struct hci_conn *conn;
31370493684eSMarcel Holtmann 
31380493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
31390493684eSMarcel Holtmann 
31400493684eSMarcel Holtmann 	hci_dev_lock(hdev);
31410493684eSMarcel Holtmann 
31420493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
314303b555e1SJohan Hedberg 	if (!conn)
314403b555e1SJohan Hedberg 		goto unlock;
314503b555e1SJohan Hedberg 
31460493684eSMarcel Holtmann 	hci_conn_hold(conn);
31470493684eSMarcel Holtmann 
3148a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
314903b555e1SJohan Hedberg 		goto unlock;
315003b555e1SJohan Hedberg 
3151a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
315203b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
315317fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
315417fa4b9dSJohan Hedberg 
315517fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31567a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
31577a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
31587a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
31597a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
31607cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
31617cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
316217fa4b9dSJohan Hedberg 
31638fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
31648fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3165ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3166ce85ee13SSzymon Janc 		else
3167ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3168ce85ee13SSzymon Janc 
316917fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
317017fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
317103b555e1SJohan Hedberg 	} else {
317203b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
317303b555e1SJohan Hedberg 
317403b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
31759f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
317603b555e1SJohan Hedberg 
317703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
317803b555e1SJohan Hedberg 			     sizeof(cp), &cp);
317903b555e1SJohan Hedberg 	}
318003b555e1SJohan Hedberg 
318103b555e1SJohan Hedberg unlock:
318203b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
318303b555e1SJohan Hedberg }
318403b555e1SJohan Hedberg 
31856039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
318603b555e1SJohan Hedberg {
318703b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
318803b555e1SJohan Hedberg 	struct hci_conn *conn;
318903b555e1SJohan Hedberg 
319003b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
319103b555e1SJohan Hedberg 
319203b555e1SJohan Hedberg 	hci_dev_lock(hdev);
319303b555e1SJohan Hedberg 
319403b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
319503b555e1SJohan Hedberg 	if (!conn)
319603b555e1SJohan Hedberg 		goto unlock;
319703b555e1SJohan Hedberg 
319803b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
319903b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
320058a681efSJohan Hedberg 	if (ev->oob_data)
320158a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
320203b555e1SJohan Hedberg 
320303b555e1SJohan Hedberg unlock:
32040493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
32050493684eSMarcel Holtmann }
32060493684eSMarcel Holtmann 
32076039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3208a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3209a5c29683SJohan Hedberg {
3210a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
321155bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
32127a828908SJohan Hedberg 	struct hci_conn *conn;
3213a5c29683SJohan Hedberg 
3214a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3215a5c29683SJohan Hedberg 
3216a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3217a5c29683SJohan Hedberg 
3218a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
32197a828908SJohan Hedberg 		goto unlock;
32207a828908SJohan Hedberg 
32217a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
32227a828908SJohan Hedberg 	if (!conn)
32237a828908SJohan Hedberg 		goto unlock;
32247a828908SJohan Hedberg 
32257a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
32267a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
32277a828908SJohan Hedberg 
32287a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
32297a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
32307a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
32317a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
32327a828908SJohan Hedberg 	 * bit set. */
32337a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
32347a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
32357a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
32367a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
32377a828908SJohan Hedberg 		goto unlock;
32387a828908SJohan Hedberg 	}
32397a828908SJohan Hedberg 
32407a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
32417a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
32427a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
324355bc1a37SJohan Hedberg 
324455bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
324555bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
324655bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
324751a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
324855bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
324955bc1a37SJohan Hedberg 			confirm_hint = 1;
325055bc1a37SJohan Hedberg 			goto confirm;
325155bc1a37SJohan Hedberg 		}
325255bc1a37SJohan Hedberg 
32539f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
32549f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
32559f61656aSJohan Hedberg 
32569f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
32579f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
32589f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
32599f61656aSJohan Hedberg 			goto unlock;
32609f61656aSJohan Hedberg 		}
32619f61656aSJohan Hedberg 
32627a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
32637a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
32647a828908SJohan Hedberg 		goto unlock;
32657a828908SJohan Hedberg 	}
32667a828908SJohan Hedberg 
326755bc1a37SJohan Hedberg confirm:
3268272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
326955bc1a37SJohan Hedberg 				  confirm_hint);
3270a5c29683SJohan Hedberg 
32717a828908SJohan Hedberg unlock:
3272a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3273a5c29683SJohan Hedberg }
3274a5c29683SJohan Hedberg 
32756039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
32761143d458SBrian Gix 					 struct sk_buff *skb)
32771143d458SBrian Gix {
32781143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
32791143d458SBrian Gix 
32801143d458SBrian Gix 	BT_DBG("%s", hdev->name);
32811143d458SBrian Gix 
3282a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3283272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
32841143d458SBrian Gix }
32851143d458SBrian Gix 
328692a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
328792a25256SJohan Hedberg 					struct sk_buff *skb)
328892a25256SJohan Hedberg {
328992a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
329092a25256SJohan Hedberg 	struct hci_conn *conn;
329192a25256SJohan Hedberg 
329292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
329392a25256SJohan Hedberg 
329492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
329592a25256SJohan Hedberg 	if (!conn)
329692a25256SJohan Hedberg 		return;
329792a25256SJohan Hedberg 
329892a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
329992a25256SJohan Hedberg 	conn->passkey_entered = 0;
330092a25256SJohan Hedberg 
330192a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
330292a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
330392a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
330492a25256SJohan Hedberg 					 conn->passkey_entered);
330592a25256SJohan Hedberg }
330692a25256SJohan Hedberg 
330792a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
330892a25256SJohan Hedberg {
330992a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
331092a25256SJohan Hedberg 	struct hci_conn *conn;
331192a25256SJohan Hedberg 
331292a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
331392a25256SJohan Hedberg 
331492a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
331592a25256SJohan Hedberg 	if (!conn)
331692a25256SJohan Hedberg 		return;
331792a25256SJohan Hedberg 
331892a25256SJohan Hedberg 	switch (ev->type) {
331992a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
332092a25256SJohan Hedberg 		conn->passkey_entered = 0;
332192a25256SJohan Hedberg 		return;
332292a25256SJohan Hedberg 
332392a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
332492a25256SJohan Hedberg 		conn->passkey_entered++;
332592a25256SJohan Hedberg 		break;
332692a25256SJohan Hedberg 
332792a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
332892a25256SJohan Hedberg 		conn->passkey_entered--;
332992a25256SJohan Hedberg 		break;
333092a25256SJohan Hedberg 
333192a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
333292a25256SJohan Hedberg 		conn->passkey_entered = 0;
333392a25256SJohan Hedberg 		break;
333492a25256SJohan Hedberg 
333592a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
333692a25256SJohan Hedberg 		return;
333792a25256SJohan Hedberg 	}
333892a25256SJohan Hedberg 
333992a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
334092a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
334192a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
334292a25256SJohan Hedberg 					 conn->passkey_entered);
334392a25256SJohan Hedberg }
334492a25256SJohan Hedberg 
33456039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3346807deac2SGustavo Padovan 					 struct sk_buff *skb)
33470493684eSMarcel Holtmann {
33480493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
33490493684eSMarcel Holtmann 	struct hci_conn *conn;
33500493684eSMarcel Holtmann 
33510493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
33520493684eSMarcel Holtmann 
33530493684eSMarcel Holtmann 	hci_dev_lock(hdev);
33540493684eSMarcel Holtmann 
33550493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
33562a611692SJohan Hedberg 	if (!conn)
33572a611692SJohan Hedberg 		goto unlock;
33582a611692SJohan Hedberg 
33592a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
33602a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
33612a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
33622a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
33632a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3364fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3365bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3366bab73cb6SJohan Hedberg 				 ev->status);
33672a611692SJohan Hedberg 
33680493684eSMarcel Holtmann 	hci_conn_put(conn);
33690493684eSMarcel Holtmann 
33702a611692SJohan Hedberg unlock:
33710493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
33720493684eSMarcel Holtmann }
33730493684eSMarcel Holtmann 
33746039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3375807deac2SGustavo Padovan 					 struct sk_buff *skb)
337641a96212SMarcel Holtmann {
337741a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
337841a96212SMarcel Holtmann 	struct inquiry_entry *ie;
337941a96212SMarcel Holtmann 
338041a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
338141a96212SMarcel Holtmann 
338241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
338341a96212SMarcel Holtmann 
3384cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3385cc11b9c1SAndrei Emeltchenko 	if (ie)
338602b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
338741a96212SMarcel Holtmann 
338841a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
338941a96212SMarcel Holtmann }
339041a96212SMarcel Holtmann 
33916039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
33922763eda6SSzymon Janc 					    struct sk_buff *skb)
33932763eda6SSzymon Janc {
33942763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
33952763eda6SSzymon Janc 	struct oob_data *data;
33962763eda6SSzymon Janc 
33972763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
33982763eda6SSzymon Janc 
33992763eda6SSzymon Janc 	hci_dev_lock(hdev);
34002763eda6SSzymon Janc 
3401a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3402e1ba1f15SSzymon Janc 		goto unlock;
3403e1ba1f15SSzymon Janc 
34042763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
34052763eda6SSzymon Janc 	if (data) {
34062763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
34072763eda6SSzymon Janc 
34082763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
34092763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
34102763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
34112763eda6SSzymon Janc 
34122763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
34132763eda6SSzymon Janc 			     &cp);
34142763eda6SSzymon Janc 	} else {
34152763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
34162763eda6SSzymon Janc 
34172763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
34182763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
34192763eda6SSzymon Janc 			     &cp);
34202763eda6SSzymon Janc 	}
34212763eda6SSzymon Janc 
3422e1ba1f15SSzymon Janc unlock:
34232763eda6SSzymon Janc 	hci_dev_unlock(hdev);
34242763eda6SSzymon Janc }
34252763eda6SSzymon Janc 
34266039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3427fcd89c09SVille Tervo {
3428fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3429fcd89c09SVille Tervo 	struct hci_conn *conn;
3430fcd89c09SVille Tervo 
34319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3432fcd89c09SVille Tervo 
3433fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3434fcd89c09SVille Tervo 
34354f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3436b62f328bSVille Tervo 	if (!conn) {
3437b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3438b62f328bSVille Tervo 		if (!conn) {
3439b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3440230fd16aSAndre Guedes 			goto unlock;
3441b62f328bSVille Tervo 		}
344229b7988aSAndre Guedes 
344329b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3444b9b343d2SAndre Guedes 
3445b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3446b9b343d2SAndre Guedes 			conn->out = true;
3447b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3448b9b343d2SAndre Guedes 		}
3449b62f328bSVille Tervo 	}
3450fcd89c09SVille Tervo 
3451cd17decbSAndre Guedes 	if (ev->status) {
3452cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3453cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3454cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3455cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3456cd17decbSAndre Guedes 		hci_conn_del(conn);
3457cd17decbSAndre Guedes 		goto unlock;
3458cd17decbSAndre Guedes 	}
3459cd17decbSAndre Guedes 
3460b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3461b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
346295b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
346383bc71b4SVinicius Costa Gomes 
34647b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3465fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3466fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3467fcd89c09SVille Tervo 
3468fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3469fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3470fcd89c09SVille Tervo 
3471fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3472fcd89c09SVille Tervo 
3473fcd89c09SVille Tervo unlock:
3474fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3475fcd89c09SVille Tervo }
3476fcd89c09SVille Tervo 
34776039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
34789aa04c91SAndre Guedes {
3479e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3480e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
34813c9e9195SAndre Guedes 	s8 rssi;
34829aa04c91SAndre Guedes 
34839aa04c91SAndre Guedes 	hci_dev_lock(hdev);
34849aa04c91SAndre Guedes 
3485e95beb41SAndre Guedes 	while (num_reports--) {
3486e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3487e95beb41SAndre Guedes 
34883c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
34893c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
349004124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
34913c9e9195SAndre Guedes 
3492e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
34939aa04c91SAndre Guedes 	}
34949aa04c91SAndre Guedes 
34959aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
34969aa04c91SAndre Guedes }
34979aa04c91SAndre Guedes 
34986039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3499a7a595f6SVinicius Costa Gomes {
3500a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3501a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3502bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3503a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3504c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3505a7a595f6SVinicius Costa Gomes 
35069f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3507a7a595f6SVinicius Costa Gomes 
3508a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3509a7a595f6SVinicius Costa Gomes 
3510a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3511bea710feSVinicius Costa Gomes 	if (conn == NULL)
3512bea710feSVinicius Costa Gomes 		goto not_found;
3513a7a595f6SVinicius Costa Gomes 
3514bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3515bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3516bea710feSVinicius Costa Gomes 		goto not_found;
3517bea710feSVinicius Costa Gomes 
3518bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3519a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3520c9839a11SVinicius Costa Gomes 
3521c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3522c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3523a7a595f6SVinicius Costa Gomes 
3524a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3525a7a595f6SVinicius Costa Gomes 
3526c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3527c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3528c9839a11SVinicius Costa Gomes 		kfree(ltk);
3529c9839a11SVinicius Costa Gomes 	}
3530c9839a11SVinicius Costa Gomes 
3531a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3532bea710feSVinicius Costa Gomes 
3533bea710feSVinicius Costa Gomes 	return;
3534bea710feSVinicius Costa Gomes 
3535bea710feSVinicius Costa Gomes not_found:
3536bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3537bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3538bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3539a7a595f6SVinicius Costa Gomes }
3540a7a595f6SVinicius Costa Gomes 
35416039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3542fcd89c09SVille Tervo {
3543fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3544fcd89c09SVille Tervo 
3545fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3546fcd89c09SVille Tervo 
3547fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3548fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3549fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3550fcd89c09SVille Tervo 		break;
3551fcd89c09SVille Tervo 
35529aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
35539aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
35549aa04c91SAndre Guedes 		break;
35559aa04c91SAndre Guedes 
3556a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3557a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3558a7a595f6SVinicius Costa Gomes 		break;
3559a7a595f6SVinicius Costa Gomes 
3560fcd89c09SVille Tervo 	default:
3561fcd89c09SVille Tervo 		break;
3562fcd89c09SVille Tervo 	}
3563fcd89c09SVille Tervo }
3564fcd89c09SVille Tervo 
35651da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
35661da177e4SLinus Torvalds {
3567a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3568a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
35691da177e4SLinus Torvalds 
35701da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
35711da177e4SLinus Torvalds 
3572a9de9248SMarcel Holtmann 	switch (event) {
35731da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
35741da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
35751da177e4SLinus Torvalds 		break;
35761da177e4SLinus Torvalds 
35771da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
35781da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
35791da177e4SLinus Torvalds 		break;
35801da177e4SLinus Torvalds 
3581a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3582a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
358321d9e30eSMarcel Holtmann 		break;
358421d9e30eSMarcel Holtmann 
35851da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
35861da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
35871da177e4SLinus Torvalds 		break;
35881da177e4SLinus Torvalds 
35891da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
35901da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
35911da177e4SLinus Torvalds 		break;
35921da177e4SLinus Torvalds 
35931da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
35941da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
35951da177e4SLinus Torvalds 		break;
35961da177e4SLinus Torvalds 
3597a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3598a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3599a9de9248SMarcel Holtmann 		break;
3600a9de9248SMarcel Holtmann 
36011da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
36021da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
36031da177e4SLinus Torvalds 		break;
36041da177e4SLinus Torvalds 
3605a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3606a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3607a9de9248SMarcel Holtmann 		break;
3608a9de9248SMarcel Holtmann 
3609a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3610a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3611a9de9248SMarcel Holtmann 		break;
3612a9de9248SMarcel Holtmann 
3613a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3614a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3615a9de9248SMarcel Holtmann 		break;
3616a9de9248SMarcel Holtmann 
3617a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3618a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3619a9de9248SMarcel Holtmann 		break;
3620a9de9248SMarcel Holtmann 
3621a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3622a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3623a9de9248SMarcel Holtmann 		break;
3624a9de9248SMarcel Holtmann 
3625a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3626a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3627a9de9248SMarcel Holtmann 		break;
3628a9de9248SMarcel Holtmann 
3629a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3630a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3631a9de9248SMarcel Holtmann 		break;
3632a9de9248SMarcel Holtmann 
3633a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3634a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3635a9de9248SMarcel Holtmann 		break;
3636a9de9248SMarcel Holtmann 
3637a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3638a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
36391da177e4SLinus Torvalds 		break;
36401da177e4SLinus Torvalds 
36411da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
36421da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
36431da177e4SLinus Torvalds 		break;
36441da177e4SLinus Torvalds 
36451da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
36461da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
36471da177e4SLinus Torvalds 		break;
36481da177e4SLinus Torvalds 
36491da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
36501da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
36511da177e4SLinus Torvalds 		break;
36521da177e4SLinus Torvalds 
36531da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
36541da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
36551da177e4SLinus Torvalds 		break;
36561da177e4SLinus Torvalds 
3657a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3658a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3659a8746417SMarcel Holtmann 		break;
3660a8746417SMarcel Holtmann 
366185a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
366285a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
366385a1e930SMarcel Holtmann 		break;
366485a1e930SMarcel Holtmann 
3665a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3666a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3667a9de9248SMarcel Holtmann 		break;
3668a9de9248SMarcel Holtmann 
3669a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3670a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3671a9de9248SMarcel Holtmann 		break;
3672a9de9248SMarcel Holtmann 
3673a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3674a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3675a9de9248SMarcel Holtmann 		break;
3676a9de9248SMarcel Holtmann 
3677a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3678a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3679a9de9248SMarcel Holtmann 		break;
3680a9de9248SMarcel Holtmann 
368104837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
368204837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
368304837f64SMarcel Holtmann 		break;
368404837f64SMarcel Holtmann 
3685a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3686a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
36871da177e4SLinus Torvalds 		break;
36881da177e4SLinus Torvalds 
36891c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
36901c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
36911c2e0041SJohan Hedberg 		break;
36921c2e0041SJohan Hedberg 
36930493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
36940493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
36950493684eSMarcel Holtmann 		break;
36960493684eSMarcel Holtmann 
369703b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
369803b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
369903b555e1SJohan Hedberg 		break;
370003b555e1SJohan Hedberg 
3701a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3702a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3703a5c29683SJohan Hedberg 		break;
3704a5c29683SJohan Hedberg 
37051143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
37061143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
37071143d458SBrian Gix 		break;
37081143d458SBrian Gix 
370992a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
371092a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
371192a25256SJohan Hedberg 		break;
371292a25256SJohan Hedberg 
371392a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
371492a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
371592a25256SJohan Hedberg 		break;
371692a25256SJohan Hedberg 
37170493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
37180493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
37190493684eSMarcel Holtmann 		break;
37200493684eSMarcel Holtmann 
372141a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
372241a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
372341a96212SMarcel Holtmann 		break;
372441a96212SMarcel Holtmann 
3725fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3726fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3727fcd89c09SVille Tervo 		break;
3728fcd89c09SVille Tervo 
37292763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
37302763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
37312763eda6SSzymon Janc 		break;
37322763eda6SSzymon Janc 
373325e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
373425e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
373525e89e99SAndrei Emeltchenko 		break;
373625e89e99SAndrei Emeltchenko 
37371da177e4SLinus Torvalds 	default:
37389f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
37391da177e4SLinus Torvalds 		break;
37401da177e4SLinus Torvalds 	}
37411da177e4SLinus Torvalds 
37421da177e4SLinus Torvalds 	kfree_skb(skb);
37431da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
37441da177e4SLinus Torvalds }
3745