xref: /openbmc/linux/net/bluetooth/hci_event.c (revision e58917b9)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds    BlueZ - Bluetooth protocol stack for Linux
32d0a0346SRon Shaffer    Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds    This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds    it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds    published by the Free Software Foundation;
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
121da177e4SLinus Torvalds    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131da177e4SLinus Torvalds    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
141da177e4SLinus Torvalds    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
151da177e4SLinus Torvalds    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
161da177e4SLinus Torvalds    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
171da177e4SLinus Torvalds    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
181da177e4SLinus Torvalds    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
211da177e4SLinus Torvalds    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
221da177e4SLinus Torvalds    SOFTWARE IS DISCLAIMED.
231da177e4SLinus Torvalds */
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds #include <asm/unaligned.h>
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
31f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h>
328e2a0d92SAndrei Emeltchenko #include <net/bluetooth/a2mp.h>
33903e4541SAndrei Emeltchenko #include <net/bluetooth/amp.h>
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds /* Handle HCI Event packets */
361da177e4SLinus Torvalds 
37a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
381da177e4SLinus Torvalds {
39a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
401da177e4SLinus Torvalds 
419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
421da177e4SLinus Torvalds 
43e6d465cbSAndre Guedes 	if (status) {
44e6d465cbSAndre Guedes 		hci_dev_lock(hdev);
45e6d465cbSAndre Guedes 		mgmt_stop_discovery_failed(hdev, status);
46e6d465cbSAndre Guedes 		hci_dev_unlock(hdev);
47a9de9248SMarcel Holtmann 		return;
48e6d465cbSAndre Guedes 	}
491da177e4SLinus Torvalds 
5089352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
5189352e7dSAndre Guedes 
5256e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
53ff9ef578SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
5456e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
55a9de9248SMarcel Holtmann 
5623bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
57a9de9248SMarcel Holtmann 
58a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
591da177e4SLinus Torvalds }
606bd57416SMarcel Holtmann 
614d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
624d93483bSAndre Guedes {
634d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
644d93483bSAndre Guedes 
659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
66ae854a70SAndre Guedes 
67ae854a70SAndre Guedes 	if (status)
68ae854a70SAndre Guedes 		return;
69ae854a70SAndre Guedes 
70ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
714d93483bSAndre Guedes }
724d93483bSAndre Guedes 
73a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
741da177e4SLinus Torvalds {
75a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
76a9de9248SMarcel Holtmann 
779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
78a9de9248SMarcel Holtmann 
79a9de9248SMarcel Holtmann 	if (status)
80a9de9248SMarcel Holtmann 		return;
81a9de9248SMarcel Holtmann 
82ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
83ae854a70SAndre Guedes 
84a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
85a9de9248SMarcel Holtmann }
86a9de9248SMarcel Holtmann 
87807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
88807deac2SGustavo Padovan 					  struct sk_buff *skb)
89a9de9248SMarcel Holtmann {
90a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
91a9de9248SMarcel Holtmann }
92a9de9248SMarcel Holtmann 
93a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
94a9de9248SMarcel Holtmann {
95a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
961da177e4SLinus Torvalds 	struct hci_conn *conn;
971da177e4SLinus Torvalds 
989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
991da177e4SLinus Torvalds 
100a9de9248SMarcel Holtmann 	if (rp->status)
101a9de9248SMarcel Holtmann 		return;
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1041da177e4SLinus Torvalds 
105a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1061da177e4SLinus Torvalds 	if (conn) {
107a9de9248SMarcel Holtmann 		if (rp->role)
1081da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1091da177e4SLinus Torvalds 		else
1101da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1111da177e4SLinus Torvalds 	}
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
114a9de9248SMarcel Holtmann }
1151da177e4SLinus Torvalds 
116e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
117e4e8e37cSMarcel Holtmann {
118e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
119e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
120e4e8e37cSMarcel Holtmann 
1219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
122e4e8e37cSMarcel Holtmann 
123e4e8e37cSMarcel Holtmann 	if (rp->status)
124e4e8e37cSMarcel Holtmann 		return;
125e4e8e37cSMarcel Holtmann 
126e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
127e4e8e37cSMarcel Holtmann 
128e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
129e4e8e37cSMarcel Holtmann 	if (conn)
130e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
131e4e8e37cSMarcel Holtmann 
132e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
133e4e8e37cSMarcel Holtmann }
134e4e8e37cSMarcel Holtmann 
135a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
136a9de9248SMarcel Holtmann {
137a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
138a9de9248SMarcel Holtmann 	struct hci_conn *conn;
139a9de9248SMarcel Holtmann 	void *sent;
140a9de9248SMarcel Holtmann 
1419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
142a9de9248SMarcel Holtmann 
143a9de9248SMarcel Holtmann 	if (rp->status)
144a9de9248SMarcel Holtmann 		return;
145a9de9248SMarcel Holtmann 
146a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14704837f64SMarcel Holtmann 	if (!sent)
148a9de9248SMarcel Holtmann 		return;
14904837f64SMarcel Holtmann 
15004837f64SMarcel Holtmann 	hci_dev_lock(hdev);
15104837f64SMarcel Holtmann 
152a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
153e4e8e37cSMarcel Holtmann 	if (conn)
15483985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15504837f64SMarcel Holtmann 
15604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds 
159807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
160807deac2SGustavo Padovan 					struct sk_buff *skb)
161e4e8e37cSMarcel Holtmann {
162e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
163e4e8e37cSMarcel Holtmann 
1649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
165e4e8e37cSMarcel Holtmann 
166e4e8e37cSMarcel Holtmann 	if (rp->status)
167e4e8e37cSMarcel Holtmann 		return;
168e4e8e37cSMarcel Holtmann 
169e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
170e4e8e37cSMarcel Holtmann }
171e4e8e37cSMarcel Holtmann 
172807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
173807deac2SGustavo Padovan 					 struct sk_buff *skb)
174e4e8e37cSMarcel Holtmann {
175e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
176e4e8e37cSMarcel Holtmann 	void *sent;
177e4e8e37cSMarcel Holtmann 
1789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
179e4e8e37cSMarcel Holtmann 
180e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
181e4e8e37cSMarcel Holtmann 	if (!sent)
182e4e8e37cSMarcel Holtmann 		return;
183e4e8e37cSMarcel Holtmann 
184e4e8e37cSMarcel Holtmann 	if (!status)
185e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
186e4e8e37cSMarcel Holtmann 
18723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
188e4e8e37cSMarcel Holtmann }
189e4e8e37cSMarcel Holtmann 
190a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1911da177e4SLinus Torvalds {
192a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
193a9de9248SMarcel Holtmann 
1949f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
195a9de9248SMarcel Holtmann 
19610572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19710572132SGustavo F. Padovan 
19823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
199d23264a8SAndre Guedes 
200a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
201ae854a70SAndre Guedes 	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
202ae854a70SAndre Guedes 			     BIT(HCI_PERIODIC_INQ));
20369775ff6SAndre Guedes 
20469775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
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);
4425ed8eb2fSJohan Hedberg 	struct hci_cp_write_ssp_mode *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 
4505ed8eb2fSJohan Hedberg 	if (!status) {
4515ed8eb2fSJohan Hedberg 		if (sent->mode)
4525ed8eb2fSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_SSP;
4535ed8eb2fSJohan Hedberg 		else
4545ed8eb2fSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_SSP;
4555ed8eb2fSJohan Hedberg 	}
4565ed8eb2fSJohan Hedberg 
457c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
4585ed8eb2fSJohan Hedberg 		mgmt_ssp_enable_complete(hdev, sent->mode, status);
459c0ecddc2SJohan Hedberg 	else if (!status) {
4605ed8eb2fSJohan Hedberg 		if (sent->mode)
46184bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
46284bde9d6SJohan Hedberg 		else
46384bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
464c0ecddc2SJohan Hedberg 	}
465333140b5SMarcel Holtmann }
466333140b5SMarcel Holtmann 
467d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
468d5859e22SJohan Hedberg {
469976eb20eSJohan Hedberg 	if (lmp_ext_inq_capable(hdev))
470d5859e22SJohan Hedberg 		return 2;
471d5859e22SJohan Hedberg 
472976eb20eSJohan Hedberg 	if (lmp_inq_rssi_capable(hdev))
473d5859e22SJohan Hedberg 		return 1;
474d5859e22SJohan Hedberg 
475d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
476d5859e22SJohan Hedberg 	    hdev->lmp_subver == 0x0757)
477d5859e22SJohan Hedberg 		return 1;
478d5859e22SJohan Hedberg 
479d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
480d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
481d5859e22SJohan Hedberg 			return 1;
482d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
483d5859e22SJohan Hedberg 			return 1;
484d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
485d5859e22SJohan Hedberg 			return 1;
486d5859e22SJohan Hedberg 	}
487d5859e22SJohan Hedberg 
488d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
489d5859e22SJohan Hedberg 	    hdev->lmp_subver == 0x1805)
490d5859e22SJohan Hedberg 		return 1;
491d5859e22SJohan Hedberg 
492d5859e22SJohan Hedberg 	return 0;
493d5859e22SJohan Hedberg }
494d5859e22SJohan Hedberg 
495d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
496d5859e22SJohan Hedberg {
497d5859e22SJohan Hedberg 	u8 mode;
498d5859e22SJohan Hedberg 
499d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
500d5859e22SJohan Hedberg 
501d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
502d5859e22SJohan Hedberg }
503d5859e22SJohan Hedberg 
504d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
505d5859e22SJohan Hedberg {
506d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
507d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
508d5859e22SJohan Hedberg 	 * command otherwise */
509d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
510d5859e22SJohan Hedberg 
5116de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5126de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5135a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
5146de6c18dSVille Tervo 		return;
5156de6c18dSVille Tervo 
516e1171e8dSJohan Hedberg 	if (lmp_bredr_capable(hdev)) {
517d5859e22SJohan Hedberg 		events[4] |= 0x01; /* Flow Specification Complete */
518d5859e22SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
519d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Read Remote Extended Features Complete */
520d5859e22SJohan Hedberg 		events[5] |= 0x08; /* Synchronous Connection Complete */
521d5859e22SJohan Hedberg 		events[5] |= 0x10; /* Synchronous Connection Changed */
522e1171e8dSJohan Hedberg 	}
523d5859e22SJohan Hedberg 
524976eb20eSJohan Hedberg 	if (lmp_inq_rssi_capable(hdev))
525a24299e6SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
526d5859e22SJohan Hedberg 
527999dcd10SAndre Guedes 	if (lmp_sniffsubr_capable(hdev))
528d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
529d5859e22SJohan Hedberg 
530976eb20eSJohan Hedberg 	if (lmp_pause_enc_capable(hdev))
531d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
532d5859e22SJohan Hedberg 
533976eb20eSJohan Hedberg 	if (lmp_ext_inq_capable(hdev))
534d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
535d5859e22SJohan Hedberg 
536c58e810eSAndre Guedes 	if (lmp_no_flush_capable(hdev))
537d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
538d5859e22SJohan Hedberg 
539976eb20eSJohan Hedberg 	if (lmp_lsto_capable(hdev))
540d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
541d5859e22SJohan Hedberg 
5429a1a1996SAndre Guedes 	if (lmp_ssp_capable(hdev)) {
543d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
544d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
545d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
546d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
547d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
548d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
549d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
550d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
551d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
552d5859e22SJohan Hedberg 					 * Features Notification */
553d5859e22SJohan Hedberg 	}
554d5859e22SJohan Hedberg 
555c383ddc4SAndre Guedes 	if (lmp_le_capable(hdev))
556d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
557d5859e22SJohan Hedberg 
558d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
559e36b04c8SJohan Hedberg 
560e36b04c8SJohan Hedberg 	if (lmp_le_capable(hdev)) {
561e36b04c8SJohan Hedberg 		memset(events, 0, sizeof(events));
562e36b04c8SJohan Hedberg 		events[0] = 0x1f;
563e36b04c8SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
564e36b04c8SJohan Hedberg 			     sizeof(events), events);
565e36b04c8SJohan Hedberg 	}
566d5859e22SJohan Hedberg }
567d5859e22SJohan Hedberg 
5684611dfa8SGustavo Padovan static void bredr_setup(struct hci_dev *hdev)
569e1171e8dSJohan Hedberg {
570e1171e8dSJohan Hedberg 	struct hci_cp_delete_stored_link_key cp;
571e1171e8dSJohan Hedberg 	__le16 param;
572e1171e8dSJohan Hedberg 	__u8 flt_type;
573e1171e8dSJohan Hedberg 
574e1171e8dSJohan Hedberg 	/* Read Buffer Size (ACL mtu, max pkt, etc.) */
575e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
576e1171e8dSJohan Hedberg 
577e1171e8dSJohan Hedberg 	/* Read Class of Device */
578e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
579e1171e8dSJohan Hedberg 
580e1171e8dSJohan Hedberg 	/* Read Local Name */
581e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
582e1171e8dSJohan Hedberg 
583e1171e8dSJohan Hedberg 	/* Read Voice Setting */
584e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
585e1171e8dSJohan Hedberg 
586e1171e8dSJohan Hedberg 	/* Clear Event Filters */
587e1171e8dSJohan Hedberg 	flt_type = HCI_FLT_CLEAR_ALL;
588e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
589e1171e8dSJohan Hedberg 
590e1171e8dSJohan Hedberg 	/* Connection accept timeout ~20 secs */
591e1171e8dSJohan Hedberg 	param = __constant_cpu_to_le16(0x7d00);
592e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
593e1171e8dSJohan Hedberg 
594e1171e8dSJohan Hedberg 	bacpy(&cp.bdaddr, BDADDR_ANY);
595e1171e8dSJohan Hedberg 	cp.delete_all = 1;
596e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
597e1171e8dSJohan Hedberg }
598e1171e8dSJohan Hedberg 
5994611dfa8SGustavo Padovan static void le_setup(struct hci_dev *hdev)
600e1171e8dSJohan Hedberg {
601e1171e8dSJohan Hedberg 	/* Read LE Buffer Size */
602e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
6038fa19098SJohan Hedberg 
6048fa19098SJohan Hedberg 	/* Read LE Advertising Channel TX Power */
6058fa19098SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
606e1171e8dSJohan Hedberg }
607e1171e8dSJohan Hedberg 
608d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
609d5859e22SJohan Hedberg {
610e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
611e61ef499SAndrei Emeltchenko 		return;
612e61ef499SAndrei Emeltchenko 
613e1171e8dSJohan Hedberg 	/* Read BD Address */
614e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
615e1171e8dSJohan Hedberg 
616e1171e8dSJohan Hedberg 	if (lmp_bredr_capable(hdev))
6174611dfa8SGustavo Padovan 		bredr_setup(hdev);
618e1171e8dSJohan Hedberg 
619e1171e8dSJohan Hedberg 	if (lmp_le_capable(hdev))
6204611dfa8SGustavo Padovan 		le_setup(hdev);
621e1171e8dSJohan Hedberg 
622d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
623d5859e22SJohan Hedberg 
624d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
625d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
626d5859e22SJohan Hedberg 
6276d3c730fSGustavo Padovan 	if (lmp_ssp_capable(hdev)) {
62854d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
629d5859e22SJohan Hedberg 			u8 mode = 0x01;
63054d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
63154d04dbbSJohan Hedberg 				     sizeof(mode), &mode);
63254d04dbbSJohan Hedberg 		} else {
63354d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
63454d04dbbSJohan Hedberg 
63554d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
63654d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
63754d04dbbSJohan Hedberg 
63854d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
63954d04dbbSJohan Hedberg 		}
640d5859e22SJohan Hedberg 	}
641d5859e22SJohan Hedberg 
642976eb20eSJohan Hedberg 	if (lmp_inq_rssi_capable(hdev))
643d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
644d5859e22SJohan Hedberg 
645976eb20eSJohan Hedberg 	if (lmp_inq_tx_pwr_capable(hdev))
646d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
647971e3a4bSAndre Guedes 
648976eb20eSJohan Hedberg 	if (lmp_ext_feat_capable(hdev)) {
649971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
650971e3a4bSAndre Guedes 
651971e3a4bSAndre Guedes 		cp.page = 0x01;
65204124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
65304124681SGustavo F. Padovan 			     &cp);
654971e3a4bSAndre Guedes 	}
655e6100a25SAndre Guedes 
65647990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
65747990ea0SJohan Hedberg 		u8 enable = 1;
65804124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
65904124681SGustavo F. Padovan 			     &enable);
66047990ea0SJohan Hedberg 	}
661d5859e22SJohan Hedberg }
662d5859e22SJohan Hedberg 
663a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
664a9de9248SMarcel Holtmann {
665a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6661143e5a6SMarcel Holtmann 
6679f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
6681143e5a6SMarcel Holtmann 
669a9de9248SMarcel Holtmann 	if (rp->status)
67028b8df77SAndrei Emeltchenko 		goto done;
6711143e5a6SMarcel Holtmann 
672a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
673e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
674d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
675e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
676d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6771da177e4SLinus Torvalds 
6789f1db00cSAndrei Emeltchenko 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
679807deac2SGustavo Padovan 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
680d5859e22SJohan Hedberg 
681d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
682d5859e22SJohan Hedberg 		hci_setup(hdev);
68328b8df77SAndrei Emeltchenko 
68428b8df77SAndrei Emeltchenko done:
68528b8df77SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
686d5859e22SJohan Hedberg }
687d5859e22SJohan Hedberg 
688d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
689d5859e22SJohan Hedberg {
690035100c8SAndrei Emeltchenko 	struct hci_cp_write_def_link_policy cp;
691d5859e22SJohan Hedberg 	u16 link_policy = 0;
692d5859e22SJohan Hedberg 
6939f92ebf6SAndre Guedes 	if (lmp_rswitch_capable(hdev))
694d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
695976eb20eSJohan Hedberg 	if (lmp_hold_capable(hdev))
696d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
6976eded100SAndre Guedes 	if (lmp_sniff_capable(hdev))
698d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
699976eb20eSJohan Hedberg 	if (lmp_park_capable(hdev))
700d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
701d5859e22SJohan Hedberg 
702035100c8SAndrei Emeltchenko 	cp.policy = cpu_to_le16(link_policy);
703035100c8SAndrei Emeltchenko 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
7041da177e4SLinus Torvalds }
7051da177e4SLinus Torvalds 
7068fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
7078fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
708a9de9248SMarcel Holtmann {
709a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
710a9de9248SMarcel Holtmann 
7119f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
712a9de9248SMarcel Holtmann 
713a9de9248SMarcel Holtmann 	if (rp->status)
714d5859e22SJohan Hedberg 		goto done;
715a9de9248SMarcel Holtmann 
716a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
717d5859e22SJohan Hedberg 
718d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
719d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
720d5859e22SJohan Hedberg 
721d5859e22SJohan Hedberg done:
722d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
723a9de9248SMarcel Holtmann }
724a9de9248SMarcel Holtmann 
7258fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
7268fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
727a9de9248SMarcel Holtmann {
728a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
729a9de9248SMarcel Holtmann 
7309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
731a9de9248SMarcel Holtmann 
732a9de9248SMarcel Holtmann 	if (rp->status)
733a9de9248SMarcel Holtmann 		return;
734a9de9248SMarcel Holtmann 
735a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
7361da177e4SLinus Torvalds 
7371da177e4SLinus Torvalds 	/* Adjust default settings according to features
7381da177e4SLinus Torvalds 	 * supported by device. */
739a9de9248SMarcel Holtmann 
7401da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
7411da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
7421da177e4SLinus Torvalds 
7431da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
7441da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
7451da177e4SLinus Torvalds 
7465b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
7471da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
7485b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
7495b7f9909SMarcel Holtmann 	}
7501da177e4SLinus Torvalds 
7515b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
7521da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
7535b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
7545b7f9909SMarcel Holtmann 	}
7555b7f9909SMarcel Holtmann 
75645db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
7575b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
7585b7f9909SMarcel Holtmann 
7595b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
7605b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
7615b7f9909SMarcel Holtmann 
7625b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
7635b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
7641da177e4SLinus Torvalds 
765efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
766efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
767efc7688bSMarcel Holtmann 
768efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
769efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
770efc7688bSMarcel Holtmann 
771efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
772efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
773efc7688bSMarcel Holtmann 
774a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
775a9de9248SMarcel Holtmann 	       hdev->features[0], hdev->features[1],
776a9de9248SMarcel Holtmann 	       hdev->features[2], hdev->features[3],
777a9de9248SMarcel Holtmann 	       hdev->features[4], hdev->features[5],
778a9de9248SMarcel Holtmann 	       hdev->features[6], hdev->features[7]);
7791da177e4SLinus Torvalds }
7801da177e4SLinus Torvalds 
7818f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev)
7828f984dfaSJohan Hedberg {
7838f984dfaSJohan Hedberg 	struct hci_cp_write_le_host_supported cp;
7848f984dfaSJohan Hedberg 
7858f984dfaSJohan Hedberg 	memset(&cp, 0, sizeof(cp));
7868f984dfaSJohan Hedberg 
7879d42820fSMarcel Holtmann 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
7888f984dfaSJohan Hedberg 		cp.le = 1;
789976eb20eSJohan Hedberg 		cp.simul = !!lmp_le_br_capable(hdev);
7908f984dfaSJohan Hedberg 	}
7918f984dfaSJohan Hedberg 
792976eb20eSJohan Hedberg 	if (cp.le != !!lmp_host_le_capable(hdev))
79304124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
79404124681SGustavo F. Padovan 			     &cp);
7958f984dfaSJohan Hedberg }
7968f984dfaSJohan Hedberg 
797971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
798971e3a4bSAndre Guedes 					   struct sk_buff *skb)
799971e3a4bSAndre Guedes {
800971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
801971e3a4bSAndre Guedes 
8029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
803971e3a4bSAndre Guedes 
804971e3a4bSAndre Guedes 	if (rp->status)
8058f984dfaSJohan Hedberg 		goto done;
806971e3a4bSAndre Guedes 
807b5b32b65SAndre Guedes 	switch (rp->page) {
808b5b32b65SAndre Guedes 	case 0:
809b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
810b5b32b65SAndre Guedes 		break;
811b5b32b65SAndre Guedes 	case 1:
81259e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
813b5b32b65SAndre Guedes 		break;
814b5b32b65SAndre Guedes 	}
815971e3a4bSAndre Guedes 
816c383ddc4SAndre Guedes 	if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
8178f984dfaSJohan Hedberg 		hci_set_le_support(hdev);
8188f984dfaSJohan Hedberg 
8198f984dfaSJohan Hedberg done:
820971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
821971e3a4bSAndre Guedes }
822971e3a4bSAndre Guedes 
8231e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
8241e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
8251e89cffbSAndrei Emeltchenko {
8261e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
8271e89cffbSAndrei Emeltchenko 
8289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8291e89cffbSAndrei Emeltchenko 
8301e89cffbSAndrei Emeltchenko 	if (rp->status)
8311e89cffbSAndrei Emeltchenko 		return;
8321e89cffbSAndrei Emeltchenko 
8331e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
8341e89cffbSAndrei Emeltchenko 
8351e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
8361e89cffbSAndrei Emeltchenko }
8371e89cffbSAndrei Emeltchenko 
838a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
839a9de9248SMarcel Holtmann {
840a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
841a9de9248SMarcel Holtmann 
8429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
843a9de9248SMarcel Holtmann 
844a9de9248SMarcel Holtmann 	if (rp->status)
845a9de9248SMarcel Holtmann 		return;
846a9de9248SMarcel Holtmann 
847a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
848a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
849a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
850a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
851da1f5198SMarcel Holtmann 
852da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
853da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
854da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
855da1f5198SMarcel Holtmann 	}
856da1f5198SMarcel Holtmann 
857da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
858da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
8591da177e4SLinus Torvalds 
860807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
861807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
8621da177e4SLinus Torvalds }
8631da177e4SLinus Torvalds 
864a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
865a9de9248SMarcel Holtmann {
866a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
8671da177e4SLinus Torvalds 
8689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
869a9de9248SMarcel Holtmann 
870a9de9248SMarcel Holtmann 	if (!rp->status)
871a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
872a9de9248SMarcel Holtmann 
87323bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
87423bb5763SJohan Hedberg }
87523bb5763SJohan Hedberg 
876350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
877350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
878350ee4cfSAndrei Emeltchenko {
879350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
880350ee4cfSAndrei Emeltchenko 
8819f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
882350ee4cfSAndrei Emeltchenko 
883350ee4cfSAndrei Emeltchenko 	if (rp->status)
884350ee4cfSAndrei Emeltchenko 		return;
885350ee4cfSAndrei Emeltchenko 
886350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
887350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
888350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
889350ee4cfSAndrei Emeltchenko 
890350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
891350ee4cfSAndrei Emeltchenko 
892350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
893350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
894350ee4cfSAndrei Emeltchenko 
895350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
896350ee4cfSAndrei Emeltchenko }
897350ee4cfSAndrei Emeltchenko 
89823bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
89923bb5763SJohan Hedberg {
90023bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
90123bb5763SJohan Hedberg 
9029f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
90323bb5763SJohan Hedberg 
90423bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
9051da177e4SLinus Torvalds }
9061da177e4SLinus Torvalds 
907928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
908928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
909928abaa7SAndrei Emeltchenko {
910928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
911928abaa7SAndrei Emeltchenko 
9129f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
913928abaa7SAndrei Emeltchenko 
914928abaa7SAndrei Emeltchenko 	if (rp->status)
9158e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
916928abaa7SAndrei Emeltchenko 
917928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
918928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
919928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
920928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
921928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
922928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
923928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
924928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
925928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
926928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
927928abaa7SAndrei Emeltchenko 
928928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
9298e2a0d92SAndrei Emeltchenko 
9308e2a0d92SAndrei Emeltchenko a2mp_rsp:
9318e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
932928abaa7SAndrei Emeltchenko }
933928abaa7SAndrei Emeltchenko 
934903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
935903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
936903e4541SAndrei Emeltchenko {
937903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
938903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
939903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
940903e4541SAndrei Emeltchenko 
941903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
942903e4541SAndrei Emeltchenko 
943903e4541SAndrei Emeltchenko 	if (rp->status)
944903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
945903e4541SAndrei Emeltchenko 
946903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
947903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
948903e4541SAndrei Emeltchenko 
949903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
9502e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
951903e4541SAndrei Emeltchenko 
952903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
953903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
954903e4541SAndrei Emeltchenko 
955903e4541SAndrei Emeltchenko 		/* Read other fragments */
956903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
957903e4541SAndrei Emeltchenko 
958903e4541SAndrei Emeltchenko 		return;
959903e4541SAndrei Emeltchenko 	}
960903e4541SAndrei Emeltchenko 
961903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
962903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
963903e4541SAndrei Emeltchenko 	assoc->offset = 0;
964903e4541SAndrei Emeltchenko 
965903e4541SAndrei Emeltchenko a2mp_rsp:
966903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
967903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
9689495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
969903e4541SAndrei Emeltchenko }
970903e4541SAndrei Emeltchenko 
971b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
972b0916ea0SJohan Hedberg 					  struct sk_buff *skb)
973b0916ea0SJohan Hedberg {
974b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
975b0916ea0SJohan Hedberg 
9769f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
977b0916ea0SJohan Hedberg 
978b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
979b0916ea0SJohan Hedberg }
980b0916ea0SJohan Hedberg 
981d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
982d5859e22SJohan Hedberg {
983d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
984d5859e22SJohan Hedberg 
9859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
986d5859e22SJohan Hedberg 
987d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
988d5859e22SJohan Hedberg }
989d5859e22SJohan Hedberg 
990d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
991d5859e22SJohan Hedberg 				      struct sk_buff *skb)
992d5859e22SJohan Hedberg {
993d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
994d5859e22SJohan Hedberg 
9959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
996d5859e22SJohan Hedberg 
997d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
998d5859e22SJohan Hedberg }
999d5859e22SJohan Hedberg 
1000d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
1001d5859e22SJohan Hedberg 					 struct sk_buff *skb)
1002d5859e22SJohan Hedberg {
100391c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
1004d5859e22SJohan Hedberg 
10059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1006d5859e22SJohan Hedberg 
100791c4e9b1SMarcel Holtmann 	if (!rp->status)
100891c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
100991c4e9b1SMarcel Holtmann 
101091c4e9b1SMarcel Holtmann 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
1011d5859e22SJohan Hedberg }
1012d5859e22SJohan Hedberg 
1013d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1014d5859e22SJohan Hedberg {
1015d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
1016d5859e22SJohan Hedberg 
10179f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1018d5859e22SJohan Hedberg 
1019d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1020d5859e22SJohan Hedberg }
1021d5859e22SJohan Hedberg 
1022980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1023980e1a53SJohan Hedberg {
1024980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1025980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
1026980e1a53SJohan Hedberg 	struct hci_conn *conn;
1027980e1a53SJohan Hedberg 
10289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1029980e1a53SJohan Hedberg 
103056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
103156e5cb86SJohan Hedberg 
1032a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1033744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
1034980e1a53SJohan Hedberg 
1035fa1bd918SMikel Astiz 	if (rp->status)
103656e5cb86SJohan Hedberg 		goto unlock;
1037980e1a53SJohan Hedberg 
1038980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1039980e1a53SJohan Hedberg 	if (!cp)
104056e5cb86SJohan Hedberg 		goto unlock;
1041980e1a53SJohan Hedberg 
1042980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1043980e1a53SJohan Hedberg 	if (conn)
1044980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
104556e5cb86SJohan Hedberg 
104656e5cb86SJohan Hedberg unlock:
104756e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1048980e1a53SJohan Hedberg }
1049980e1a53SJohan Hedberg 
1050980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1051980e1a53SJohan Hedberg {
1052980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1053980e1a53SJohan Hedberg 
10549f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1055980e1a53SJohan Hedberg 
105656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
105756e5cb86SJohan Hedberg 
1058a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1059744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
1060980e1a53SJohan Hedberg 						 rp->status);
106156e5cb86SJohan Hedberg 
106256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1063980e1a53SJohan Hedberg }
106456e5cb86SJohan Hedberg 
10656ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
10666ed58ec5SVille Tervo 				       struct sk_buff *skb)
10676ed58ec5SVille Tervo {
10686ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
10696ed58ec5SVille Tervo 
10709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10716ed58ec5SVille Tervo 
10726ed58ec5SVille Tervo 	if (rp->status)
10736ed58ec5SVille Tervo 		return;
10746ed58ec5SVille Tervo 
10756ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
10766ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
10776ed58ec5SVille Tervo 
10786ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
10796ed58ec5SVille Tervo 
10806ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
10816ed58ec5SVille Tervo 
10826ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
10836ed58ec5SVille Tervo }
1084980e1a53SJohan Hedberg 
10858fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
10868fa19098SJohan Hedberg 					struct sk_buff *skb)
10878fa19098SJohan Hedberg {
10888fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
10898fa19098SJohan Hedberg 
10908fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10918fa19098SJohan Hedberg 
10928fa19098SJohan Hedberg 	if (!rp->status)
10938fa19098SJohan Hedberg 		hdev->adv_tx_power = rp->tx_power;
10948fa19098SJohan Hedberg 
10958fa19098SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
10968fa19098SJohan Hedberg }
10978fa19098SJohan Hedberg 
1098e36b04c8SJohan Hedberg static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1099e36b04c8SJohan Hedberg {
1100e36b04c8SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
1101e36b04c8SJohan Hedberg 
1102e36b04c8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1103e36b04c8SJohan Hedberg 
1104e36b04c8SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1105e36b04c8SJohan Hedberg }
1106e36b04c8SJohan Hedberg 
1107a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1108a5c29683SJohan Hedberg {
1109a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1110a5c29683SJohan Hedberg 
11119f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1112a5c29683SJohan Hedberg 
111356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
111456e5cb86SJohan Hedberg 
1115a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
111604124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
111704124681SGustavo F. Padovan 						 rp->status);
111856e5cb86SJohan Hedberg 
111956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1120a5c29683SJohan Hedberg }
1121a5c29683SJohan Hedberg 
1122a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
1123a5c29683SJohan Hedberg 					  struct sk_buff *skb)
1124a5c29683SJohan Hedberg {
1125a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1126a5c29683SJohan Hedberg 
11279f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1128a5c29683SJohan Hedberg 
112956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
113056e5cb86SJohan Hedberg 
1131a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1132744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
113304124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
113456e5cb86SJohan Hedberg 
113556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1136a5c29683SJohan Hedberg }
1137a5c29683SJohan Hedberg 
11381143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
11391143d458SBrian Gix {
11401143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
11411143d458SBrian Gix 
11429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
11431143d458SBrian Gix 
11441143d458SBrian Gix 	hci_dev_lock(hdev);
11451143d458SBrian Gix 
1146a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1147272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1148272d90dfSJohan Hedberg 						 0, rp->status);
11491143d458SBrian Gix 
11501143d458SBrian Gix 	hci_dev_unlock(hdev);
11511143d458SBrian Gix }
11521143d458SBrian Gix 
11531143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
11541143d458SBrian Gix 					  struct sk_buff *skb)
11551143d458SBrian Gix {
11561143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
11571143d458SBrian Gix 
11589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
11591143d458SBrian Gix 
11601143d458SBrian Gix 	hci_dev_lock(hdev);
11611143d458SBrian Gix 
1162a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
11631143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
116404124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
11651143d458SBrian Gix 
11661143d458SBrian Gix 	hci_dev_unlock(hdev);
11671143d458SBrian Gix }
11681143d458SBrian Gix 
1169c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1170c35938b2SSzymon Janc 					     struct sk_buff *skb)
1171c35938b2SSzymon Janc {
1172c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1173c35938b2SSzymon Janc 
11749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1175c35938b2SSzymon Janc 
117656e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1177744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1178c35938b2SSzymon Janc 						rp->randomizer, rp->status);
117956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1180c35938b2SSzymon Janc }
1181c35938b2SSzymon Janc 
118207f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
118307f7fa5dSAndre Guedes {
118407f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
118507f7fa5dSAndre Guedes 
11869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
11877ba8b4beSAndre Guedes 
11887ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
11893fd24153SAndre Guedes 
11903fd24153SAndre Guedes 	if (status) {
11913fd24153SAndre Guedes 		hci_dev_lock(hdev);
11923fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
11933fd24153SAndre Guedes 		hci_dev_unlock(hdev);
11943fd24153SAndre Guedes 		return;
11953fd24153SAndre Guedes 	}
119607f7fa5dSAndre Guedes }
119707f7fa5dSAndre Guedes 
1198eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1199eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1200eb9d91f5SAndre Guedes {
1201eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1202eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1203eb9d91f5SAndre Guedes 
12049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1205eb9d91f5SAndre Guedes 
1206eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1207eb9d91f5SAndre Guedes 	if (!cp)
1208eb9d91f5SAndre Guedes 		return;
1209eb9d91f5SAndre Guedes 
121068a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
121168a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
12127ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
12137ba8b4beSAndre Guedes 
12143fd24153SAndre Guedes 		if (status) {
12153fd24153SAndre Guedes 			hci_dev_lock(hdev);
12163fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
12173fd24153SAndre Guedes 			hci_dev_unlock(hdev);
12187ba8b4beSAndre Guedes 			return;
12193fd24153SAndre Guedes 		}
12207ba8b4beSAndre Guedes 
1221d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1222d23264a8SAndre Guedes 
1223a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1224343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1225a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
122668a8aea4SAndrei Emeltchenko 		break;
122768a8aea4SAndrei Emeltchenko 
122868a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1229c9ecc48eSAndre Guedes 		if (status) {
1230c9ecc48eSAndre Guedes 			hci_dev_lock(hdev);
1231c9ecc48eSAndre Guedes 			mgmt_stop_discovery_failed(hdev, status);
1232c9ecc48eSAndre Guedes 			hci_dev_unlock(hdev);
12337ba8b4beSAndre Guedes 			return;
1234c9ecc48eSAndre Guedes 		}
12357ba8b4beSAndre Guedes 
1236d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1237d23264a8SAndre Guedes 
1238bc3dd33cSAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1239bc3dd33cSAndre Guedes 		    hdev->discovery.state == DISCOVERY_FINDING) {
12405e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
12415e0452c0SAndre Guedes 		} else {
1242c599008fSAndre Guedes 			hci_dev_lock(hdev);
1243c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1244c599008fSAndre Guedes 			hci_dev_unlock(hdev);
12455e0452c0SAndre Guedes 		}
1246c599008fSAndre Guedes 
124768a8aea4SAndrei Emeltchenko 		break;
124868a8aea4SAndrei Emeltchenko 
124968a8aea4SAndrei Emeltchenko 	default:
125068a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
125168a8aea4SAndrei Emeltchenko 		break;
125235815085SAndre Guedes 	}
1253eb9d91f5SAndre Guedes }
1254eb9d91f5SAndre Guedes 
1255a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1256a7a595f6SVinicius Costa Gomes {
1257a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1258a7a595f6SVinicius Costa Gomes 
12599f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1260a7a595f6SVinicius Costa Gomes 
1261a7a595f6SVinicius Costa Gomes 	if (rp->status)
1262a7a595f6SVinicius Costa Gomes 		return;
1263a7a595f6SVinicius Costa Gomes 
1264a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1265a7a595f6SVinicius Costa Gomes }
1266a7a595f6SVinicius Costa Gomes 
1267a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1268a7a595f6SVinicius Costa Gomes {
1269a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1270a7a595f6SVinicius Costa Gomes 
12719f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1272a7a595f6SVinicius Costa Gomes 
1273a7a595f6SVinicius Costa Gomes 	if (rp->status)
1274a7a595f6SVinicius Costa Gomes 		return;
1275a7a595f6SVinicius Costa Gomes 
1276a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1277a7a595f6SVinicius Costa Gomes }
1278a7a595f6SVinicius Costa Gomes 
12796039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1280f9b49306SAndre Guedes 					   struct sk_buff *skb)
1281f9b49306SAndre Guedes {
128206199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1283f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1284f9b49306SAndre Guedes 
12859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1286f9b49306SAndre Guedes 
128706199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
12888f984dfaSJohan Hedberg 	if (!sent)
1289f9b49306SAndre Guedes 		return;
1290f9b49306SAndre Guedes 
12918f984dfaSJohan Hedberg 	if (!status) {
12928f984dfaSJohan Hedberg 		if (sent->le)
12938f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
12948f984dfaSJohan Hedberg 		else
12958f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
129653b2caabSJohan Hedberg 
129753b2caabSJohan Hedberg 		if (sent->simul)
129853b2caabSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE_BREDR;
129953b2caabSJohan Hedberg 		else
130053b2caabSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
13018f984dfaSJohan Hedberg 	}
13028f984dfaSJohan Hedberg 
13038f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
13048f984dfaSJohan Hedberg 	    !test_bit(HCI_INIT, &hdev->flags))
13058f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
13068f984dfaSJohan Hedberg 
13078f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1308f9b49306SAndre Guedes }
1309f9b49306SAndre Guedes 
131093c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
131193c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
131293c284eeSAndrei Emeltchenko {
131393c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
131493c284eeSAndrei Emeltchenko 
131593c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
131693c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
131793c284eeSAndrei Emeltchenko 
131893c284eeSAndrei Emeltchenko 	if (rp->status)
131993c284eeSAndrei Emeltchenko 		return;
132093c284eeSAndrei Emeltchenko 
132193c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
132293c284eeSAndrei Emeltchenko }
132393c284eeSAndrei Emeltchenko 
13246039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1325a9de9248SMarcel Holtmann {
13269f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1327a9de9248SMarcel Holtmann 
1328a9de9248SMarcel Holtmann 	if (status) {
132923bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1330a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
133156e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1332a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
13337a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
133456e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1335314b2381SJohan Hedberg 		return;
1336314b2381SJohan Hedberg 	}
1337314b2381SJohan Hedberg 
133889352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
133989352e7dSAndre Guedes 
134056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1341343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
134256e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1343a9de9248SMarcel Holtmann }
1344a9de9248SMarcel Holtmann 
13456039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
13461da177e4SLinus Torvalds {
1347a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
13481da177e4SLinus Torvalds 	struct hci_conn *conn;
13491da177e4SLinus Torvalds 
13509f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1351a9de9248SMarcel Holtmann 
1352a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
13531da177e4SLinus Torvalds 	if (!cp)
13541da177e4SLinus Torvalds 		return;
13551da177e4SLinus Torvalds 
13561da177e4SLinus Torvalds 	hci_dev_lock(hdev);
13571da177e4SLinus Torvalds 
13581da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
13591da177e4SLinus Torvalds 
13606ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
13611da177e4SLinus Torvalds 
13621da177e4SLinus Torvalds 	if (status) {
13631da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
13644c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
13651da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
13661da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
13671da177e4SLinus Torvalds 				hci_conn_del(conn);
13684c67bc74SMarcel Holtmann 			} else
13694c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
13701da177e4SLinus Torvalds 		}
13711da177e4SLinus Torvalds 	} else {
13721da177e4SLinus Torvalds 		if (!conn) {
13731da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
13741da177e4SLinus Torvalds 			if (conn) {
1375a0c808b3SJohan Hedberg 				conn->out = true;
13761da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
13771da177e4SLinus Torvalds 			} else
1378893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
13791da177e4SLinus Torvalds 		}
13801da177e4SLinus Torvalds 	}
13811da177e4SLinus Torvalds 
13821da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
13831da177e4SLinus Torvalds }
13841da177e4SLinus Torvalds 
1385a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
13861da177e4SLinus Torvalds {
1387a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
13881da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
13891da177e4SLinus Torvalds 	__u16 handle;
13901da177e4SLinus Torvalds 
13919f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1392b6a0dc82SMarcel Holtmann 
1393a9de9248SMarcel Holtmann 	if (!status)
1394a9de9248SMarcel Holtmann 		return;
1395a9de9248SMarcel Holtmann 
1396a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
13971da177e4SLinus Torvalds 	if (!cp)
1398a9de9248SMarcel Holtmann 		return;
13991da177e4SLinus Torvalds 
14001da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
14011da177e4SLinus Torvalds 
14029f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
14031da177e4SLinus Torvalds 
14041da177e4SLinus Torvalds 	hci_dev_lock(hdev);
14051da177e4SLinus Torvalds 
14061da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14075a08ecceSAndrei Emeltchenko 	if (acl) {
14085a08ecceSAndrei Emeltchenko 		sco = acl->link;
14095a08ecceSAndrei Emeltchenko 		if (sco) {
14101da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
14111da177e4SLinus Torvalds 
14121da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
14131da177e4SLinus Torvalds 			hci_conn_del(sco);
14141da177e4SLinus Torvalds 		}
14155a08ecceSAndrei Emeltchenko 	}
14161da177e4SLinus Torvalds 
14171da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14181da177e4SLinus Torvalds }
14191da177e4SLinus Torvalds 
1420f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1421f8558555SMarcel Holtmann {
1422f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1423f8558555SMarcel Holtmann 	struct hci_conn *conn;
1424f8558555SMarcel Holtmann 
14259f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1426f8558555SMarcel Holtmann 
1427f8558555SMarcel Holtmann 	if (!status)
1428f8558555SMarcel Holtmann 		return;
1429f8558555SMarcel Holtmann 
1430f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1431f8558555SMarcel Holtmann 	if (!cp)
1432f8558555SMarcel Holtmann 		return;
1433f8558555SMarcel Holtmann 
1434f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1435f8558555SMarcel Holtmann 
1436f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1437f8558555SMarcel Holtmann 	if (conn) {
1438f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1439f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1440f8558555SMarcel Holtmann 			hci_conn_put(conn);
1441f8558555SMarcel Holtmann 		}
1442f8558555SMarcel Holtmann 	}
1443f8558555SMarcel Holtmann 
1444f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1445f8558555SMarcel Holtmann }
1446f8558555SMarcel Holtmann 
1447f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1448f8558555SMarcel Holtmann {
1449f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1450f8558555SMarcel Holtmann 	struct hci_conn *conn;
1451f8558555SMarcel Holtmann 
14529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1453f8558555SMarcel Holtmann 
1454f8558555SMarcel Holtmann 	if (!status)
1455f8558555SMarcel Holtmann 		return;
1456f8558555SMarcel Holtmann 
1457f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1458f8558555SMarcel Holtmann 	if (!cp)
1459f8558555SMarcel Holtmann 		return;
1460f8558555SMarcel Holtmann 
1461f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1462f8558555SMarcel Holtmann 
1463f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1464f8558555SMarcel Holtmann 	if (conn) {
1465f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1466f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1467f8558555SMarcel Holtmann 			hci_conn_put(conn);
1468f8558555SMarcel Holtmann 		}
1469f8558555SMarcel Holtmann 	}
1470f8558555SMarcel Holtmann 
1471f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1472f8558555SMarcel Holtmann }
1473f8558555SMarcel Holtmann 
1474127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1475392599b9SJohan Hedberg 				    struct hci_conn *conn)
1476392599b9SJohan Hedberg {
1477392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1478392599b9SJohan Hedberg 		return 0;
1479392599b9SJohan Hedberg 
1480765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1481392599b9SJohan Hedberg 		return 0;
1482392599b9SJohan Hedberg 
1483392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1484e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1485807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1486807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1487392599b9SJohan Hedberg 		return 0;
1488392599b9SJohan Hedberg 
1489392599b9SJohan Hedberg 	return 1;
1490392599b9SJohan Hedberg }
1491392599b9SJohan Hedberg 
14926039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
149300abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
149430dc78e1SJohan Hedberg {
149530dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
149630dc78e1SJohan Hedberg 
149730dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
149830dc78e1SJohan Hedberg 
149930dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
150030dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
150130dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
150230dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
150330dc78e1SJohan Hedberg 
150430dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
150530dc78e1SJohan Hedberg }
150630dc78e1SJohan Hedberg 
1507b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
150830dc78e1SJohan Hedberg {
150930dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
151030dc78e1SJohan Hedberg 	struct inquiry_entry *e;
151130dc78e1SJohan Hedberg 
1512b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1513b644ba33SJohan Hedberg 		return false;
1514b644ba33SJohan Hedberg 
1515b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1516c810089cSRam Malovany 	if (!e)
1517c810089cSRam Malovany 		return false;
1518c810089cSRam Malovany 
1519b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1520b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1521b644ba33SJohan Hedberg 		return true;
1522b644ba33SJohan Hedberg 	}
1523b644ba33SJohan Hedberg 
1524b644ba33SJohan Hedberg 	return false;
1525b644ba33SJohan Hedberg }
1526b644ba33SJohan Hedberg 
1527b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1528b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1529b644ba33SJohan Hedberg {
1530b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1531b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1532b644ba33SJohan Hedberg 
1533b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
153404124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
153504124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1536b644ba33SJohan Hedberg 
1537b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1538b644ba33SJohan Hedberg 		return;
1539b644ba33SJohan Hedberg 
154030dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
154130dc78e1SJohan Hedberg 		goto discov_complete;
154230dc78e1SJohan Hedberg 
154330dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
154430dc78e1SJohan Hedberg 		return;
154530dc78e1SJohan Hedberg 
154630dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
15477cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
15487cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
15497cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
15507cc8380eSRam Malovany 	 * Event */
15517cc8380eSRam Malovany 	if (!e)
15527cc8380eSRam Malovany 		return;
15537cc8380eSRam Malovany 
155430dc78e1SJohan Hedberg 	list_del(&e->list);
15557cc8380eSRam Malovany 	if (name) {
15567cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1557b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1558b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1559c3e7c0d9SRam Malovany 	} else {
1560c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
156130dc78e1SJohan Hedberg 	}
156230dc78e1SJohan Hedberg 
1563b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
156430dc78e1SJohan Hedberg 		return;
156530dc78e1SJohan Hedberg 
156630dc78e1SJohan Hedberg discov_complete:
156730dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
156830dc78e1SJohan Hedberg }
156930dc78e1SJohan Hedberg 
1570a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
15711da177e4SLinus Torvalds {
1572127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1573127178d2SJohan Hedberg 	struct hci_conn *conn;
1574127178d2SJohan Hedberg 
15759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1576127178d2SJohan Hedberg 
1577127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1578127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1579127178d2SJohan Hedberg 	if (!status)
1580127178d2SJohan Hedberg 		return;
1581127178d2SJohan Hedberg 
1582127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1583127178d2SJohan Hedberg 	if (!cp)
1584127178d2SJohan Hedberg 		return;
1585127178d2SJohan Hedberg 
1586127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1587127178d2SJohan Hedberg 
1588127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1589b644ba33SJohan Hedberg 
1590b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1591b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1592b644ba33SJohan Hedberg 
159379c6c70cSJohan Hedberg 	if (!conn)
159479c6c70cSJohan Hedberg 		goto unlock;
159579c6c70cSJohan Hedberg 
159679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
159779c6c70cSJohan Hedberg 		goto unlock;
159879c6c70cSJohan Hedberg 
159951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1600127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1601127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1602127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1603127178d2SJohan Hedberg 	}
1604127178d2SJohan Hedberg 
160579c6c70cSJohan Hedberg unlock:
1606127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1607a9de9248SMarcel Holtmann }
16081da177e4SLinus Torvalds 
1609769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1610769be974SMarcel Holtmann {
1611769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1612769be974SMarcel Holtmann 	struct hci_conn *conn;
1613769be974SMarcel Holtmann 
16149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1615769be974SMarcel Holtmann 
1616769be974SMarcel Holtmann 	if (!status)
1617769be974SMarcel Holtmann 		return;
1618769be974SMarcel Holtmann 
1619769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1620769be974SMarcel Holtmann 	if (!cp)
1621769be974SMarcel Holtmann 		return;
1622769be974SMarcel Holtmann 
1623769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1624769be974SMarcel Holtmann 
1625769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1626769be974SMarcel Holtmann 	if (conn) {
1627769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1628769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1629769be974SMarcel Holtmann 			hci_conn_put(conn);
1630769be974SMarcel Holtmann 		}
1631769be974SMarcel Holtmann 	}
1632769be974SMarcel Holtmann 
1633769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1634769be974SMarcel Holtmann }
1635769be974SMarcel Holtmann 
1636769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1637769be974SMarcel Holtmann {
1638769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1639769be974SMarcel Holtmann 	struct hci_conn *conn;
1640769be974SMarcel Holtmann 
16419f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1642769be974SMarcel Holtmann 
1643769be974SMarcel Holtmann 	if (!status)
1644769be974SMarcel Holtmann 		return;
1645769be974SMarcel Holtmann 
1646769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1647769be974SMarcel Holtmann 	if (!cp)
1648769be974SMarcel Holtmann 		return;
1649769be974SMarcel Holtmann 
1650769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1651769be974SMarcel Holtmann 
1652769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1653769be974SMarcel Holtmann 	if (conn) {
1654769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1655769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1656769be974SMarcel Holtmann 			hci_conn_put(conn);
1657769be974SMarcel Holtmann 		}
1658769be974SMarcel Holtmann 	}
1659769be974SMarcel Holtmann 
1660769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1661769be974SMarcel Holtmann }
1662769be974SMarcel Holtmann 
1663a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1664a9de9248SMarcel Holtmann {
1665b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1666b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1667b6a0dc82SMarcel Holtmann 	__u16 handle;
1668b6a0dc82SMarcel Holtmann 
16699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1670b6a0dc82SMarcel Holtmann 
1671b6a0dc82SMarcel Holtmann 	if (!status)
1672b6a0dc82SMarcel Holtmann 		return;
1673b6a0dc82SMarcel Holtmann 
1674b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1675b6a0dc82SMarcel Holtmann 	if (!cp)
1676b6a0dc82SMarcel Holtmann 		return;
1677b6a0dc82SMarcel Holtmann 
1678b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1679b6a0dc82SMarcel Holtmann 
16809f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1681b6a0dc82SMarcel Holtmann 
1682b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1683b6a0dc82SMarcel Holtmann 
1684b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
16855a08ecceSAndrei Emeltchenko 	if (acl) {
16865a08ecceSAndrei Emeltchenko 		sco = acl->link;
16875a08ecceSAndrei Emeltchenko 		if (sco) {
1688b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1689b6a0dc82SMarcel Holtmann 
1690b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1691b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1692b6a0dc82SMarcel Holtmann 		}
16935a08ecceSAndrei Emeltchenko 	}
1694b6a0dc82SMarcel Holtmann 
1695b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1696a9de9248SMarcel Holtmann }
1697a9de9248SMarcel Holtmann 
1698a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1699a9de9248SMarcel Holtmann {
1700a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
170104837f64SMarcel Holtmann 	struct hci_conn *conn;
170204837f64SMarcel Holtmann 
17039f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1704a9de9248SMarcel Holtmann 
1705a9de9248SMarcel Holtmann 	if (!status)
1706a9de9248SMarcel Holtmann 		return;
1707a9de9248SMarcel Holtmann 
1708a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
170904837f64SMarcel Holtmann 	if (!cp)
1710a9de9248SMarcel Holtmann 		return;
171104837f64SMarcel Holtmann 
171204837f64SMarcel Holtmann 	hci_dev_lock(hdev);
171304837f64SMarcel Holtmann 
171404837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1715e73439d8SMarcel Holtmann 	if (conn) {
171651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
171704837f64SMarcel Holtmann 
171851a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1719e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1720e73439d8SMarcel Holtmann 	}
1721e73439d8SMarcel Holtmann 
172204837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
172304837f64SMarcel Holtmann }
172404837f64SMarcel Holtmann 
1725a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1726a9de9248SMarcel Holtmann {
1727a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
172804837f64SMarcel Holtmann 	struct hci_conn *conn;
172904837f64SMarcel Holtmann 
17309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1731a9de9248SMarcel Holtmann 
1732a9de9248SMarcel Holtmann 	if (!status)
1733a9de9248SMarcel Holtmann 		return;
1734a9de9248SMarcel Holtmann 
1735a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
173604837f64SMarcel Holtmann 	if (!cp)
1737a9de9248SMarcel Holtmann 		return;
173804837f64SMarcel Holtmann 
173904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
174004837f64SMarcel Holtmann 
174104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1742e73439d8SMarcel Holtmann 	if (conn) {
174351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
174404837f64SMarcel Holtmann 
174551a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1746e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1747e73439d8SMarcel Holtmann 	}
1748e73439d8SMarcel Holtmann 
174904837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
175004837f64SMarcel Holtmann }
175104837f64SMarcel Holtmann 
175288c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
175388c3df13SJohan Hedberg {
175488c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
175588c3df13SJohan Hedberg 	struct hci_conn *conn;
175688c3df13SJohan Hedberg 
175788c3df13SJohan Hedberg 	if (!status)
175888c3df13SJohan Hedberg 		return;
175988c3df13SJohan Hedberg 
176088c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
176188c3df13SJohan Hedberg 	if (!cp)
176288c3df13SJohan Hedberg 		return;
176388c3df13SJohan Hedberg 
176488c3df13SJohan Hedberg 	hci_dev_lock(hdev);
176588c3df13SJohan Hedberg 
176688c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
176788c3df13SJohan Hedberg 	if (conn)
176888c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
176988c3df13SJohan Hedberg 				       conn->dst_type, status);
177088c3df13SJohan Hedberg 
177188c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
177288c3df13SJohan Hedberg }
177388c3df13SJohan Hedberg 
1774fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1775fcd89c09SVille Tervo {
1776fcd89c09SVille Tervo 	struct hci_conn *conn;
1777fcd89c09SVille Tervo 
17789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1779fcd89c09SVille Tervo 
1780f00a06acSAndre Guedes 	if (status) {
1781fcd89c09SVille Tervo 		hci_dev_lock(hdev);
1782fcd89c09SVille Tervo 
17830c95ab78SAndre Guedes 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
1784f00a06acSAndre Guedes 		if (!conn) {
1785f00a06acSAndre Guedes 			hci_dev_unlock(hdev);
1786f00a06acSAndre Guedes 			return;
1787f00a06acSAndre Guedes 		}
1788fcd89c09SVille Tervo 
17896ed93dc6SAndrei Emeltchenko 		BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
1790fcd89c09SVille Tervo 
1791fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
17920c95ab78SAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
1793328c9248SHemant Gupta 				    conn->dst_type, status);
1794fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, status);
1795fcd89c09SVille Tervo 		hci_conn_del(conn);
1796fcd89c09SVille Tervo 
1797fcd89c09SVille Tervo 		hci_dev_unlock(hdev);
1798fcd89c09SVille Tervo 	}
1799f00a06acSAndre Guedes }
1800fcd89c09SVille Tervo 
1801a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1802a7a595f6SVinicius Costa Gomes {
18039f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1804a7a595f6SVinicius Costa Gomes }
1805a7a595f6SVinicius Costa Gomes 
1806a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1807a02226d6SAndrei Emeltchenko {
180893c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
180993c284eeSAndrei Emeltchenko 
1810a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
181193c284eeSAndrei Emeltchenko 
181293c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
181393c284eeSAndrei Emeltchenko 	if (!cp)
181493c284eeSAndrei Emeltchenko 		return;
181593c284eeSAndrei Emeltchenko 
1816e58917b9SAndrei Emeltchenko 	hci_dev_lock(hdev);
1817e58917b9SAndrei Emeltchenko 
1818e58917b9SAndrei Emeltchenko 	if (status) {
1819e58917b9SAndrei Emeltchenko 		struct hci_conn *hcon;
1820e58917b9SAndrei Emeltchenko 
1821e58917b9SAndrei Emeltchenko 		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
1822e58917b9SAndrei Emeltchenko 		if (hcon)
1823e58917b9SAndrei Emeltchenko 			hci_conn_del(hcon);
1824e58917b9SAndrei Emeltchenko 	} else {
182593c284eeSAndrei Emeltchenko 		amp_write_remote_assoc(hdev, cp->phy_handle);
1826a02226d6SAndrei Emeltchenko 	}
1827a02226d6SAndrei Emeltchenko 
1828e58917b9SAndrei Emeltchenko 	hci_dev_unlock(hdev);
1829e58917b9SAndrei Emeltchenko }
1830e58917b9SAndrei Emeltchenko 
18310b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
18320b26ab9dSAndrei Emeltchenko {
18330b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
18340b26ab9dSAndrei Emeltchenko 
18350b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18360b26ab9dSAndrei Emeltchenko 
18370b26ab9dSAndrei Emeltchenko 	if (status)
18380b26ab9dSAndrei Emeltchenko 		return;
18390b26ab9dSAndrei Emeltchenko 
18400b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
18410b26ab9dSAndrei Emeltchenko 	if (!cp)
18420b26ab9dSAndrei Emeltchenko 		return;
18430b26ab9dSAndrei Emeltchenko 
18440b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
18450b26ab9dSAndrei Emeltchenko }
18460b26ab9dSAndrei Emeltchenko 
18475ce66b59SAndrei Emeltchenko static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
18485ce66b59SAndrei Emeltchenko {
18495ce66b59SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18505ce66b59SAndrei Emeltchenko }
18515ce66b59SAndrei Emeltchenko 
18526039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18531da177e4SLinus Torvalds {
18541da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
185530dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
185630dc78e1SJohan Hedberg 	struct inquiry_entry *e;
18571da177e4SLinus Torvalds 
18589f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18591da177e4SLinus Torvalds 
186023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
18616bd57416SMarcel Holtmann 
1862a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
186389352e7dSAndre Guedes 
186489352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
186589352e7dSAndre Guedes 		return;
186689352e7dSAndre Guedes 
1867a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
186830dc78e1SJohan Hedberg 		return;
186930dc78e1SJohan Hedberg 
187056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
187130dc78e1SJohan Hedberg 
1872343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
187330dc78e1SJohan Hedberg 		goto unlock;
187430dc78e1SJohan Hedberg 
187530dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1876ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
187730dc78e1SJohan Hedberg 		goto unlock;
187830dc78e1SJohan Hedberg 	}
187930dc78e1SJohan Hedberg 
188030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
188130dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
188230dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
188330dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
188430dc78e1SJohan Hedberg 	} else {
188530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
188630dc78e1SJohan Hedberg 	}
188730dc78e1SJohan Hedberg 
188830dc78e1SJohan Hedberg unlock:
188956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
18901da177e4SLinus Torvalds }
18911da177e4SLinus Torvalds 
18926039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
18931da177e4SLinus Torvalds {
189445bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1895a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
18961da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
18971da177e4SLinus Torvalds 
18981da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
18991da177e4SLinus Torvalds 
190045bb4bf0SMarcel Holtmann 	if (!num_rsp)
190145bb4bf0SMarcel Holtmann 		return;
190245bb4bf0SMarcel Holtmann 
19031519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
19041519cc17SAndre Guedes 		return;
19051519cc17SAndre Guedes 
19061da177e4SLinus Torvalds 	hci_dev_lock(hdev);
190745bb4bf0SMarcel Holtmann 
1908e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1909388fc8faSJohan Hedberg 		bool name_known, ssp;
19103175405bSJohan Hedberg 
19111da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
19121da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
19131da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
19141da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
19151da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
19161da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
19171da177e4SLinus Torvalds 		data.rssi		= 0x00;
191841a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
19193175405bSJohan Hedberg 
1920388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
192148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
192204124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
192304124681SGustavo F. Padovan 				  0);
19241da177e4SLinus Torvalds 	}
192545bb4bf0SMarcel Holtmann 
19261da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19271da177e4SLinus Torvalds }
19281da177e4SLinus Torvalds 
19296039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19301da177e4SLinus Torvalds {
1931a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1932a9de9248SMarcel Holtmann 	struct hci_conn *conn;
19331da177e4SLinus Torvalds 
1934a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
193545bb4bf0SMarcel Holtmann 
19361da177e4SLinus Torvalds 	hci_dev_lock(hdev);
193745bb4bf0SMarcel Holtmann 
1938a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
19399499237aSMarcel Holtmann 	if (!conn) {
19409499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
19419499237aSMarcel Holtmann 			goto unlock;
19429499237aSMarcel Holtmann 
19439499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1944a9de9248SMarcel Holtmann 		if (!conn)
1945a9de9248SMarcel Holtmann 			goto unlock;
194645bb4bf0SMarcel Holtmann 
19479499237aSMarcel Holtmann 		conn->type = SCO_LINK;
19489499237aSMarcel Holtmann 	}
19499499237aSMarcel Holtmann 
1950a9de9248SMarcel Holtmann 	if (!ev->status) {
1951a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1952769be974SMarcel Holtmann 
1953769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1954769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1955769be974SMarcel Holtmann 			hci_conn_hold(conn);
1956a9ea3ed9SSzymon Janc 
1957a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1958a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1959a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1960a9ea3ed9SSzymon Janc 			else
1961052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1962769be974SMarcel Holtmann 		} else
1963a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1964a9de9248SMarcel Holtmann 
19659eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
19667d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
19677d0db0a3SMarcel Holtmann 
1968a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1969a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1970a9de9248SMarcel Holtmann 
1971a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1972a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1973a9de9248SMarcel Holtmann 
1974a9de9248SMarcel Holtmann 		/* Get remote features */
1975a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1976a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1977a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1978769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1979769be974SMarcel Holtmann 				     sizeof(cp), &cp);
198045bb4bf0SMarcel Holtmann 		}
1981a9de9248SMarcel Holtmann 
1982a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1983d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1984a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1985a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1986a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
198704124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
198804124681SGustavo F. Padovan 				     &cp);
1989a9de9248SMarcel Holtmann 		}
199017d5c04cSJohan Hedberg 	} else {
1991a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
199217d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1993744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
199448264f06SJohan Hedberg 					    conn->dst_type, ev->status);
199517d5c04cSJohan Hedberg 	}
199645bb4bf0SMarcel Holtmann 
1997e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1998e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
199945bb4bf0SMarcel Holtmann 
2000769be974SMarcel Holtmann 	if (ev->status) {
2001a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2002a9de9248SMarcel Holtmann 		hci_conn_del(conn);
2003c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
2004c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2005a9de9248SMarcel Holtmann 
2006a9de9248SMarcel Holtmann unlock:
20071da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
2008a9de9248SMarcel Holtmann 
2009a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
20101da177e4SLinus Torvalds }
20111da177e4SLinus Torvalds 
20126039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
20131da177e4SLinus Torvalds {
2014a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
20151da177e4SLinus Torvalds 	int mask = hdev->link_mode;
20161da177e4SLinus Torvalds 
20176ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
2018807deac2SGustavo Padovan 	       ev->link_type);
20191da177e4SLinus Torvalds 
20201da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
20211da177e4SLinus Torvalds 
2022138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
2023138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
20241da177e4SLinus Torvalds 		/* Connection accepted */
2025c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
20261da177e4SLinus Torvalds 		struct hci_conn *conn;
20271da177e4SLinus Torvalds 
20281da177e4SLinus Torvalds 		hci_dev_lock(hdev);
2029b6a0dc82SMarcel Holtmann 
2030cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2031cc11b9c1SAndrei Emeltchenko 		if (ie)
2032c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
2033c7bdd502SMarcel Holtmann 
20348fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
20358fc9ced3SGustavo Padovan 					       &ev->bdaddr);
20361da177e4SLinus Torvalds 		if (!conn) {
2037cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2038cc11b9c1SAndrei Emeltchenko 			if (!conn) {
2039893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
20401da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
20411da177e4SLinus Torvalds 				return;
20421da177e4SLinus Torvalds 			}
20431da177e4SLinus Torvalds 		}
2044b6a0dc82SMarcel Holtmann 
20451da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
20461da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
2047b6a0dc82SMarcel Holtmann 
20481da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
20491da177e4SLinus Torvalds 
2050b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
2051b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
2052b6a0dc82SMarcel Holtmann 
20531da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
20541da177e4SLinus Torvalds 
20551da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
20561da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
20571da177e4SLinus Torvalds 			else
20581da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
20591da177e4SLinus Torvalds 
206004124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
206104124681SGustavo F. Padovan 				     &cp);
2062b6a0dc82SMarcel Holtmann 		} else {
2063b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
2064b6a0dc82SMarcel Holtmann 
2065b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
2066a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
2067b6a0dc82SMarcel Holtmann 
206882781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
206982781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
207082781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
2071b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
2072b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
2073b6a0dc82SMarcel Holtmann 
2074b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2075b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
2076b6a0dc82SMarcel Holtmann 		}
20771da177e4SLinus Torvalds 	} else {
20781da177e4SLinus Torvalds 		/* Connection rejected */
20791da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
20801da177e4SLinus Torvalds 
20811da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
20829f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
2083a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
20841da177e4SLinus Torvalds 	}
20851da177e4SLinus Torvalds }
20861da177e4SLinus Torvalds 
2087f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2088f0d6a0eaSMikel Astiz {
2089f0d6a0eaSMikel Astiz 	switch (err) {
2090f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2091f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2092f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2093f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2094f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2095f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2096f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2097f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2098f0d6a0eaSMikel Astiz 	default:
2099f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2100f0d6a0eaSMikel Astiz 	}
2101f0d6a0eaSMikel Astiz }
2102f0d6a0eaSMikel Astiz 
21036039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
21041da177e4SLinus Torvalds {
2105a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
210604837f64SMarcel Holtmann 	struct hci_conn *conn;
21071da177e4SLinus Torvalds 
21089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
21091da177e4SLinus Torvalds 
21101da177e4SLinus Torvalds 	hci_dev_lock(hdev);
21111da177e4SLinus Torvalds 
211204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2113f7520543SJohan Hedberg 	if (!conn)
2114f7520543SJohan Hedberg 		goto unlock;
2115f7520543SJohan Hedberg 
211637d9ef76SJohan Hedberg 	if (ev->status == 0)
21171da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
21187d0db0a3SMarcel Holtmann 
2119b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
2120b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
2121f0d6a0eaSMikel Astiz 		if (ev->status) {
212288c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
212388c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
2124f0d6a0eaSMikel Astiz 		} else {
2125f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
2126f0d6a0eaSMikel Astiz 
2127afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
2128f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
2129f0d6a0eaSMikel Astiz 		}
213037d9ef76SJohan Hedberg 	}
2131f7520543SJohan Hedberg 
213237d9ef76SJohan Hedberg 	if (ev->status == 0) {
21336ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
21346ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
21352950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
21361da177e4SLinus Torvalds 		hci_conn_del(conn);
213737d9ef76SJohan Hedberg 	}
21381da177e4SLinus Torvalds 
2139f7520543SJohan Hedberg unlock:
21401da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
21411da177e4SLinus Torvalds }
21421da177e4SLinus Torvalds 
21436039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2144a9de9248SMarcel Holtmann {
2145a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2146a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2147a9de9248SMarcel Holtmann 
21489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2149a9de9248SMarcel Holtmann 
2150a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2151a9de9248SMarcel Holtmann 
2152a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2153d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2154d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2155d7556e20SWaldemar Rymarkiewicz 
2156765c2a96SJohan Hedberg 	if (!ev->status) {
2157aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
215851a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2159d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
216019f8def0SWaldemar Rymarkiewicz 		} else {
2161a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2162765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
216319f8def0SWaldemar Rymarkiewicz 		}
21642a611692SJohan Hedberg 	} else {
2165bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
2166bab73cb6SJohan Hedberg 				 ev->status);
21672a611692SJohan Hedberg 	}
2168a9de9248SMarcel Holtmann 
216951a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
217051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2171a9de9248SMarcel Holtmann 
2172f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2173aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2174f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2175f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2176f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2177d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2178d7556e20SWaldemar Rymarkiewicz 				     &cp);
2179f8558555SMarcel Holtmann 		} else {
2180f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2181f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2182f8558555SMarcel Holtmann 			hci_conn_put(conn);
2183f8558555SMarcel Holtmann 		}
2184052b30b0SMarcel Holtmann 	} else {
2185a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2186a9de9248SMarcel Holtmann 
2187052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2188052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2189052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2190052b30b0SMarcel Holtmann 	}
2191052b30b0SMarcel Holtmann 
219251a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2193a9de9248SMarcel Holtmann 		if (!ev->status) {
2194a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2195f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2196f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2197d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2198d7556e20SWaldemar Rymarkiewicz 				     &cp);
2199a9de9248SMarcel Holtmann 		} else {
220051a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2201a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2202a9de9248SMarcel Holtmann 		}
2203a9de9248SMarcel Holtmann 	}
2204a9de9248SMarcel Holtmann 
2205d7556e20SWaldemar Rymarkiewicz unlock:
2206a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2207a9de9248SMarcel Holtmann }
2208a9de9248SMarcel Holtmann 
22096039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2210a9de9248SMarcel Holtmann {
2211127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2212127178d2SJohan Hedberg 	struct hci_conn *conn;
2213127178d2SJohan Hedberg 
2214a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2215a9de9248SMarcel Holtmann 
2216a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2217127178d2SJohan Hedberg 
2218127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2219127178d2SJohan Hedberg 
2220127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2221b644ba33SJohan Hedberg 
2222b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2223b644ba33SJohan Hedberg 		goto check_auth;
2224b644ba33SJohan Hedberg 
2225b644ba33SJohan Hedberg 	if (ev->status == 0)
2226b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2227b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2228b644ba33SJohan Hedberg 	else
2229b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2230b644ba33SJohan Hedberg 
2231b644ba33SJohan Hedberg check_auth:
223279c6c70cSJohan Hedberg 	if (!conn)
223379c6c70cSJohan Hedberg 		goto unlock;
223479c6c70cSJohan Hedberg 
223579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
223679c6c70cSJohan Hedberg 		goto unlock;
223779c6c70cSJohan Hedberg 
223851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2239127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2240127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2241127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2242127178d2SJohan Hedberg 	}
2243127178d2SJohan Hedberg 
224479c6c70cSJohan Hedberg unlock:
2245127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2246a9de9248SMarcel Holtmann }
2247a9de9248SMarcel Holtmann 
22486039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2249a9de9248SMarcel Holtmann {
2250a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2251a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2252a9de9248SMarcel Holtmann 
22539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2254a9de9248SMarcel Holtmann 
2255a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2256a9de9248SMarcel Holtmann 
2257a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2258a9de9248SMarcel Holtmann 	if (conn) {
2259a9de9248SMarcel Holtmann 		if (!ev->status) {
2260ae293196SMarcel Holtmann 			if (ev->encrypt) {
2261ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2262ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2263a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2264da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2265ae293196SMarcel Holtmann 			} else
2266a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2267a9de9248SMarcel Holtmann 		}
2268a9de9248SMarcel Holtmann 
226951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2270a9de9248SMarcel Holtmann 
2271a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2272d839c813SGustavo Padovan 			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
2273a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2274a7d7723aSGustavo Padovan 			goto unlock;
2275a7d7723aSGustavo Padovan 		}
2276a7d7723aSGustavo Padovan 
2277f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2278f8558555SMarcel Holtmann 			if (!ev->status)
2279f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2280f8558555SMarcel Holtmann 
2281f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2282f8558555SMarcel Holtmann 			hci_conn_put(conn);
2283f8558555SMarcel Holtmann 		} else
2284a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2285a9de9248SMarcel Holtmann 	}
2286a9de9248SMarcel Holtmann 
2287a7d7723aSGustavo Padovan unlock:
2288a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2289a9de9248SMarcel Holtmann }
2290a9de9248SMarcel Holtmann 
22916039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2292807deac2SGustavo Padovan 					     struct sk_buff *skb)
2293a9de9248SMarcel Holtmann {
2294a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2295a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2296a9de9248SMarcel Holtmann 
22979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2298a9de9248SMarcel Holtmann 
2299a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2300a9de9248SMarcel Holtmann 
2301a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2302a9de9248SMarcel Holtmann 	if (conn) {
2303a9de9248SMarcel Holtmann 		if (!ev->status)
2304a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2305a9de9248SMarcel Holtmann 
230651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2307a9de9248SMarcel Holtmann 
2308a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2309a9de9248SMarcel Holtmann 	}
2310a9de9248SMarcel Holtmann 
2311a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2312a9de9248SMarcel Holtmann }
2313a9de9248SMarcel Holtmann 
23146039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2315807deac2SGustavo Padovan 				    struct sk_buff *skb)
2316a9de9248SMarcel Holtmann {
2317a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2318a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2319a9de9248SMarcel Holtmann 
23209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2321a9de9248SMarcel Holtmann 
2322a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2323a9de9248SMarcel Holtmann 
2324a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2325ccd556feSJohan Hedberg 	if (!conn)
2326ccd556feSJohan Hedberg 		goto unlock;
2327ccd556feSJohan Hedberg 
2328769be974SMarcel Holtmann 	if (!ev->status)
2329a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2330a9de9248SMarcel Holtmann 
2331ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2332ccd556feSJohan Hedberg 		goto unlock;
2333ccd556feSJohan Hedberg 
2334ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2335769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2336769be974SMarcel Holtmann 		cp.handle = ev->handle;
2337769be974SMarcel Holtmann 		cp.page = 0x01;
2338ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2339769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2340392599b9SJohan Hedberg 		goto unlock;
2341392599b9SJohan Hedberg 	}
2342392599b9SJohan Hedberg 
2343671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2344127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2345127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2346127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2347127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2348127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2349b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2350b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
235108c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2352b644ba33SJohan Hedberg 				      conn->dev_class);
2353392599b9SJohan Hedberg 
2354127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2355769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2356769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2357769be974SMarcel Holtmann 		hci_conn_put(conn);
2358769be974SMarcel Holtmann 	}
2359769be974SMarcel Holtmann 
2360ccd556feSJohan Hedberg unlock:
2361a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2362a9de9248SMarcel Holtmann }
2363a9de9248SMarcel Holtmann 
23646039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
23656039aa73SGustavo Padovan {
23666039aa73SGustavo Padovan 	BT_DBG("%s", hdev->name);
23676039aa73SGustavo Padovan }
23686039aa73SGustavo Padovan 
23696039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2370807deac2SGustavo Padovan 				       struct sk_buff *skb)
2371a9de9248SMarcel Holtmann {
2372a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2373a9de9248SMarcel Holtmann }
2374a9de9248SMarcel Holtmann 
23756039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2376a9de9248SMarcel Holtmann {
2377a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2378a9de9248SMarcel Holtmann 	__u16 opcode;
2379a9de9248SMarcel Holtmann 
2380a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2381a9de9248SMarcel Holtmann 
2382a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2383a9de9248SMarcel Holtmann 
2384a9de9248SMarcel Holtmann 	switch (opcode) {
2385a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2386a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2387a9de9248SMarcel Holtmann 		break;
2388a9de9248SMarcel Holtmann 
23894d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
23904d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
23914d93483bSAndre Guedes 		break;
23924d93483bSAndre Guedes 
2393a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2394a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2395a9de9248SMarcel Holtmann 		break;
2396a9de9248SMarcel Holtmann 
2397a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2398a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2399a9de9248SMarcel Holtmann 		break;
2400a9de9248SMarcel Holtmann 
2401a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2402a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2403a9de9248SMarcel Holtmann 		break;
2404a9de9248SMarcel Holtmann 
2405e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2406e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2407e4e8e37cSMarcel Holtmann 		break;
2408e4e8e37cSMarcel Holtmann 
2409a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2410a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2411a9de9248SMarcel Holtmann 		break;
2412a9de9248SMarcel Holtmann 
2413e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2414e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2415e4e8e37cSMarcel Holtmann 		break;
2416e4e8e37cSMarcel Holtmann 
2417e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2418e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2419e4e8e37cSMarcel Holtmann 		break;
2420e4e8e37cSMarcel Holtmann 
2421a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2422a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2423a9de9248SMarcel Holtmann 		break;
2424a9de9248SMarcel Holtmann 
2425a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2426a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2427a9de9248SMarcel Holtmann 		break;
2428a9de9248SMarcel Holtmann 
2429a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2430a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2431a9de9248SMarcel Holtmann 		break;
2432a9de9248SMarcel Holtmann 
2433a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2434a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2435a9de9248SMarcel Holtmann 		break;
2436a9de9248SMarcel Holtmann 
2437a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2438a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2439a9de9248SMarcel Holtmann 		break;
2440a9de9248SMarcel Holtmann 
2441a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2442a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2443a9de9248SMarcel Holtmann 		break;
2444a9de9248SMarcel Holtmann 
2445a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2446a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2447a9de9248SMarcel Holtmann 		break;
2448a9de9248SMarcel Holtmann 
2449a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2450a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2451a9de9248SMarcel Holtmann 		break;
2452a9de9248SMarcel Holtmann 
2453a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2454a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2455a9de9248SMarcel Holtmann 		break;
2456a9de9248SMarcel Holtmann 
2457a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2458a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2459a9de9248SMarcel Holtmann 		break;
2460a9de9248SMarcel Holtmann 
2461a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2462a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2463a9de9248SMarcel Holtmann 		break;
2464a9de9248SMarcel Holtmann 
2465333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2466333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2467333140b5SMarcel Holtmann 		break;
2468333140b5SMarcel Holtmann 
2469a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2470a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2471a9de9248SMarcel Holtmann 		break;
2472a9de9248SMarcel Holtmann 
2473a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2474a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2475a9de9248SMarcel Holtmann 		break;
2476a9de9248SMarcel Holtmann 
2477a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2478a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2479a9de9248SMarcel Holtmann 		break;
2480a9de9248SMarcel Holtmann 
2481971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2482971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2483971e3a4bSAndre Guedes 		break;
2484971e3a4bSAndre Guedes 
2485a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2486a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2487a9de9248SMarcel Holtmann 		break;
2488a9de9248SMarcel Holtmann 
2489a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2490a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2491a9de9248SMarcel Holtmann 		break;
2492a9de9248SMarcel Holtmann 
2493350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2494350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2495350ee4cfSAndrei Emeltchenko 		break;
2496350ee4cfSAndrei Emeltchenko 
249723bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
249823bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
249923bb5763SJohan Hedberg 		break;
250023bb5763SJohan Hedberg 
25011e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
25021e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
25031e89cffbSAndrei Emeltchenko 		break;
25041e89cffbSAndrei Emeltchenko 
2505928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2506928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2507928abaa7SAndrei Emeltchenko 		break;
2508928abaa7SAndrei Emeltchenko 
2509903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2510903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2511903e4541SAndrei Emeltchenko 		break;
2512903e4541SAndrei Emeltchenko 
2513b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2514b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2515b0916ea0SJohan Hedberg 		break;
2516b0916ea0SJohan Hedberg 
2517d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2518d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2519d5859e22SJohan Hedberg 		break;
2520d5859e22SJohan Hedberg 
2521d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2522d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2523d5859e22SJohan Hedberg 		break;
2524d5859e22SJohan Hedberg 
2525d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2526d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2527d5859e22SJohan Hedberg 		break;
2528d5859e22SJohan Hedberg 
2529d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2530d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2531d5859e22SJohan Hedberg 		break;
2532d5859e22SJohan Hedberg 
2533980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2534980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2535980e1a53SJohan Hedberg 		break;
2536980e1a53SJohan Hedberg 
2537980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2538980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2539980e1a53SJohan Hedberg 		break;
2540980e1a53SJohan Hedberg 
2541c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2542c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2543c35938b2SSzymon Janc 		break;
2544c35938b2SSzymon Janc 
25456ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
25466ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
25476ed58ec5SVille Tervo 		break;
25486ed58ec5SVille Tervo 
25498fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
25508fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
25518fa19098SJohan Hedberg 		break;
25528fa19098SJohan Hedberg 
2553e36b04c8SJohan Hedberg 	case HCI_OP_LE_SET_EVENT_MASK:
2554e36b04c8SJohan Hedberg 		hci_cc_le_set_event_mask(hdev, skb);
2555e36b04c8SJohan Hedberg 		break;
2556e36b04c8SJohan Hedberg 
2557a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2558a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2559a5c29683SJohan Hedberg 		break;
2560a5c29683SJohan Hedberg 
2561a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2562a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2563a5c29683SJohan Hedberg 		break;
2564a5c29683SJohan Hedberg 
25651143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
25661143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
25671143d458SBrian Gix 		break;
25681143d458SBrian Gix 
25691143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
25701143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
257116cde993SSzymon Janc 		break;
257207f7fa5dSAndre Guedes 
257307f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
257407f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
25751143d458SBrian Gix 		break;
25761143d458SBrian Gix 
2577eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2578eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2579eb9d91f5SAndre Guedes 		break;
2580eb9d91f5SAndre Guedes 
2581a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2582a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2583a7a595f6SVinicius Costa Gomes 		break;
2584a7a595f6SVinicius Costa Gomes 
2585a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2586a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2587a7a595f6SVinicius Costa Gomes 		break;
2588a7a595f6SVinicius Costa Gomes 
2589f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2590f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2591f9b49306SAndre Guedes 		break;
2592f9b49306SAndre Guedes 
259393c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
259493c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
259593c284eeSAndrei Emeltchenko 		break;
259693c284eeSAndrei Emeltchenko 
2597a9de9248SMarcel Holtmann 	default:
25989f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2599a9de9248SMarcel Holtmann 		break;
2600a9de9248SMarcel Holtmann 	}
2601a9de9248SMarcel Holtmann 
26026bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
26036bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
26046bd32326SVille Tervo 
2605a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2606a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2607a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2608c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2609a9de9248SMarcel Holtmann 	}
2610a9de9248SMarcel Holtmann }
2611a9de9248SMarcel Holtmann 
26126039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2613a9de9248SMarcel Holtmann {
2614a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2615a9de9248SMarcel Holtmann 	__u16 opcode;
2616a9de9248SMarcel Holtmann 
2617a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2618a9de9248SMarcel Holtmann 
2619a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2620a9de9248SMarcel Holtmann 
2621a9de9248SMarcel Holtmann 	switch (opcode) {
2622a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2623a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2624a9de9248SMarcel Holtmann 		break;
2625a9de9248SMarcel Holtmann 
2626a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2627a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2628a9de9248SMarcel Holtmann 		break;
2629a9de9248SMarcel Holtmann 
2630a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2631a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2632a9de9248SMarcel Holtmann 		break;
2633a9de9248SMarcel Holtmann 
2634f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2635f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2636f8558555SMarcel Holtmann 		break;
2637f8558555SMarcel Holtmann 
2638f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2639f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2640f8558555SMarcel Holtmann 		break;
2641f8558555SMarcel Holtmann 
2642a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2643a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2644a9de9248SMarcel Holtmann 		break;
2645a9de9248SMarcel Holtmann 
2646769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2647769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2648769be974SMarcel Holtmann 		break;
2649769be974SMarcel Holtmann 
2650769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2651769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2652769be974SMarcel Holtmann 		break;
2653769be974SMarcel Holtmann 
2654a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2655a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2656a9de9248SMarcel Holtmann 		break;
2657a9de9248SMarcel Holtmann 
2658a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2659a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2660a9de9248SMarcel Holtmann 		break;
2661a9de9248SMarcel Holtmann 
2662a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2663a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2664a9de9248SMarcel Holtmann 		break;
2665a9de9248SMarcel Holtmann 
26668962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
266788c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
26688962ee74SJohan Hedberg 		break;
26698962ee74SJohan Hedberg 
2670fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2671fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2672fcd89c09SVille Tervo 		break;
2673fcd89c09SVille Tervo 
2674a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2675a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2676a7a595f6SVinicius Costa Gomes 		break;
2677a7a595f6SVinicius Costa Gomes 
2678a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2679a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2680a02226d6SAndrei Emeltchenko 		break;
2681a02226d6SAndrei Emeltchenko 
26820b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
26830b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
26840b26ab9dSAndrei Emeltchenko 		break;
26850b26ab9dSAndrei Emeltchenko 
26865ce66b59SAndrei Emeltchenko 	case HCI_OP_CREATE_LOGICAL_LINK:
26875ce66b59SAndrei Emeltchenko 		hci_cs_create_logical_link(hdev, ev->status);
26885ce66b59SAndrei Emeltchenko 		break;
26895ce66b59SAndrei Emeltchenko 
2690a9de9248SMarcel Holtmann 	default:
26919f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2692a9de9248SMarcel Holtmann 		break;
2693a9de9248SMarcel Holtmann 	}
2694a9de9248SMarcel Holtmann 
26956bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
26966bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
26976bd32326SVille Tervo 
269810572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2699a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2700a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2701c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2702a9de9248SMarcel Holtmann 	}
2703a9de9248SMarcel Holtmann }
2704a9de9248SMarcel Holtmann 
27056039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2706a9de9248SMarcel Holtmann {
2707a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2708a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2709a9de9248SMarcel Holtmann 
27109f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2711a9de9248SMarcel Holtmann 
2712a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2713a9de9248SMarcel Holtmann 
2714a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2715a9de9248SMarcel Holtmann 	if (conn) {
2716a9de9248SMarcel Holtmann 		if (!ev->status) {
2717a9de9248SMarcel Holtmann 			if (ev->role)
2718a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2719a9de9248SMarcel Holtmann 			else
2720a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2721a9de9248SMarcel Holtmann 		}
2722a9de9248SMarcel Holtmann 
272351a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2724a9de9248SMarcel Holtmann 
2725a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2726a9de9248SMarcel Holtmann 	}
2727a9de9248SMarcel Holtmann 
2728a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2729a9de9248SMarcel Holtmann }
2730a9de9248SMarcel Holtmann 
27316039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
27321da177e4SLinus Torvalds {
2733a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
27341da177e4SLinus Torvalds 	int i;
27351da177e4SLinus Torvalds 
273632ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
273732ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
273832ac5b9bSAndrei Emeltchenko 		return;
273932ac5b9bSAndrei Emeltchenko 	}
274032ac5b9bSAndrei Emeltchenko 
2741c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2742c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
27431da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
27441da177e4SLinus Torvalds 		return;
27451da177e4SLinus Torvalds 	}
27461da177e4SLinus Torvalds 
2747c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2748c5993de8SAndrei Emeltchenko 
2749613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2750613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
27511da177e4SLinus Torvalds 		struct hci_conn *conn;
27521da177e4SLinus Torvalds 		__u16  handle, count;
27531da177e4SLinus Torvalds 
2754613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2755613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
27561da177e4SLinus Torvalds 
27571da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2758f4280918SAndrei Emeltchenko 		if (!conn)
2759f4280918SAndrei Emeltchenko 			continue;
2760f4280918SAndrei Emeltchenko 
27611da177e4SLinus Torvalds 		conn->sent -= count;
27621da177e4SLinus Torvalds 
2763f4280918SAndrei Emeltchenko 		switch (conn->type) {
2764f4280918SAndrei Emeltchenko 		case ACL_LINK:
276570f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
276670f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
27671da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2768f4280918SAndrei Emeltchenko 			break;
2769f4280918SAndrei Emeltchenko 
2770f4280918SAndrei Emeltchenko 		case LE_LINK:
27716ed58ec5SVille Tervo 			if (hdev->le_pkts) {
27726ed58ec5SVille Tervo 				hdev->le_cnt += count;
27736ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
27746ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
27756ed58ec5SVille Tervo 			} else {
27766ed58ec5SVille Tervo 				hdev->acl_cnt += count;
27776ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
27786ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
27796ed58ec5SVille Tervo 			}
2780f4280918SAndrei Emeltchenko 			break;
2781f4280918SAndrei Emeltchenko 
2782f4280918SAndrei Emeltchenko 		case SCO_LINK:
278370f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
278470f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
27855b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2786f4280918SAndrei Emeltchenko 			break;
2787f4280918SAndrei Emeltchenko 
2788f4280918SAndrei Emeltchenko 		default:
2789f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2790f4280918SAndrei Emeltchenko 			break;
27911da177e4SLinus Torvalds 		}
27921da177e4SLinus Torvalds 	}
2793a9de9248SMarcel Holtmann 
27943eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
27951da177e4SLinus Torvalds }
27961da177e4SLinus Torvalds 
279776ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
279876ef7cf7SAndrei Emeltchenko 						 __u16 handle)
279976ef7cf7SAndrei Emeltchenko {
280076ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
280176ef7cf7SAndrei Emeltchenko 
280276ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
280376ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
280476ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
280576ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
280676ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
280776ef7cf7SAndrei Emeltchenko 		if (chan)
280876ef7cf7SAndrei Emeltchenko 			return chan->conn;
280976ef7cf7SAndrei Emeltchenko 		break;
281076ef7cf7SAndrei Emeltchenko 	default:
281176ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
281276ef7cf7SAndrei Emeltchenko 		break;
281376ef7cf7SAndrei Emeltchenko 	}
281476ef7cf7SAndrei Emeltchenko 
281576ef7cf7SAndrei Emeltchenko 	return NULL;
281676ef7cf7SAndrei Emeltchenko }
281776ef7cf7SAndrei Emeltchenko 
28186039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
281925e89e99SAndrei Emeltchenko {
282025e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
282125e89e99SAndrei Emeltchenko 	int i;
282225e89e99SAndrei Emeltchenko 
282325e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
282425e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
282525e89e99SAndrei Emeltchenko 		return;
282625e89e99SAndrei Emeltchenko 	}
282725e89e99SAndrei Emeltchenko 
282825e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
282925e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
283025e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
283125e89e99SAndrei Emeltchenko 		return;
283225e89e99SAndrei Emeltchenko 	}
283325e89e99SAndrei Emeltchenko 
283425e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
283525e89e99SAndrei Emeltchenko 	       ev->num_hndl);
283625e89e99SAndrei Emeltchenko 
283725e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
283825e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
283976ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
284025e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
284125e89e99SAndrei Emeltchenko 
284225e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
284325e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
284425e89e99SAndrei Emeltchenko 
284576ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
284625e89e99SAndrei Emeltchenko 		if (!conn)
284725e89e99SAndrei Emeltchenko 			continue;
284825e89e99SAndrei Emeltchenko 
284925e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
285025e89e99SAndrei Emeltchenko 
285125e89e99SAndrei Emeltchenko 		switch (conn->type) {
285225e89e99SAndrei Emeltchenko 		case ACL_LINK:
2853bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
285425e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
285525e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
285625e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
285725e89e99SAndrei Emeltchenko 			break;
285825e89e99SAndrei Emeltchenko 
285925e89e99SAndrei Emeltchenko 		default:
286025e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
286125e89e99SAndrei Emeltchenko 			break;
286225e89e99SAndrei Emeltchenko 		}
286325e89e99SAndrei Emeltchenko 	}
286425e89e99SAndrei Emeltchenko 
286525e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
286625e89e99SAndrei Emeltchenko }
286725e89e99SAndrei Emeltchenko 
28686039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
28691da177e4SLinus Torvalds {
2870a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
287104837f64SMarcel Holtmann 	struct hci_conn *conn;
28721da177e4SLinus Torvalds 
28739f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
28741da177e4SLinus Torvalds 
28751da177e4SLinus Torvalds 	hci_dev_lock(hdev);
28761da177e4SLinus Torvalds 
287704837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
287804837f64SMarcel Holtmann 	if (conn) {
287904837f64SMarcel Holtmann 		conn->mode = ev->mode;
288004837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
288104837f64SMarcel Holtmann 
28828fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
28838fc9ced3SGustavo Padovan 					&conn->flags)) {
288404837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
288558a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
288604837f64SMarcel Holtmann 			else
288758a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
288804837f64SMarcel Holtmann 		}
2889e73439d8SMarcel Holtmann 
289051a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2891e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
289204837f64SMarcel Holtmann 	}
289304837f64SMarcel Holtmann 
289404837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
289504837f64SMarcel Holtmann }
289604837f64SMarcel Holtmann 
28976039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
28981da177e4SLinus Torvalds {
2899052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2900052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2901052b30b0SMarcel Holtmann 
2902a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2903052b30b0SMarcel Holtmann 
2904052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2905052b30b0SMarcel Holtmann 
2906052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2907b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2908b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2909b6f98044SWaldemar Rymarkiewicz 
2910b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2911052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2912052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2913052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2914052b30b0SMarcel Holtmann 	}
2915052b30b0SMarcel Holtmann 
2916a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
291703b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
291803b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2919a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2920a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2921a770bb5aSWaldemar Rymarkiewicz 
2922a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2923a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2924a770bb5aSWaldemar Rymarkiewicz 		else
2925a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2926a770bb5aSWaldemar Rymarkiewicz 
2927744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2928a770bb5aSWaldemar Rymarkiewicz 	}
2929980e1a53SJohan Hedberg 
2930b6f98044SWaldemar Rymarkiewicz unlock:
2931052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
29321da177e4SLinus Torvalds }
29331da177e4SLinus Torvalds 
29346039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29351da177e4SLinus Torvalds {
293655ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
293755ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
293855ed8ca1SJohan Hedberg 	struct hci_conn *conn;
293955ed8ca1SJohan Hedberg 	struct link_key *key;
294055ed8ca1SJohan Hedberg 
2941a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
294255ed8ca1SJohan Hedberg 
2943a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
294455ed8ca1SJohan Hedberg 		return;
294555ed8ca1SJohan Hedberg 
294655ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
294755ed8ca1SJohan Hedberg 
294855ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
294955ed8ca1SJohan Hedberg 	if (!key) {
29506ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
29516ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
295255ed8ca1SJohan Hedberg 		goto not_found;
295355ed8ca1SJohan Hedberg 	}
295455ed8ca1SJohan Hedberg 
29556ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
29566ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
295755ed8ca1SJohan Hedberg 
2958a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2959b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
296055ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
296155ed8ca1SJohan Hedberg 		goto not_found;
296255ed8ca1SJohan Hedberg 	}
296355ed8ca1SJohan Hedberg 
296455ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
296560b83f57SWaldemar Rymarkiewicz 	if (conn) {
296660b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2967807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
296855ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
296955ed8ca1SJohan Hedberg 			goto not_found;
297055ed8ca1SJohan Hedberg 		}
297155ed8ca1SJohan Hedberg 
297260b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
297360b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
29748fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
29758fc9ced3SGustavo Padovan 			       hdev->name);
297660b83f57SWaldemar Rymarkiewicz 			goto not_found;
297760b83f57SWaldemar Rymarkiewicz 		}
297860b83f57SWaldemar Rymarkiewicz 
297960b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
298060b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
298160b83f57SWaldemar Rymarkiewicz 	}
298260b83f57SWaldemar Rymarkiewicz 
298355ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
29849b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
298555ed8ca1SJohan Hedberg 
298655ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
298755ed8ca1SJohan Hedberg 
298855ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
298955ed8ca1SJohan Hedberg 
299055ed8ca1SJohan Hedberg 	return;
299155ed8ca1SJohan Hedberg 
299255ed8ca1SJohan Hedberg not_found:
299355ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
299455ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
29951da177e4SLinus Torvalds }
29961da177e4SLinus Torvalds 
29976039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
29981da177e4SLinus Torvalds {
2999052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
3000052b30b0SMarcel Holtmann 	struct hci_conn *conn;
300155ed8ca1SJohan Hedberg 	u8 pin_len = 0;
3002052b30b0SMarcel Holtmann 
3003a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3004052b30b0SMarcel Holtmann 
3005052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
3006052b30b0SMarcel Holtmann 
3007052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
3008052b30b0SMarcel Holtmann 	if (conn) {
3009052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3010052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3011980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
301213d39315SWaldemar Rymarkiewicz 
301313d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
301413d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
301513d39315SWaldemar Rymarkiewicz 
3016052b30b0SMarcel Holtmann 		hci_conn_put(conn);
3017052b30b0SMarcel Holtmann 	}
3018052b30b0SMarcel Holtmann 
3019a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
3020d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
302155ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
302255ed8ca1SJohan Hedberg 
3023052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
30241da177e4SLinus Torvalds }
30251da177e4SLinus Torvalds 
30266039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
302704837f64SMarcel Holtmann {
3028a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
302904837f64SMarcel Holtmann 	struct hci_conn *conn;
303004837f64SMarcel Holtmann 
30319f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
303204837f64SMarcel Holtmann 
303304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
303404837f64SMarcel Holtmann 
303504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30361da177e4SLinus Torvalds 	if (conn && !ev->status) {
30371da177e4SLinus Torvalds 		struct inquiry_entry *ie;
30381da177e4SLinus Torvalds 
3039cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3040cc11b9c1SAndrei Emeltchenko 		if (ie) {
30411da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
30421da177e4SLinus Torvalds 			ie->timestamp = jiffies;
30431da177e4SLinus Torvalds 		}
30441da177e4SLinus Torvalds 	}
30451da177e4SLinus Torvalds 
30461da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
30471da177e4SLinus Torvalds }
30481da177e4SLinus Torvalds 
30496039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3050a8746417SMarcel Holtmann {
3051a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3052a8746417SMarcel Holtmann 	struct hci_conn *conn;
3053a8746417SMarcel Holtmann 
30549f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3055a8746417SMarcel Holtmann 
3056a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
3057a8746417SMarcel Holtmann 
3058a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3059a8746417SMarcel Holtmann 	if (conn && !ev->status)
3060a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3061a8746417SMarcel Holtmann 
3062a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
3063a8746417SMarcel Holtmann }
3064a8746417SMarcel Holtmann 
30656039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
306685a1e930SMarcel Holtmann {
3067a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
306885a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
306985a1e930SMarcel Holtmann 
307085a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
307185a1e930SMarcel Holtmann 
307285a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
307385a1e930SMarcel Holtmann 
3074cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3075cc11b9c1SAndrei Emeltchenko 	if (ie) {
307685a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
307785a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
307885a1e930SMarcel Holtmann 	}
307985a1e930SMarcel Holtmann 
308085a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
308185a1e930SMarcel Holtmann }
308285a1e930SMarcel Holtmann 
30836039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3084807deac2SGustavo Padovan 					     struct sk_buff *skb)
3085a9de9248SMarcel Holtmann {
3086a9de9248SMarcel Holtmann 	struct inquiry_data data;
3087a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
3088388fc8faSJohan Hedberg 	bool name_known, ssp;
3089a9de9248SMarcel Holtmann 
3090a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3091a9de9248SMarcel Holtmann 
3092a9de9248SMarcel Holtmann 	if (!num_rsp)
3093a9de9248SMarcel Holtmann 		return;
3094a9de9248SMarcel Holtmann 
30951519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30961519cc17SAndre Guedes 		return;
30971519cc17SAndre Guedes 
3098a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3099a9de9248SMarcel Holtmann 
3100a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3101138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3102138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3103a9de9248SMarcel Holtmann 
3104e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3105a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3106a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3107a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3108a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3109a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3110a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3111a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
311241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
31133175405bSJohan Hedberg 
31143175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3115388fc8faSJohan Hedberg 							      false, &ssp);
311648264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3117e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3118388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3119a9de9248SMarcel Holtmann 		}
3120a9de9248SMarcel Holtmann 	} else {
3121a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3122a9de9248SMarcel Holtmann 
3123e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3124a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3125a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3126a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3127a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3128a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3129a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3130a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
313141a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
31323175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3133388fc8faSJohan Hedberg 							      false, &ssp);
313448264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3135e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3136388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3137a9de9248SMarcel Holtmann 		}
3138a9de9248SMarcel Holtmann 	}
3139a9de9248SMarcel Holtmann 
3140a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3141a9de9248SMarcel Holtmann }
3142a9de9248SMarcel Holtmann 
31436039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3144807deac2SGustavo Padovan 					struct sk_buff *skb)
3145a9de9248SMarcel Holtmann {
314641a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
314741a96212SMarcel Holtmann 	struct hci_conn *conn;
314841a96212SMarcel Holtmann 
3149a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
315041a96212SMarcel Holtmann 
315141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
315241a96212SMarcel Holtmann 
315341a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3154ccd556feSJohan Hedberg 	if (!conn)
3155ccd556feSJohan Hedberg 		goto unlock;
3156ccd556feSJohan Hedberg 
3157769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
315841a96212SMarcel Holtmann 		struct inquiry_entry *ie;
315941a96212SMarcel Holtmann 
3160cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3161cc11b9c1SAndrei Emeltchenko 		if (ie)
316202b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
316341a96212SMarcel Holtmann 
316402b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
316558a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
316641a96212SMarcel Holtmann 	}
316741a96212SMarcel Holtmann 
3168ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3169ccd556feSJohan Hedberg 		goto unlock;
3170ccd556feSJohan Hedberg 
3171671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3172127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3173127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3174127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3175127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3176127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3177b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3178b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
317908c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
3180b644ba33SJohan Hedberg 				      conn->dev_class);
3181392599b9SJohan Hedberg 
3182127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3183769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3184769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
3185769be974SMarcel Holtmann 		hci_conn_put(conn);
3186769be974SMarcel Holtmann 	}
3187769be974SMarcel Holtmann 
3188ccd556feSJohan Hedberg unlock:
318941a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3190a9de9248SMarcel Holtmann }
3191a9de9248SMarcel Holtmann 
31926039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3193807deac2SGustavo Padovan 				       struct sk_buff *skb)
3194a9de9248SMarcel Holtmann {
3195b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3196b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3197b6a0dc82SMarcel Holtmann 
31989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3199b6a0dc82SMarcel Holtmann 
3200b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3201b6a0dc82SMarcel Holtmann 
3202b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
32039dc0a3afSMarcel Holtmann 	if (!conn) {
32049dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
32059dc0a3afSMarcel Holtmann 			goto unlock;
32069dc0a3afSMarcel Holtmann 
32079dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3208b6a0dc82SMarcel Holtmann 		if (!conn)
3209b6a0dc82SMarcel Holtmann 			goto unlock;
3210b6a0dc82SMarcel Holtmann 
32119dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
32129dc0a3afSMarcel Holtmann 	}
32139dc0a3afSMarcel Holtmann 
3214732547f9SMarcel Holtmann 	switch (ev->status) {
3215732547f9SMarcel Holtmann 	case 0x00:
3216732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3217732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3218732547f9SMarcel Holtmann 
32199eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
3220732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3221732547f9SMarcel Holtmann 		break;
3222732547f9SMarcel Holtmann 
3223705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3224732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
32251038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3226732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
3227732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
3228efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3229efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
3230efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
3231efc7688bSMarcel Holtmann 			goto unlock;
3232efc7688bSMarcel Holtmann 		}
3233732547f9SMarcel Holtmann 		/* fall through */
3234efc7688bSMarcel Holtmann 
3235732547f9SMarcel Holtmann 	default:
3236b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3237732547f9SMarcel Holtmann 		break;
3238732547f9SMarcel Holtmann 	}
3239b6a0dc82SMarcel Holtmann 
3240b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3241b6a0dc82SMarcel Holtmann 	if (ev->status)
3242b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3243b6a0dc82SMarcel Holtmann 
3244b6a0dc82SMarcel Holtmann unlock:
3245b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3246a9de9248SMarcel Holtmann }
3247a9de9248SMarcel Holtmann 
32486039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
3249a9de9248SMarcel Holtmann {
3250a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3251a9de9248SMarcel Holtmann }
3252a9de9248SMarcel Holtmann 
32536039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
325404837f64SMarcel Holtmann {
3255a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
325604837f64SMarcel Holtmann 
32579f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
325804837f64SMarcel Holtmann }
325904837f64SMarcel Holtmann 
32606039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3261807deac2SGustavo Padovan 					    struct sk_buff *skb)
3262a9de9248SMarcel Holtmann {
3263a9de9248SMarcel Holtmann 	struct inquiry_data data;
3264a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3265a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
32669d939d94SVishal Agarwal 	size_t eir_len;
3267a9de9248SMarcel Holtmann 
3268a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3269a9de9248SMarcel Holtmann 
3270a9de9248SMarcel Holtmann 	if (!num_rsp)
3271a9de9248SMarcel Holtmann 		return;
3272a9de9248SMarcel Holtmann 
32731519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
32741519cc17SAndre Guedes 		return;
32751519cc17SAndre Guedes 
3276a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3277a9de9248SMarcel Holtmann 
3278e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3279388fc8faSJohan Hedberg 		bool name_known, ssp;
3280561aafbcSJohan Hedberg 
3281a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3282a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3283a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3284a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3285a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3286a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3287a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
328841a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3289561aafbcSJohan Hedberg 
3290a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
32914ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
32924ddb1930SJohan Hedberg 						       sizeof(info->data),
32934ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3294561aafbcSJohan Hedberg 		else
3295561aafbcSJohan Hedberg 			name_known = true;
3296561aafbcSJohan Hedberg 
3297388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3298388fc8faSJohan Hedberg 						      &ssp);
32999d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
330048264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
330104124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
33029d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3303a9de9248SMarcel Holtmann 	}
3304a9de9248SMarcel Holtmann 
3305a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3306a9de9248SMarcel Holtmann }
3307a9de9248SMarcel Holtmann 
33081c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
33091c2e0041SJohan Hedberg 					 struct sk_buff *skb)
33101c2e0041SJohan Hedberg {
33111c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
33121c2e0041SJohan Hedberg 	struct hci_conn *conn;
33131c2e0041SJohan Hedberg 
33149f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
33151c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
33161c2e0041SJohan Hedberg 
33171c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
33181c2e0041SJohan Hedberg 
33191c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
33201c2e0041SJohan Hedberg 	if (!conn)
33211c2e0041SJohan Hedberg 		goto unlock;
33221c2e0041SJohan Hedberg 
33231c2e0041SJohan Hedberg 	if (!ev->status)
33241c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
33251c2e0041SJohan Hedberg 
33261c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
33271c2e0041SJohan Hedberg 
33281c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
33291c2e0041SJohan Hedberg 		hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
33301c2e0041SJohan Hedberg 		hci_conn_put(conn);
33311c2e0041SJohan Hedberg 		goto unlock;
33321c2e0041SJohan Hedberg 	}
33331c2e0041SJohan Hedberg 
33341c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
33351c2e0041SJohan Hedberg 		if (!ev->status)
33361c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
33371c2e0041SJohan Hedberg 
33381c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
33391c2e0041SJohan Hedberg 		hci_conn_put(conn);
33401c2e0041SJohan Hedberg 	} else {
33411c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
33421c2e0041SJohan Hedberg 
33431c2e0041SJohan Hedberg 		hci_conn_hold(conn);
33441c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
33451c2e0041SJohan Hedberg 		hci_conn_put(conn);
33461c2e0041SJohan Hedberg 	}
33471c2e0041SJohan Hedberg 
33481c2e0041SJohan Hedberg unlock:
33491c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
33501c2e0041SJohan Hedberg }
33511c2e0041SJohan Hedberg 
33526039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
335317fa4b9dSJohan Hedberg {
335417fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
335517fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
335617fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
335717fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
335817fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
335917fa4b9dSJohan Hedberg 			return 0x02;
336017fa4b9dSJohan Hedberg 		else
336117fa4b9dSJohan Hedberg 			return 0x03;
336217fa4b9dSJohan Hedberg 	}
336317fa4b9dSJohan Hedberg 
336417fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
336517fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
336658797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
336717fa4b9dSJohan Hedberg 
336817fa4b9dSJohan Hedberg 	return conn->auth_type;
336917fa4b9dSJohan Hedberg }
337017fa4b9dSJohan Hedberg 
33716039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
33720493684eSMarcel Holtmann {
33730493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
33740493684eSMarcel Holtmann 	struct hci_conn *conn;
33750493684eSMarcel Holtmann 
33760493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
33770493684eSMarcel Holtmann 
33780493684eSMarcel Holtmann 	hci_dev_lock(hdev);
33790493684eSMarcel Holtmann 
33800493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
338103b555e1SJohan Hedberg 	if (!conn)
338203b555e1SJohan Hedberg 		goto unlock;
338303b555e1SJohan Hedberg 
33840493684eSMarcel Holtmann 	hci_conn_hold(conn);
33850493684eSMarcel Holtmann 
3386a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
338703b555e1SJohan Hedberg 		goto unlock;
338803b555e1SJohan Hedberg 
3389a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
339003b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
339117fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
339217fa4b9dSJohan Hedberg 
339317fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
33947a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
33957a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
33967a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
33977a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
33987cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
33997cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
340017fa4b9dSJohan Hedberg 
34018fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
34028fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3403ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3404ce85ee13SSzymon Janc 		else
3405ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3406ce85ee13SSzymon Janc 
340717fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
340817fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
340903b555e1SJohan Hedberg 	} else {
341003b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
341103b555e1SJohan Hedberg 
341203b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
34139f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
341403b555e1SJohan Hedberg 
341503b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
341603b555e1SJohan Hedberg 			     sizeof(cp), &cp);
341703b555e1SJohan Hedberg 	}
341803b555e1SJohan Hedberg 
341903b555e1SJohan Hedberg unlock:
342003b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
342103b555e1SJohan Hedberg }
342203b555e1SJohan Hedberg 
34236039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
342403b555e1SJohan Hedberg {
342503b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
342603b555e1SJohan Hedberg 	struct hci_conn *conn;
342703b555e1SJohan Hedberg 
342803b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
342903b555e1SJohan Hedberg 
343003b555e1SJohan Hedberg 	hci_dev_lock(hdev);
343103b555e1SJohan Hedberg 
343203b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
343303b555e1SJohan Hedberg 	if (!conn)
343403b555e1SJohan Hedberg 		goto unlock;
343503b555e1SJohan Hedberg 
343603b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
343703b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
343858a681efSJohan Hedberg 	if (ev->oob_data)
343958a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
344003b555e1SJohan Hedberg 
344103b555e1SJohan Hedberg unlock:
34420493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
34430493684eSMarcel Holtmann }
34440493684eSMarcel Holtmann 
34456039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3446a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3447a5c29683SJohan Hedberg {
3448a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
344955bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
34507a828908SJohan Hedberg 	struct hci_conn *conn;
3451a5c29683SJohan Hedberg 
3452a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3453a5c29683SJohan Hedberg 
3454a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3455a5c29683SJohan Hedberg 
3456a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
34577a828908SJohan Hedberg 		goto unlock;
34587a828908SJohan Hedberg 
34597a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
34607a828908SJohan Hedberg 	if (!conn)
34617a828908SJohan Hedberg 		goto unlock;
34627a828908SJohan Hedberg 
34637a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
34647a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
34657a828908SJohan Hedberg 
34667a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
34677a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
34687a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
34697a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
34707a828908SJohan Hedberg 	 * bit set. */
34717a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
34727a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
34737a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
34747a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
34757a828908SJohan Hedberg 		goto unlock;
34767a828908SJohan Hedberg 	}
34777a828908SJohan Hedberg 
34787a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
34797a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
34807a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
348155bc1a37SJohan Hedberg 
348255bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
348355bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
348455bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
348551a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
348655bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
348755bc1a37SJohan Hedberg 			confirm_hint = 1;
348855bc1a37SJohan Hedberg 			goto confirm;
348955bc1a37SJohan Hedberg 		}
349055bc1a37SJohan Hedberg 
34919f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
34929f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
34939f61656aSJohan Hedberg 
34949f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
34959f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
34969f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
34979f61656aSJohan Hedberg 			goto unlock;
34989f61656aSJohan Hedberg 		}
34999f61656aSJohan Hedberg 
35007a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
35017a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
35027a828908SJohan Hedberg 		goto unlock;
35037a828908SJohan Hedberg 	}
35047a828908SJohan Hedberg 
350555bc1a37SJohan Hedberg confirm:
3506272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
350755bc1a37SJohan Hedberg 				  confirm_hint);
3508a5c29683SJohan Hedberg 
35097a828908SJohan Hedberg unlock:
3510a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3511a5c29683SJohan Hedberg }
3512a5c29683SJohan Hedberg 
35136039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
35141143d458SBrian Gix 					 struct sk_buff *skb)
35151143d458SBrian Gix {
35161143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
35171143d458SBrian Gix 
35181143d458SBrian Gix 	BT_DBG("%s", hdev->name);
35191143d458SBrian Gix 
3520a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3521272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
35221143d458SBrian Gix }
35231143d458SBrian Gix 
352492a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
352592a25256SJohan Hedberg 					struct sk_buff *skb)
352692a25256SJohan Hedberg {
352792a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
352892a25256SJohan Hedberg 	struct hci_conn *conn;
352992a25256SJohan Hedberg 
353092a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
353192a25256SJohan Hedberg 
353292a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
353392a25256SJohan Hedberg 	if (!conn)
353492a25256SJohan Hedberg 		return;
353592a25256SJohan Hedberg 
353692a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
353792a25256SJohan Hedberg 	conn->passkey_entered = 0;
353892a25256SJohan Hedberg 
353992a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
354092a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
354192a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
354292a25256SJohan Hedberg 					 conn->passkey_entered);
354392a25256SJohan Hedberg }
354492a25256SJohan Hedberg 
354592a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
354692a25256SJohan Hedberg {
354792a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
354892a25256SJohan Hedberg 	struct hci_conn *conn;
354992a25256SJohan Hedberg 
355092a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
355192a25256SJohan Hedberg 
355292a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
355392a25256SJohan Hedberg 	if (!conn)
355492a25256SJohan Hedberg 		return;
355592a25256SJohan Hedberg 
355692a25256SJohan Hedberg 	switch (ev->type) {
355792a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
355892a25256SJohan Hedberg 		conn->passkey_entered = 0;
355992a25256SJohan Hedberg 		return;
356092a25256SJohan Hedberg 
356192a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
356292a25256SJohan Hedberg 		conn->passkey_entered++;
356392a25256SJohan Hedberg 		break;
356492a25256SJohan Hedberg 
356592a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
356692a25256SJohan Hedberg 		conn->passkey_entered--;
356792a25256SJohan Hedberg 		break;
356892a25256SJohan Hedberg 
356992a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
357092a25256SJohan Hedberg 		conn->passkey_entered = 0;
357192a25256SJohan Hedberg 		break;
357292a25256SJohan Hedberg 
357392a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
357492a25256SJohan Hedberg 		return;
357592a25256SJohan Hedberg 	}
357692a25256SJohan Hedberg 
357792a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
357892a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
357992a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
358092a25256SJohan Hedberg 					 conn->passkey_entered);
358192a25256SJohan Hedberg }
358292a25256SJohan Hedberg 
35836039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3584807deac2SGustavo Padovan 					 struct sk_buff *skb)
35850493684eSMarcel Holtmann {
35860493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
35870493684eSMarcel Holtmann 	struct hci_conn *conn;
35880493684eSMarcel Holtmann 
35890493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
35900493684eSMarcel Holtmann 
35910493684eSMarcel Holtmann 	hci_dev_lock(hdev);
35920493684eSMarcel Holtmann 
35930493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
35942a611692SJohan Hedberg 	if (!conn)
35952a611692SJohan Hedberg 		goto unlock;
35962a611692SJohan Hedberg 
35972a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
35982a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
35992a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
36002a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
36012a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3602fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3603bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3604bab73cb6SJohan Hedberg 				 ev->status);
36052a611692SJohan Hedberg 
36060493684eSMarcel Holtmann 	hci_conn_put(conn);
36070493684eSMarcel Holtmann 
36082a611692SJohan Hedberg unlock:
36090493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
36100493684eSMarcel Holtmann }
36110493684eSMarcel Holtmann 
36126039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3613807deac2SGustavo Padovan 					 struct sk_buff *skb)
361441a96212SMarcel Holtmann {
361541a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
361641a96212SMarcel Holtmann 	struct inquiry_entry *ie;
361741a96212SMarcel Holtmann 
361841a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
361941a96212SMarcel Holtmann 
362041a96212SMarcel Holtmann 	hci_dev_lock(hdev);
362141a96212SMarcel Holtmann 
3622cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3623cc11b9c1SAndrei Emeltchenko 	if (ie)
362402b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
362541a96212SMarcel Holtmann 
362641a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
362741a96212SMarcel Holtmann }
362841a96212SMarcel Holtmann 
36296039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
36302763eda6SSzymon Janc 					    struct sk_buff *skb)
36312763eda6SSzymon Janc {
36322763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
36332763eda6SSzymon Janc 	struct oob_data *data;
36342763eda6SSzymon Janc 
36352763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
36362763eda6SSzymon Janc 
36372763eda6SSzymon Janc 	hci_dev_lock(hdev);
36382763eda6SSzymon Janc 
3639a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3640e1ba1f15SSzymon Janc 		goto unlock;
3641e1ba1f15SSzymon Janc 
36422763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
36432763eda6SSzymon Janc 	if (data) {
36442763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
36452763eda6SSzymon Janc 
36462763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
36472763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
36482763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
36492763eda6SSzymon Janc 
36502763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
36512763eda6SSzymon Janc 			     &cp);
36522763eda6SSzymon Janc 	} else {
36532763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
36542763eda6SSzymon Janc 
36552763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
36562763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
36572763eda6SSzymon Janc 			     &cp);
36582763eda6SSzymon Janc 	}
36592763eda6SSzymon Janc 
3660e1ba1f15SSzymon Janc unlock:
36612763eda6SSzymon Janc 	hci_dev_unlock(hdev);
36622763eda6SSzymon Janc }
36632763eda6SSzymon Janc 
3664d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3665d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3666d5e91192SAndrei Emeltchenko {
3667d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3668d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3669d5e91192SAndrei Emeltchenko 
3670d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3671d5e91192SAndrei Emeltchenko 	       ev->status);
3672d5e91192SAndrei Emeltchenko 
3673d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3674d5e91192SAndrei Emeltchenko 
3675d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3676d5e91192SAndrei Emeltchenko 	if (!hcon) {
3677d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3678d5e91192SAndrei Emeltchenko 		return;
3679d5e91192SAndrei Emeltchenko 	}
3680d5e91192SAndrei Emeltchenko 
3681d5e91192SAndrei Emeltchenko 	if (ev->status) {
3682d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3683d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3684d5e91192SAndrei Emeltchenko 		return;
3685d5e91192SAndrei Emeltchenko 	}
3686d5e91192SAndrei Emeltchenko 
3687d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3688d5e91192SAndrei Emeltchenko 
3689d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3690d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3691d5e91192SAndrei Emeltchenko 
3692d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3693d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3694d5e91192SAndrei Emeltchenko 	hci_conn_put(hcon);
3695d5e91192SAndrei Emeltchenko 
3696d5e91192SAndrei Emeltchenko 	hci_conn_hold_device(hcon);
3697d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3698d5e91192SAndrei Emeltchenko 
3699d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3700d5e91192SAndrei Emeltchenko 
3701d5e91192SAndrei Emeltchenko 	if (hcon->out) {
3702d5e91192SAndrei Emeltchenko 		struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev);
3703d5e91192SAndrei Emeltchenko 
3704d5e91192SAndrei Emeltchenko 		if (!bredr_hdev)
3705d5e91192SAndrei Emeltchenko 			return;
3706d5e91192SAndrei Emeltchenko 
3707d5e91192SAndrei Emeltchenko 		/* Placeholder - create chan req
3708d5e91192SAndrei Emeltchenko 		l2cap_chan_create_cfm(bredr_hcon, hcon->remote_id);
3709d5e91192SAndrei Emeltchenko 		*/
3710d5e91192SAndrei Emeltchenko 
3711d5e91192SAndrei Emeltchenko 		hci_dev_put(bredr_hdev);
3712d5e91192SAndrei Emeltchenko 	}
3713d5e91192SAndrei Emeltchenko }
3714d5e91192SAndrei Emeltchenko 
371527695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
371627695fb4SAndrei Emeltchenko {
371727695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
371827695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
371927695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
372027695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
372127695fb4SAndrei Emeltchenko 
372227695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
372327695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
372427695fb4SAndrei Emeltchenko 	       ev->status);
372527695fb4SAndrei Emeltchenko 
372627695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
372727695fb4SAndrei Emeltchenko 	if (!hcon)
372827695fb4SAndrei Emeltchenko 		return;
372927695fb4SAndrei Emeltchenko 
373027695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
373127695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
373227695fb4SAndrei Emeltchenko 	if (!hchan)
373327695fb4SAndrei Emeltchenko 		return;
373427695fb4SAndrei Emeltchenko 
373527695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
373627695fb4SAndrei Emeltchenko 
373727695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
373827695fb4SAndrei Emeltchenko 
373927695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
374027695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
374127695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
374227695fb4SAndrei Emeltchenko 
374327695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
374427695fb4SAndrei Emeltchenko 
374527695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
374627695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
374727695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
374827695fb4SAndrei Emeltchenko 
374927695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
375027695fb4SAndrei Emeltchenko 	}
375127695fb4SAndrei Emeltchenko }
375227695fb4SAndrei Emeltchenko 
3753606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3754606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3755606e2a10SAndrei Emeltchenko {
3756606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3757606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3758606e2a10SAndrei Emeltchenko 
3759606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3760606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3761606e2a10SAndrei Emeltchenko 
3762606e2a10SAndrei Emeltchenko 	if (ev->status)
3763606e2a10SAndrei Emeltchenko 		return;
3764606e2a10SAndrei Emeltchenko 
3765606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3766606e2a10SAndrei Emeltchenko 
3767606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3768606e2a10SAndrei Emeltchenko 	if (!hchan)
3769606e2a10SAndrei Emeltchenko 		goto unlock;
3770606e2a10SAndrei Emeltchenko 
3771606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3772606e2a10SAndrei Emeltchenko 
3773606e2a10SAndrei Emeltchenko unlock:
3774606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3775606e2a10SAndrei Emeltchenko }
3776606e2a10SAndrei Emeltchenko 
37779eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
37789eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
37799eef6b3aSAndrei Emeltchenko {
37809eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
37819eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
37829eef6b3aSAndrei Emeltchenko 
37839eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
37849eef6b3aSAndrei Emeltchenko 
37859eef6b3aSAndrei Emeltchenko 	if (ev->status)
37869eef6b3aSAndrei Emeltchenko 		return;
37879eef6b3aSAndrei Emeltchenko 
37889eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
37899eef6b3aSAndrei Emeltchenko 
37909eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
37919eef6b3aSAndrei Emeltchenko 	if (hcon) {
37929eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
37939eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
37949eef6b3aSAndrei Emeltchenko 	}
37959eef6b3aSAndrei Emeltchenko 
37969eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
37979eef6b3aSAndrei Emeltchenko }
37989eef6b3aSAndrei Emeltchenko 
37996039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3800fcd89c09SVille Tervo {
3801fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3802fcd89c09SVille Tervo 	struct hci_conn *conn;
3803fcd89c09SVille Tervo 
38049f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3805fcd89c09SVille Tervo 
3806fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3807fcd89c09SVille Tervo 
38084f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3809b62f328bSVille Tervo 	if (!conn) {
3810b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3811b62f328bSVille Tervo 		if (!conn) {
3812b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3813230fd16aSAndre Guedes 			goto unlock;
3814b62f328bSVille Tervo 		}
381529b7988aSAndre Guedes 
381629b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3817b9b343d2SAndre Guedes 
3818b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3819b9b343d2SAndre Guedes 			conn->out = true;
3820b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3821b9b343d2SAndre Guedes 		}
3822b62f328bSVille Tervo 	}
3823fcd89c09SVille Tervo 
3824cd17decbSAndre Guedes 	if (ev->status) {
3825cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3826cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3827cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3828cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3829cd17decbSAndre Guedes 		hci_conn_del(conn);
3830cd17decbSAndre Guedes 		goto unlock;
3831cd17decbSAndre Guedes 	}
3832cd17decbSAndre Guedes 
3833b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3834b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
383595b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
383683bc71b4SVinicius Costa Gomes 
38377b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3838fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3839fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3840fcd89c09SVille Tervo 
3841fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3842fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3843fcd89c09SVille Tervo 
3844fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3845fcd89c09SVille Tervo 
3846fcd89c09SVille Tervo unlock:
3847fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3848fcd89c09SVille Tervo }
3849fcd89c09SVille Tervo 
38506039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
38519aa04c91SAndre Guedes {
3852e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3853e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
38543c9e9195SAndre Guedes 	s8 rssi;
38559aa04c91SAndre Guedes 
38569aa04c91SAndre Guedes 	hci_dev_lock(hdev);
38579aa04c91SAndre Guedes 
3858e95beb41SAndre Guedes 	while (num_reports--) {
3859e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3860e95beb41SAndre Guedes 
38613c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
38623c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
386304124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
38643c9e9195SAndre Guedes 
3865e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
38669aa04c91SAndre Guedes 	}
38679aa04c91SAndre Guedes 
38689aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
38699aa04c91SAndre Guedes }
38709aa04c91SAndre Guedes 
38716039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3872a7a595f6SVinicius Costa Gomes {
3873a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3874a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3875bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3876a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3877c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3878a7a595f6SVinicius Costa Gomes 
38799f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3880a7a595f6SVinicius Costa Gomes 
3881a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3882a7a595f6SVinicius Costa Gomes 
3883a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3884bea710feSVinicius Costa Gomes 	if (conn == NULL)
3885bea710feSVinicius Costa Gomes 		goto not_found;
3886a7a595f6SVinicius Costa Gomes 
3887bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3888bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3889bea710feSVinicius Costa Gomes 		goto not_found;
3890bea710feSVinicius Costa Gomes 
3891bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3892a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3893c9839a11SVinicius Costa Gomes 
3894c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3895c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3896a7a595f6SVinicius Costa Gomes 
3897a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3898a7a595f6SVinicius Costa Gomes 
3899c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3900c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3901c9839a11SVinicius Costa Gomes 		kfree(ltk);
3902c9839a11SVinicius Costa Gomes 	}
3903c9839a11SVinicius Costa Gomes 
3904a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3905bea710feSVinicius Costa Gomes 
3906bea710feSVinicius Costa Gomes 	return;
3907bea710feSVinicius Costa Gomes 
3908bea710feSVinicius Costa Gomes not_found:
3909bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3910bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3911bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3912a7a595f6SVinicius Costa Gomes }
3913a7a595f6SVinicius Costa Gomes 
39146039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3915fcd89c09SVille Tervo {
3916fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3917fcd89c09SVille Tervo 
3918fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3919fcd89c09SVille Tervo 
3920fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3921fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3922fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3923fcd89c09SVille Tervo 		break;
3924fcd89c09SVille Tervo 
39259aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
39269aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
39279aa04c91SAndre Guedes 		break;
39289aa04c91SAndre Guedes 
3929a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3930a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3931a7a595f6SVinicius Costa Gomes 		break;
3932a7a595f6SVinicius Costa Gomes 
3933fcd89c09SVille Tervo 	default:
3934fcd89c09SVille Tervo 		break;
3935fcd89c09SVille Tervo 	}
3936fcd89c09SVille Tervo }
3937fcd89c09SVille Tervo 
39389495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
39399495b2eeSAndrei Emeltchenko {
39409495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
39419495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
39429495b2eeSAndrei Emeltchenko 
39439495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
39449495b2eeSAndrei Emeltchenko 
39459495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
39469495b2eeSAndrei Emeltchenko 
39479495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
39489495b2eeSAndrei Emeltchenko 	if (!hcon)
39499495b2eeSAndrei Emeltchenko 		return;
39509495b2eeSAndrei Emeltchenko 
39519495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
39529495b2eeSAndrei Emeltchenko }
39539495b2eeSAndrei Emeltchenko 
39541da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
39551da177e4SLinus Torvalds {
3956a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3957a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
39581da177e4SLinus Torvalds 
39591da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
39601da177e4SLinus Torvalds 
3961a9de9248SMarcel Holtmann 	switch (event) {
39621da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
39631da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
39641da177e4SLinus Torvalds 		break;
39651da177e4SLinus Torvalds 
39661da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
39671da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
39681da177e4SLinus Torvalds 		break;
39691da177e4SLinus Torvalds 
3970a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3971a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
397221d9e30eSMarcel Holtmann 		break;
397321d9e30eSMarcel Holtmann 
39741da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
39751da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
39761da177e4SLinus Torvalds 		break;
39771da177e4SLinus Torvalds 
39781da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
39791da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
39801da177e4SLinus Torvalds 		break;
39811da177e4SLinus Torvalds 
39821da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
39831da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
39841da177e4SLinus Torvalds 		break;
39851da177e4SLinus Torvalds 
3986a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3987a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3988a9de9248SMarcel Holtmann 		break;
3989a9de9248SMarcel Holtmann 
39901da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
39911da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
39921da177e4SLinus Torvalds 		break;
39931da177e4SLinus Torvalds 
3994a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3995a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3996a9de9248SMarcel Holtmann 		break;
3997a9de9248SMarcel Holtmann 
3998a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3999a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
4000a9de9248SMarcel Holtmann 		break;
4001a9de9248SMarcel Holtmann 
4002a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
4003a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
4004a9de9248SMarcel Holtmann 		break;
4005a9de9248SMarcel Holtmann 
4006a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
4007a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
4008a9de9248SMarcel Holtmann 		break;
4009a9de9248SMarcel Holtmann 
4010a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
4011a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
4012a9de9248SMarcel Holtmann 		break;
4013a9de9248SMarcel Holtmann 
4014a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
4015a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
4016a9de9248SMarcel Holtmann 		break;
4017a9de9248SMarcel Holtmann 
4018a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
4019a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
4020a9de9248SMarcel Holtmann 		break;
4021a9de9248SMarcel Holtmann 
4022a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
4023a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
4024a9de9248SMarcel Holtmann 		break;
4025a9de9248SMarcel Holtmann 
4026a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
4027a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
40281da177e4SLinus Torvalds 		break;
40291da177e4SLinus Torvalds 
40301da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
40311da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
40321da177e4SLinus Torvalds 		break;
40331da177e4SLinus Torvalds 
40341da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
40351da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
40361da177e4SLinus Torvalds 		break;
40371da177e4SLinus Torvalds 
40381da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
40391da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
40401da177e4SLinus Torvalds 		break;
40411da177e4SLinus Torvalds 
40421da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
40431da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
40441da177e4SLinus Torvalds 		break;
40451da177e4SLinus Torvalds 
4046a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
4047a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
4048a8746417SMarcel Holtmann 		break;
4049a8746417SMarcel Holtmann 
405085a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
405185a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
405285a1e930SMarcel Holtmann 		break;
405385a1e930SMarcel Holtmann 
4054a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4055a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
4056a9de9248SMarcel Holtmann 		break;
4057a9de9248SMarcel Holtmann 
4058a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
4059a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
4060a9de9248SMarcel Holtmann 		break;
4061a9de9248SMarcel Holtmann 
4062a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
4063a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
4064a9de9248SMarcel Holtmann 		break;
4065a9de9248SMarcel Holtmann 
4066a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
4067a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
4068a9de9248SMarcel Holtmann 		break;
4069a9de9248SMarcel Holtmann 
407004837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
407104837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
407204837f64SMarcel Holtmann 		break;
407304837f64SMarcel Holtmann 
4074a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
4075a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
40761da177e4SLinus Torvalds 		break;
40771da177e4SLinus Torvalds 
40781c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
40791c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
40801c2e0041SJohan Hedberg 		break;
40811c2e0041SJohan Hedberg 
40820493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
40830493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
40840493684eSMarcel Holtmann 		break;
40850493684eSMarcel Holtmann 
408603b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
408703b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
408803b555e1SJohan Hedberg 		break;
408903b555e1SJohan Hedberg 
4090a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
4091a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
4092a5c29683SJohan Hedberg 		break;
4093a5c29683SJohan Hedberg 
40941143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
40951143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
40961143d458SBrian Gix 		break;
40971143d458SBrian Gix 
409892a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
409992a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
410092a25256SJohan Hedberg 		break;
410192a25256SJohan Hedberg 
410292a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
410392a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
410492a25256SJohan Hedberg 		break;
410592a25256SJohan Hedberg 
41060493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
41070493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
41080493684eSMarcel Holtmann 		break;
41090493684eSMarcel Holtmann 
411041a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
411141a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
411241a96212SMarcel Holtmann 		break;
411341a96212SMarcel Holtmann 
4114fcd89c09SVille Tervo 	case HCI_EV_LE_META:
4115fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
4116fcd89c09SVille Tervo 		break;
4117fcd89c09SVille Tervo 
41189495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
41199495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
41209495b2eeSAndrei Emeltchenko 		break;
41219495b2eeSAndrei Emeltchenko 
41222763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
41232763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
41242763eda6SSzymon Janc 		break;
41252763eda6SSzymon Janc 
4126d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
4127d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
4128d5e91192SAndrei Emeltchenko 		break;
4129d5e91192SAndrei Emeltchenko 
413027695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
413127695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
413227695fb4SAndrei Emeltchenko 		break;
413327695fb4SAndrei Emeltchenko 
4134606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4135606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
4136606e2a10SAndrei Emeltchenko 		break;
4137606e2a10SAndrei Emeltchenko 
41389eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
41399eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
41409eef6b3aSAndrei Emeltchenko 		break;
41419eef6b3aSAndrei Emeltchenko 
414225e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
414325e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
414425e89e99SAndrei Emeltchenko 		break;
414525e89e99SAndrei Emeltchenko 
41461da177e4SLinus Torvalds 	default:
41479f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
41481da177e4SLinus Torvalds 		break;
41491da177e4SLinus Torvalds 	}
41501da177e4SLinus Torvalds 
41511da177e4SLinus Torvalds 	kfree_skb(skb);
41521da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
41531da177e4SLinus Torvalds }
4154