xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 9eef6b3a)
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 	if (status)
181393c284eeSAndrei Emeltchenko 		return;
181493c284eeSAndrei Emeltchenko 
181593c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
181693c284eeSAndrei Emeltchenko 	if (!cp)
181793c284eeSAndrei Emeltchenko 		return;
181893c284eeSAndrei Emeltchenko 
181993c284eeSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
1820a02226d6SAndrei Emeltchenko }
1821a02226d6SAndrei Emeltchenko 
18220b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
18230b26ab9dSAndrei Emeltchenko {
18240b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
18250b26ab9dSAndrei Emeltchenko 
18260b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18270b26ab9dSAndrei Emeltchenko 
18280b26ab9dSAndrei Emeltchenko 	if (status)
18290b26ab9dSAndrei Emeltchenko 		return;
18300b26ab9dSAndrei Emeltchenko 
18310b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
18320b26ab9dSAndrei Emeltchenko 	if (!cp)
18330b26ab9dSAndrei Emeltchenko 		return;
18340b26ab9dSAndrei Emeltchenko 
18350b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
18360b26ab9dSAndrei Emeltchenko }
18370b26ab9dSAndrei Emeltchenko 
18385ce66b59SAndrei Emeltchenko static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
18395ce66b59SAndrei Emeltchenko {
18405ce66b59SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18415ce66b59SAndrei Emeltchenko }
18425ce66b59SAndrei Emeltchenko 
18436039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18441da177e4SLinus Torvalds {
18451da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
184630dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
184730dc78e1SJohan Hedberg 	struct inquiry_entry *e;
18481da177e4SLinus Torvalds 
18499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18501da177e4SLinus Torvalds 
185123bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
18526bd57416SMarcel Holtmann 
1853a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
185489352e7dSAndre Guedes 
185589352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
185689352e7dSAndre Guedes 		return;
185789352e7dSAndre Guedes 
1858a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
185930dc78e1SJohan Hedberg 		return;
186030dc78e1SJohan Hedberg 
186156e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
186230dc78e1SJohan Hedberg 
1863343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
186430dc78e1SJohan Hedberg 		goto unlock;
186530dc78e1SJohan Hedberg 
186630dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1867ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
186830dc78e1SJohan Hedberg 		goto unlock;
186930dc78e1SJohan Hedberg 	}
187030dc78e1SJohan Hedberg 
187130dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
187230dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
187330dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
187430dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
187530dc78e1SJohan Hedberg 	} else {
187630dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
187730dc78e1SJohan Hedberg 	}
187830dc78e1SJohan Hedberg 
187930dc78e1SJohan Hedberg unlock:
188056e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
18811da177e4SLinus Torvalds }
18821da177e4SLinus Torvalds 
18836039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
18841da177e4SLinus Torvalds {
188545bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1886a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
18871da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
18881da177e4SLinus Torvalds 
18891da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
18901da177e4SLinus Torvalds 
189145bb4bf0SMarcel Holtmann 	if (!num_rsp)
189245bb4bf0SMarcel Holtmann 		return;
189345bb4bf0SMarcel Holtmann 
18941519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
18951519cc17SAndre Guedes 		return;
18961519cc17SAndre Guedes 
18971da177e4SLinus Torvalds 	hci_dev_lock(hdev);
189845bb4bf0SMarcel Holtmann 
1899e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1900388fc8faSJohan Hedberg 		bool name_known, ssp;
19013175405bSJohan Hedberg 
19021da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
19031da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
19041da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
19051da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
19061da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
19071da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
19081da177e4SLinus Torvalds 		data.rssi		= 0x00;
190941a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
19103175405bSJohan Hedberg 
1911388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
191248264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
191304124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
191404124681SGustavo F. Padovan 				  0);
19151da177e4SLinus Torvalds 	}
191645bb4bf0SMarcel Holtmann 
19171da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19181da177e4SLinus Torvalds }
19191da177e4SLinus Torvalds 
19206039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19211da177e4SLinus Torvalds {
1922a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1923a9de9248SMarcel Holtmann 	struct hci_conn *conn;
19241da177e4SLinus Torvalds 
1925a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
192645bb4bf0SMarcel Holtmann 
19271da177e4SLinus Torvalds 	hci_dev_lock(hdev);
192845bb4bf0SMarcel Holtmann 
1929a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
19309499237aSMarcel Holtmann 	if (!conn) {
19319499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
19329499237aSMarcel Holtmann 			goto unlock;
19339499237aSMarcel Holtmann 
19349499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1935a9de9248SMarcel Holtmann 		if (!conn)
1936a9de9248SMarcel Holtmann 			goto unlock;
193745bb4bf0SMarcel Holtmann 
19389499237aSMarcel Holtmann 		conn->type = SCO_LINK;
19399499237aSMarcel Holtmann 	}
19409499237aSMarcel Holtmann 
1941a9de9248SMarcel Holtmann 	if (!ev->status) {
1942a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1943769be974SMarcel Holtmann 
1944769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1945769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1946769be974SMarcel Holtmann 			hci_conn_hold(conn);
1947a9ea3ed9SSzymon Janc 
1948a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1949a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1950a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1951a9ea3ed9SSzymon Janc 			else
1952052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1953769be974SMarcel Holtmann 		} else
1954a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1955a9de9248SMarcel Holtmann 
19569eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
19577d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
19587d0db0a3SMarcel Holtmann 
1959a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1960a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1961a9de9248SMarcel Holtmann 
1962a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1963a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1964a9de9248SMarcel Holtmann 
1965a9de9248SMarcel Holtmann 		/* Get remote features */
1966a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1967a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1968a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1969769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1970769be974SMarcel Holtmann 				     sizeof(cp), &cp);
197145bb4bf0SMarcel Holtmann 		}
1972a9de9248SMarcel Holtmann 
1973a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1974d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1975a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1976a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1977a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
197804124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
197904124681SGustavo F. Padovan 				     &cp);
1980a9de9248SMarcel Holtmann 		}
198117d5c04cSJohan Hedberg 	} else {
1982a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
198317d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1984744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
198548264f06SJohan Hedberg 					    conn->dst_type, ev->status);
198617d5c04cSJohan Hedberg 	}
198745bb4bf0SMarcel Holtmann 
1988e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1989e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
199045bb4bf0SMarcel Holtmann 
1991769be974SMarcel Holtmann 	if (ev->status) {
1992a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1993a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1994c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1995c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1996a9de9248SMarcel Holtmann 
1997a9de9248SMarcel Holtmann unlock:
19981da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1999a9de9248SMarcel Holtmann 
2000a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
20011da177e4SLinus Torvalds }
20021da177e4SLinus Torvalds 
20036039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
20041da177e4SLinus Torvalds {
2005a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
20061da177e4SLinus Torvalds 	int mask = hdev->link_mode;
20071da177e4SLinus Torvalds 
20086ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
2009807deac2SGustavo Padovan 	       ev->link_type);
20101da177e4SLinus Torvalds 
20111da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
20121da177e4SLinus Torvalds 
2013138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
2014138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
20151da177e4SLinus Torvalds 		/* Connection accepted */
2016c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
20171da177e4SLinus Torvalds 		struct hci_conn *conn;
20181da177e4SLinus Torvalds 
20191da177e4SLinus Torvalds 		hci_dev_lock(hdev);
2020b6a0dc82SMarcel Holtmann 
2021cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2022cc11b9c1SAndrei Emeltchenko 		if (ie)
2023c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
2024c7bdd502SMarcel Holtmann 
20258fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
20268fc9ced3SGustavo Padovan 					       &ev->bdaddr);
20271da177e4SLinus Torvalds 		if (!conn) {
2028cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2029cc11b9c1SAndrei Emeltchenko 			if (!conn) {
2030893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
20311da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
20321da177e4SLinus Torvalds 				return;
20331da177e4SLinus Torvalds 			}
20341da177e4SLinus Torvalds 		}
2035b6a0dc82SMarcel Holtmann 
20361da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
20371da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
2038b6a0dc82SMarcel Holtmann 
20391da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
20401da177e4SLinus Torvalds 
2041b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
2042b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
2043b6a0dc82SMarcel Holtmann 
20441da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
20451da177e4SLinus Torvalds 
20461da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
20471da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
20481da177e4SLinus Torvalds 			else
20491da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
20501da177e4SLinus Torvalds 
205104124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
205204124681SGustavo F. Padovan 				     &cp);
2053b6a0dc82SMarcel Holtmann 		} else {
2054b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
2055b6a0dc82SMarcel Holtmann 
2056b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
2057a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
2058b6a0dc82SMarcel Holtmann 
205982781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
206082781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
206182781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
2062b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
2063b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
2064b6a0dc82SMarcel Holtmann 
2065b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2066b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
2067b6a0dc82SMarcel Holtmann 		}
20681da177e4SLinus Torvalds 	} else {
20691da177e4SLinus Torvalds 		/* Connection rejected */
20701da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
20711da177e4SLinus Torvalds 
20721da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
20739f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
2074a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
20751da177e4SLinus Torvalds 	}
20761da177e4SLinus Torvalds }
20771da177e4SLinus Torvalds 
2078f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2079f0d6a0eaSMikel Astiz {
2080f0d6a0eaSMikel Astiz 	switch (err) {
2081f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2082f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2083f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2084f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2085f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2086f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2087f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2088f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2089f0d6a0eaSMikel Astiz 	default:
2090f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2091f0d6a0eaSMikel Astiz 	}
2092f0d6a0eaSMikel Astiz }
2093f0d6a0eaSMikel Astiz 
20946039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
20951da177e4SLinus Torvalds {
2096a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
209704837f64SMarcel Holtmann 	struct hci_conn *conn;
20981da177e4SLinus Torvalds 
20999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
21001da177e4SLinus Torvalds 
21011da177e4SLinus Torvalds 	hci_dev_lock(hdev);
21021da177e4SLinus Torvalds 
210304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2104f7520543SJohan Hedberg 	if (!conn)
2105f7520543SJohan Hedberg 		goto unlock;
2106f7520543SJohan Hedberg 
210737d9ef76SJohan Hedberg 	if (ev->status == 0)
21081da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
21097d0db0a3SMarcel Holtmann 
2110b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
2111b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
2112f0d6a0eaSMikel Astiz 		if (ev->status) {
211388c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
211488c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
2115f0d6a0eaSMikel Astiz 		} else {
2116f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
2117f0d6a0eaSMikel Astiz 
2118afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
2119f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
2120f0d6a0eaSMikel Astiz 		}
212137d9ef76SJohan Hedberg 	}
2122f7520543SJohan Hedberg 
212337d9ef76SJohan Hedberg 	if (ev->status == 0) {
21246ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
21256ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
21262950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
21271da177e4SLinus Torvalds 		hci_conn_del(conn);
212837d9ef76SJohan Hedberg 	}
21291da177e4SLinus Torvalds 
2130f7520543SJohan Hedberg unlock:
21311da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
21321da177e4SLinus Torvalds }
21331da177e4SLinus Torvalds 
21346039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2135a9de9248SMarcel Holtmann {
2136a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2137a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2138a9de9248SMarcel Holtmann 
21399f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2140a9de9248SMarcel Holtmann 
2141a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2142a9de9248SMarcel Holtmann 
2143a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2144d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2145d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2146d7556e20SWaldemar Rymarkiewicz 
2147765c2a96SJohan Hedberg 	if (!ev->status) {
2148aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
214951a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2150d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
215119f8def0SWaldemar Rymarkiewicz 		} else {
2152a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2153765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
215419f8def0SWaldemar Rymarkiewicz 		}
21552a611692SJohan Hedberg 	} else {
2156bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
2157bab73cb6SJohan Hedberg 				 ev->status);
21582a611692SJohan Hedberg 	}
2159a9de9248SMarcel Holtmann 
216051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
216151a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2162a9de9248SMarcel Holtmann 
2163f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2164aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2165f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2166f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2167f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2168d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2169d7556e20SWaldemar Rymarkiewicz 				     &cp);
2170f8558555SMarcel Holtmann 		} else {
2171f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2172f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2173f8558555SMarcel Holtmann 			hci_conn_put(conn);
2174f8558555SMarcel Holtmann 		}
2175052b30b0SMarcel Holtmann 	} else {
2176a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2177a9de9248SMarcel Holtmann 
2178052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2179052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2180052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2181052b30b0SMarcel Holtmann 	}
2182052b30b0SMarcel Holtmann 
218351a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2184a9de9248SMarcel Holtmann 		if (!ev->status) {
2185a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2186f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2187f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2188d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2189d7556e20SWaldemar Rymarkiewicz 				     &cp);
2190a9de9248SMarcel Holtmann 		} else {
219151a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2192a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2193a9de9248SMarcel Holtmann 		}
2194a9de9248SMarcel Holtmann 	}
2195a9de9248SMarcel Holtmann 
2196d7556e20SWaldemar Rymarkiewicz unlock:
2197a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2198a9de9248SMarcel Holtmann }
2199a9de9248SMarcel Holtmann 
22006039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2201a9de9248SMarcel Holtmann {
2202127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2203127178d2SJohan Hedberg 	struct hci_conn *conn;
2204127178d2SJohan Hedberg 
2205a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2206a9de9248SMarcel Holtmann 
2207a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2208127178d2SJohan Hedberg 
2209127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2210127178d2SJohan Hedberg 
2211127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2212b644ba33SJohan Hedberg 
2213b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2214b644ba33SJohan Hedberg 		goto check_auth;
2215b644ba33SJohan Hedberg 
2216b644ba33SJohan Hedberg 	if (ev->status == 0)
2217b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2218b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2219b644ba33SJohan Hedberg 	else
2220b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2221b644ba33SJohan Hedberg 
2222b644ba33SJohan Hedberg check_auth:
222379c6c70cSJohan Hedberg 	if (!conn)
222479c6c70cSJohan Hedberg 		goto unlock;
222579c6c70cSJohan Hedberg 
222679c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
222779c6c70cSJohan Hedberg 		goto unlock;
222879c6c70cSJohan Hedberg 
222951a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2230127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2231127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2232127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2233127178d2SJohan Hedberg 	}
2234127178d2SJohan Hedberg 
223579c6c70cSJohan Hedberg unlock:
2236127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2237a9de9248SMarcel Holtmann }
2238a9de9248SMarcel Holtmann 
22396039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2240a9de9248SMarcel Holtmann {
2241a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2242a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2243a9de9248SMarcel Holtmann 
22449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2245a9de9248SMarcel Holtmann 
2246a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2247a9de9248SMarcel Holtmann 
2248a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2249a9de9248SMarcel Holtmann 	if (conn) {
2250a9de9248SMarcel Holtmann 		if (!ev->status) {
2251ae293196SMarcel Holtmann 			if (ev->encrypt) {
2252ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2253ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2254a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2255da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2256ae293196SMarcel Holtmann 			} else
2257a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2258a9de9248SMarcel Holtmann 		}
2259a9de9248SMarcel Holtmann 
226051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2261a9de9248SMarcel Holtmann 
2262a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2263d839c813SGustavo Padovan 			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
2264a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2265a7d7723aSGustavo Padovan 			goto unlock;
2266a7d7723aSGustavo Padovan 		}
2267a7d7723aSGustavo Padovan 
2268f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2269f8558555SMarcel Holtmann 			if (!ev->status)
2270f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2271f8558555SMarcel Holtmann 
2272f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2273f8558555SMarcel Holtmann 			hci_conn_put(conn);
2274f8558555SMarcel Holtmann 		} else
2275a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2276a9de9248SMarcel Holtmann 	}
2277a9de9248SMarcel Holtmann 
2278a7d7723aSGustavo Padovan unlock:
2279a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2280a9de9248SMarcel Holtmann }
2281a9de9248SMarcel Holtmann 
22826039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2283807deac2SGustavo Padovan 					     struct sk_buff *skb)
2284a9de9248SMarcel Holtmann {
2285a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2286a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2287a9de9248SMarcel Holtmann 
22889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2289a9de9248SMarcel Holtmann 
2290a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2291a9de9248SMarcel Holtmann 
2292a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2293a9de9248SMarcel Holtmann 	if (conn) {
2294a9de9248SMarcel Holtmann 		if (!ev->status)
2295a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2296a9de9248SMarcel Holtmann 
229751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2298a9de9248SMarcel Holtmann 
2299a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2300a9de9248SMarcel Holtmann 	}
2301a9de9248SMarcel Holtmann 
2302a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2303a9de9248SMarcel Holtmann }
2304a9de9248SMarcel Holtmann 
23056039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2306807deac2SGustavo Padovan 				    struct sk_buff *skb)
2307a9de9248SMarcel Holtmann {
2308a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2309a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2310a9de9248SMarcel Holtmann 
23119f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2312a9de9248SMarcel Holtmann 
2313a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2314a9de9248SMarcel Holtmann 
2315a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2316ccd556feSJohan Hedberg 	if (!conn)
2317ccd556feSJohan Hedberg 		goto unlock;
2318ccd556feSJohan Hedberg 
2319769be974SMarcel Holtmann 	if (!ev->status)
2320a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2321a9de9248SMarcel Holtmann 
2322ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2323ccd556feSJohan Hedberg 		goto unlock;
2324ccd556feSJohan Hedberg 
2325ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2326769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2327769be974SMarcel Holtmann 		cp.handle = ev->handle;
2328769be974SMarcel Holtmann 		cp.page = 0x01;
2329ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2330769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2331392599b9SJohan Hedberg 		goto unlock;
2332392599b9SJohan Hedberg 	}
2333392599b9SJohan Hedberg 
2334671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2335127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2336127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2337127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2338127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2339127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2340b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2341b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
234208c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2343b644ba33SJohan Hedberg 				      conn->dev_class);
2344392599b9SJohan Hedberg 
2345127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2346769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2347769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2348769be974SMarcel Holtmann 		hci_conn_put(conn);
2349769be974SMarcel Holtmann 	}
2350769be974SMarcel Holtmann 
2351ccd556feSJohan Hedberg unlock:
2352a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2353a9de9248SMarcel Holtmann }
2354a9de9248SMarcel Holtmann 
23556039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
23566039aa73SGustavo Padovan {
23576039aa73SGustavo Padovan 	BT_DBG("%s", hdev->name);
23586039aa73SGustavo Padovan }
23596039aa73SGustavo Padovan 
23606039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2361807deac2SGustavo Padovan 				       struct sk_buff *skb)
2362a9de9248SMarcel Holtmann {
2363a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2364a9de9248SMarcel Holtmann }
2365a9de9248SMarcel Holtmann 
23666039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2367a9de9248SMarcel Holtmann {
2368a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2369a9de9248SMarcel Holtmann 	__u16 opcode;
2370a9de9248SMarcel Holtmann 
2371a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2372a9de9248SMarcel Holtmann 
2373a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2374a9de9248SMarcel Holtmann 
2375a9de9248SMarcel Holtmann 	switch (opcode) {
2376a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2377a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2378a9de9248SMarcel Holtmann 		break;
2379a9de9248SMarcel Holtmann 
23804d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
23814d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
23824d93483bSAndre Guedes 		break;
23834d93483bSAndre Guedes 
2384a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2385a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2386a9de9248SMarcel Holtmann 		break;
2387a9de9248SMarcel Holtmann 
2388a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2389a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2390a9de9248SMarcel Holtmann 		break;
2391a9de9248SMarcel Holtmann 
2392a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2393a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2394a9de9248SMarcel Holtmann 		break;
2395a9de9248SMarcel Holtmann 
2396e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2397e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2398e4e8e37cSMarcel Holtmann 		break;
2399e4e8e37cSMarcel Holtmann 
2400a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2401a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2402a9de9248SMarcel Holtmann 		break;
2403a9de9248SMarcel Holtmann 
2404e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2405e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2406e4e8e37cSMarcel Holtmann 		break;
2407e4e8e37cSMarcel Holtmann 
2408e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2409e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2410e4e8e37cSMarcel Holtmann 		break;
2411e4e8e37cSMarcel Holtmann 
2412a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2413a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2414a9de9248SMarcel Holtmann 		break;
2415a9de9248SMarcel Holtmann 
2416a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2417a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2418a9de9248SMarcel Holtmann 		break;
2419a9de9248SMarcel Holtmann 
2420a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2421a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2422a9de9248SMarcel Holtmann 		break;
2423a9de9248SMarcel Holtmann 
2424a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2425a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2426a9de9248SMarcel Holtmann 		break;
2427a9de9248SMarcel Holtmann 
2428a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2429a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2430a9de9248SMarcel Holtmann 		break;
2431a9de9248SMarcel Holtmann 
2432a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2433a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2434a9de9248SMarcel Holtmann 		break;
2435a9de9248SMarcel Holtmann 
2436a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2437a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2438a9de9248SMarcel Holtmann 		break;
2439a9de9248SMarcel Holtmann 
2440a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2441a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2442a9de9248SMarcel Holtmann 		break;
2443a9de9248SMarcel Holtmann 
2444a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2445a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2446a9de9248SMarcel Holtmann 		break;
2447a9de9248SMarcel Holtmann 
2448a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2449a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2450a9de9248SMarcel Holtmann 		break;
2451a9de9248SMarcel Holtmann 
2452a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2453a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2454a9de9248SMarcel Holtmann 		break;
2455a9de9248SMarcel Holtmann 
2456333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2457333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2458333140b5SMarcel Holtmann 		break;
2459333140b5SMarcel Holtmann 
2460a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2461a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2462a9de9248SMarcel Holtmann 		break;
2463a9de9248SMarcel Holtmann 
2464a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2465a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2466a9de9248SMarcel Holtmann 		break;
2467a9de9248SMarcel Holtmann 
2468a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2469a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2470a9de9248SMarcel Holtmann 		break;
2471a9de9248SMarcel Holtmann 
2472971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2473971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2474971e3a4bSAndre Guedes 		break;
2475971e3a4bSAndre Guedes 
2476a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2477a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2478a9de9248SMarcel Holtmann 		break;
2479a9de9248SMarcel Holtmann 
2480a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2481a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2482a9de9248SMarcel Holtmann 		break;
2483a9de9248SMarcel Holtmann 
2484350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2485350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2486350ee4cfSAndrei Emeltchenko 		break;
2487350ee4cfSAndrei Emeltchenko 
248823bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
248923bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
249023bb5763SJohan Hedberg 		break;
249123bb5763SJohan Hedberg 
24921e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
24931e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
24941e89cffbSAndrei Emeltchenko 		break;
24951e89cffbSAndrei Emeltchenko 
2496928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2497928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2498928abaa7SAndrei Emeltchenko 		break;
2499928abaa7SAndrei Emeltchenko 
2500903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2501903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2502903e4541SAndrei Emeltchenko 		break;
2503903e4541SAndrei Emeltchenko 
2504b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2505b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2506b0916ea0SJohan Hedberg 		break;
2507b0916ea0SJohan Hedberg 
2508d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2509d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2510d5859e22SJohan Hedberg 		break;
2511d5859e22SJohan Hedberg 
2512d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2513d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2514d5859e22SJohan Hedberg 		break;
2515d5859e22SJohan Hedberg 
2516d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2517d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2518d5859e22SJohan Hedberg 		break;
2519d5859e22SJohan Hedberg 
2520d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2521d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2522d5859e22SJohan Hedberg 		break;
2523d5859e22SJohan Hedberg 
2524980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2525980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2526980e1a53SJohan Hedberg 		break;
2527980e1a53SJohan Hedberg 
2528980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2529980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2530980e1a53SJohan Hedberg 		break;
2531980e1a53SJohan Hedberg 
2532c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2533c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2534c35938b2SSzymon Janc 		break;
2535c35938b2SSzymon Janc 
25366ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
25376ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
25386ed58ec5SVille Tervo 		break;
25396ed58ec5SVille Tervo 
25408fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
25418fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
25428fa19098SJohan Hedberg 		break;
25438fa19098SJohan Hedberg 
2544e36b04c8SJohan Hedberg 	case HCI_OP_LE_SET_EVENT_MASK:
2545e36b04c8SJohan Hedberg 		hci_cc_le_set_event_mask(hdev, skb);
2546e36b04c8SJohan Hedberg 		break;
2547e36b04c8SJohan Hedberg 
2548a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2549a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2550a5c29683SJohan Hedberg 		break;
2551a5c29683SJohan Hedberg 
2552a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2553a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2554a5c29683SJohan Hedberg 		break;
2555a5c29683SJohan Hedberg 
25561143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
25571143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
25581143d458SBrian Gix 		break;
25591143d458SBrian Gix 
25601143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
25611143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
256216cde993SSzymon Janc 		break;
256307f7fa5dSAndre Guedes 
256407f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
256507f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
25661143d458SBrian Gix 		break;
25671143d458SBrian Gix 
2568eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2569eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2570eb9d91f5SAndre Guedes 		break;
2571eb9d91f5SAndre Guedes 
2572a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2573a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2574a7a595f6SVinicius Costa Gomes 		break;
2575a7a595f6SVinicius Costa Gomes 
2576a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2577a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2578a7a595f6SVinicius Costa Gomes 		break;
2579a7a595f6SVinicius Costa Gomes 
2580f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2581f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2582f9b49306SAndre Guedes 		break;
2583f9b49306SAndre Guedes 
258493c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
258593c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
258693c284eeSAndrei Emeltchenko 		break;
258793c284eeSAndrei Emeltchenko 
2588a9de9248SMarcel Holtmann 	default:
25899f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2590a9de9248SMarcel Holtmann 		break;
2591a9de9248SMarcel Holtmann 	}
2592a9de9248SMarcel Holtmann 
25936bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
25946bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
25956bd32326SVille Tervo 
2596a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2597a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2598a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2599c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2600a9de9248SMarcel Holtmann 	}
2601a9de9248SMarcel Holtmann }
2602a9de9248SMarcel Holtmann 
26036039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2604a9de9248SMarcel Holtmann {
2605a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2606a9de9248SMarcel Holtmann 	__u16 opcode;
2607a9de9248SMarcel Holtmann 
2608a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2609a9de9248SMarcel Holtmann 
2610a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2611a9de9248SMarcel Holtmann 
2612a9de9248SMarcel Holtmann 	switch (opcode) {
2613a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2614a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2615a9de9248SMarcel Holtmann 		break;
2616a9de9248SMarcel Holtmann 
2617a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2618a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2619a9de9248SMarcel Holtmann 		break;
2620a9de9248SMarcel Holtmann 
2621a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2622a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2623a9de9248SMarcel Holtmann 		break;
2624a9de9248SMarcel Holtmann 
2625f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2626f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2627f8558555SMarcel Holtmann 		break;
2628f8558555SMarcel Holtmann 
2629f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2630f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2631f8558555SMarcel Holtmann 		break;
2632f8558555SMarcel Holtmann 
2633a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2634a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2635a9de9248SMarcel Holtmann 		break;
2636a9de9248SMarcel Holtmann 
2637769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2638769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2639769be974SMarcel Holtmann 		break;
2640769be974SMarcel Holtmann 
2641769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2642769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2643769be974SMarcel Holtmann 		break;
2644769be974SMarcel Holtmann 
2645a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2646a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2647a9de9248SMarcel Holtmann 		break;
2648a9de9248SMarcel Holtmann 
2649a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2650a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2651a9de9248SMarcel Holtmann 		break;
2652a9de9248SMarcel Holtmann 
2653a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2654a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2655a9de9248SMarcel Holtmann 		break;
2656a9de9248SMarcel Holtmann 
26578962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
265888c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
26598962ee74SJohan Hedberg 		break;
26608962ee74SJohan Hedberg 
2661fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2662fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2663fcd89c09SVille Tervo 		break;
2664fcd89c09SVille Tervo 
2665a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2666a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2667a7a595f6SVinicius Costa Gomes 		break;
2668a7a595f6SVinicius Costa Gomes 
2669a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2670a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2671a02226d6SAndrei Emeltchenko 		break;
2672a02226d6SAndrei Emeltchenko 
26730b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
26740b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
26750b26ab9dSAndrei Emeltchenko 		break;
26760b26ab9dSAndrei Emeltchenko 
26775ce66b59SAndrei Emeltchenko 	case HCI_OP_CREATE_LOGICAL_LINK:
26785ce66b59SAndrei Emeltchenko 		hci_cs_create_logical_link(hdev, ev->status);
26795ce66b59SAndrei Emeltchenko 		break;
26805ce66b59SAndrei Emeltchenko 
2681a9de9248SMarcel Holtmann 	default:
26829f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2683a9de9248SMarcel Holtmann 		break;
2684a9de9248SMarcel Holtmann 	}
2685a9de9248SMarcel Holtmann 
26866bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
26876bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
26886bd32326SVille Tervo 
268910572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2690a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2691a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2692c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2693a9de9248SMarcel Holtmann 	}
2694a9de9248SMarcel Holtmann }
2695a9de9248SMarcel Holtmann 
26966039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2697a9de9248SMarcel Holtmann {
2698a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2699a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2700a9de9248SMarcel Holtmann 
27019f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2702a9de9248SMarcel Holtmann 
2703a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2704a9de9248SMarcel Holtmann 
2705a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2706a9de9248SMarcel Holtmann 	if (conn) {
2707a9de9248SMarcel Holtmann 		if (!ev->status) {
2708a9de9248SMarcel Holtmann 			if (ev->role)
2709a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2710a9de9248SMarcel Holtmann 			else
2711a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2712a9de9248SMarcel Holtmann 		}
2713a9de9248SMarcel Holtmann 
271451a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2715a9de9248SMarcel Holtmann 
2716a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2717a9de9248SMarcel Holtmann 	}
2718a9de9248SMarcel Holtmann 
2719a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2720a9de9248SMarcel Holtmann }
2721a9de9248SMarcel Holtmann 
27226039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
27231da177e4SLinus Torvalds {
2724a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
27251da177e4SLinus Torvalds 	int i;
27261da177e4SLinus Torvalds 
272732ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
272832ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
272932ac5b9bSAndrei Emeltchenko 		return;
273032ac5b9bSAndrei Emeltchenko 	}
273132ac5b9bSAndrei Emeltchenko 
2732c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2733c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
27341da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
27351da177e4SLinus Torvalds 		return;
27361da177e4SLinus Torvalds 	}
27371da177e4SLinus Torvalds 
2738c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2739c5993de8SAndrei Emeltchenko 
2740613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2741613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
27421da177e4SLinus Torvalds 		struct hci_conn *conn;
27431da177e4SLinus Torvalds 		__u16  handle, count;
27441da177e4SLinus Torvalds 
2745613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2746613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
27471da177e4SLinus Torvalds 
27481da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2749f4280918SAndrei Emeltchenko 		if (!conn)
2750f4280918SAndrei Emeltchenko 			continue;
2751f4280918SAndrei Emeltchenko 
27521da177e4SLinus Torvalds 		conn->sent -= count;
27531da177e4SLinus Torvalds 
2754f4280918SAndrei Emeltchenko 		switch (conn->type) {
2755f4280918SAndrei Emeltchenko 		case ACL_LINK:
275670f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
275770f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
27581da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2759f4280918SAndrei Emeltchenko 			break;
2760f4280918SAndrei Emeltchenko 
2761f4280918SAndrei Emeltchenko 		case LE_LINK:
27626ed58ec5SVille Tervo 			if (hdev->le_pkts) {
27636ed58ec5SVille Tervo 				hdev->le_cnt += count;
27646ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
27656ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
27666ed58ec5SVille Tervo 			} else {
27676ed58ec5SVille Tervo 				hdev->acl_cnt += count;
27686ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
27696ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
27706ed58ec5SVille Tervo 			}
2771f4280918SAndrei Emeltchenko 			break;
2772f4280918SAndrei Emeltchenko 
2773f4280918SAndrei Emeltchenko 		case SCO_LINK:
277470f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
277570f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
27765b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2777f4280918SAndrei Emeltchenko 			break;
2778f4280918SAndrei Emeltchenko 
2779f4280918SAndrei Emeltchenko 		default:
2780f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2781f4280918SAndrei Emeltchenko 			break;
27821da177e4SLinus Torvalds 		}
27831da177e4SLinus Torvalds 	}
2784a9de9248SMarcel Holtmann 
27853eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
27861da177e4SLinus Torvalds }
27871da177e4SLinus Torvalds 
278876ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
278976ef7cf7SAndrei Emeltchenko 						 __u16 handle)
279076ef7cf7SAndrei Emeltchenko {
279176ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
279276ef7cf7SAndrei Emeltchenko 
279376ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
279476ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
279576ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
279676ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
279776ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
279876ef7cf7SAndrei Emeltchenko 		if (chan)
279976ef7cf7SAndrei Emeltchenko 			return chan->conn;
280076ef7cf7SAndrei Emeltchenko 		break;
280176ef7cf7SAndrei Emeltchenko 	default:
280276ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
280376ef7cf7SAndrei Emeltchenko 		break;
280476ef7cf7SAndrei Emeltchenko 	}
280576ef7cf7SAndrei Emeltchenko 
280676ef7cf7SAndrei Emeltchenko 	return NULL;
280776ef7cf7SAndrei Emeltchenko }
280876ef7cf7SAndrei Emeltchenko 
28096039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
281025e89e99SAndrei Emeltchenko {
281125e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
281225e89e99SAndrei Emeltchenko 	int i;
281325e89e99SAndrei Emeltchenko 
281425e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
281525e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
281625e89e99SAndrei Emeltchenko 		return;
281725e89e99SAndrei Emeltchenko 	}
281825e89e99SAndrei Emeltchenko 
281925e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
282025e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
282125e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
282225e89e99SAndrei Emeltchenko 		return;
282325e89e99SAndrei Emeltchenko 	}
282425e89e99SAndrei Emeltchenko 
282525e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
282625e89e99SAndrei Emeltchenko 	       ev->num_hndl);
282725e89e99SAndrei Emeltchenko 
282825e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
282925e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
283076ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
283125e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
283225e89e99SAndrei Emeltchenko 
283325e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
283425e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
283525e89e99SAndrei Emeltchenko 
283676ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
283725e89e99SAndrei Emeltchenko 		if (!conn)
283825e89e99SAndrei Emeltchenko 			continue;
283925e89e99SAndrei Emeltchenko 
284025e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
284125e89e99SAndrei Emeltchenko 
284225e89e99SAndrei Emeltchenko 		switch (conn->type) {
284325e89e99SAndrei Emeltchenko 		case ACL_LINK:
2844bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
284525e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
284625e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
284725e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
284825e89e99SAndrei Emeltchenko 			break;
284925e89e99SAndrei Emeltchenko 
285025e89e99SAndrei Emeltchenko 		default:
285125e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
285225e89e99SAndrei Emeltchenko 			break;
285325e89e99SAndrei Emeltchenko 		}
285425e89e99SAndrei Emeltchenko 	}
285525e89e99SAndrei Emeltchenko 
285625e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
285725e89e99SAndrei Emeltchenko }
285825e89e99SAndrei Emeltchenko 
28596039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
28601da177e4SLinus Torvalds {
2861a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
286204837f64SMarcel Holtmann 	struct hci_conn *conn;
28631da177e4SLinus Torvalds 
28649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
28651da177e4SLinus Torvalds 
28661da177e4SLinus Torvalds 	hci_dev_lock(hdev);
28671da177e4SLinus Torvalds 
286804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
286904837f64SMarcel Holtmann 	if (conn) {
287004837f64SMarcel Holtmann 		conn->mode = ev->mode;
287104837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
287204837f64SMarcel Holtmann 
28738fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
28748fc9ced3SGustavo Padovan 					&conn->flags)) {
287504837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
287658a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
287704837f64SMarcel Holtmann 			else
287858a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
287904837f64SMarcel Holtmann 		}
2880e73439d8SMarcel Holtmann 
288151a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2882e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
288304837f64SMarcel Holtmann 	}
288404837f64SMarcel Holtmann 
288504837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
288604837f64SMarcel Holtmann }
288704837f64SMarcel Holtmann 
28886039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
28891da177e4SLinus Torvalds {
2890052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2891052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2892052b30b0SMarcel Holtmann 
2893a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2894052b30b0SMarcel Holtmann 
2895052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2896052b30b0SMarcel Holtmann 
2897052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2898b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2899b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2900b6f98044SWaldemar Rymarkiewicz 
2901b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2902052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2903052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2904052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2905052b30b0SMarcel Holtmann 	}
2906052b30b0SMarcel Holtmann 
2907a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
290803b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
290903b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2910a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2911a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2912a770bb5aSWaldemar Rymarkiewicz 
2913a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2914a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2915a770bb5aSWaldemar Rymarkiewicz 		else
2916a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2917a770bb5aSWaldemar Rymarkiewicz 
2918744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2919a770bb5aSWaldemar Rymarkiewicz 	}
2920980e1a53SJohan Hedberg 
2921b6f98044SWaldemar Rymarkiewicz unlock:
2922052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
29231da177e4SLinus Torvalds }
29241da177e4SLinus Torvalds 
29256039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29261da177e4SLinus Torvalds {
292755ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
292855ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
292955ed8ca1SJohan Hedberg 	struct hci_conn *conn;
293055ed8ca1SJohan Hedberg 	struct link_key *key;
293155ed8ca1SJohan Hedberg 
2932a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
293355ed8ca1SJohan Hedberg 
2934a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
293555ed8ca1SJohan Hedberg 		return;
293655ed8ca1SJohan Hedberg 
293755ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
293855ed8ca1SJohan Hedberg 
293955ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
294055ed8ca1SJohan Hedberg 	if (!key) {
29416ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
29426ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
294355ed8ca1SJohan Hedberg 		goto not_found;
294455ed8ca1SJohan Hedberg 	}
294555ed8ca1SJohan Hedberg 
29466ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
29476ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
294855ed8ca1SJohan Hedberg 
2949a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2950b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
295155ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
295255ed8ca1SJohan Hedberg 		goto not_found;
295355ed8ca1SJohan Hedberg 	}
295455ed8ca1SJohan Hedberg 
295555ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
295660b83f57SWaldemar Rymarkiewicz 	if (conn) {
295760b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2958807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
295955ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
296055ed8ca1SJohan Hedberg 			goto not_found;
296155ed8ca1SJohan Hedberg 		}
296255ed8ca1SJohan Hedberg 
296360b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
296460b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
29658fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
29668fc9ced3SGustavo Padovan 			       hdev->name);
296760b83f57SWaldemar Rymarkiewicz 			goto not_found;
296860b83f57SWaldemar Rymarkiewicz 		}
296960b83f57SWaldemar Rymarkiewicz 
297060b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
297160b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
297260b83f57SWaldemar Rymarkiewicz 	}
297360b83f57SWaldemar Rymarkiewicz 
297455ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
29759b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
297655ed8ca1SJohan Hedberg 
297755ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
297855ed8ca1SJohan Hedberg 
297955ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
298055ed8ca1SJohan Hedberg 
298155ed8ca1SJohan Hedberg 	return;
298255ed8ca1SJohan Hedberg 
298355ed8ca1SJohan Hedberg not_found:
298455ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
298555ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
29861da177e4SLinus Torvalds }
29871da177e4SLinus Torvalds 
29886039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
29891da177e4SLinus Torvalds {
2990052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2991052b30b0SMarcel Holtmann 	struct hci_conn *conn;
299255ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2993052b30b0SMarcel Holtmann 
2994a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2995052b30b0SMarcel Holtmann 
2996052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2997052b30b0SMarcel Holtmann 
2998052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2999052b30b0SMarcel Holtmann 	if (conn) {
3000052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
3001052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
3002980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
300313d39315SWaldemar Rymarkiewicz 
300413d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
300513d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
300613d39315SWaldemar Rymarkiewicz 
3007052b30b0SMarcel Holtmann 		hci_conn_put(conn);
3008052b30b0SMarcel Holtmann 	}
3009052b30b0SMarcel Holtmann 
3010a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
3011d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
301255ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
301355ed8ca1SJohan Hedberg 
3014052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
30151da177e4SLinus Torvalds }
30161da177e4SLinus Torvalds 
30176039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
301804837f64SMarcel Holtmann {
3019a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
302004837f64SMarcel Holtmann 	struct hci_conn *conn;
302104837f64SMarcel Holtmann 
30229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
302304837f64SMarcel Holtmann 
302404837f64SMarcel Holtmann 	hci_dev_lock(hdev);
302504837f64SMarcel Holtmann 
302604837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30271da177e4SLinus Torvalds 	if (conn && !ev->status) {
30281da177e4SLinus Torvalds 		struct inquiry_entry *ie;
30291da177e4SLinus Torvalds 
3030cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3031cc11b9c1SAndrei Emeltchenko 		if (ie) {
30321da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
30331da177e4SLinus Torvalds 			ie->timestamp = jiffies;
30341da177e4SLinus Torvalds 		}
30351da177e4SLinus Torvalds 	}
30361da177e4SLinus Torvalds 
30371da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
30381da177e4SLinus Torvalds }
30391da177e4SLinus Torvalds 
30406039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3041a8746417SMarcel Holtmann {
3042a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3043a8746417SMarcel Holtmann 	struct hci_conn *conn;
3044a8746417SMarcel Holtmann 
30459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3046a8746417SMarcel Holtmann 
3047a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
3048a8746417SMarcel Holtmann 
3049a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3050a8746417SMarcel Holtmann 	if (conn && !ev->status)
3051a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3052a8746417SMarcel Holtmann 
3053a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
3054a8746417SMarcel Holtmann }
3055a8746417SMarcel Holtmann 
30566039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
305785a1e930SMarcel Holtmann {
3058a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
305985a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
306085a1e930SMarcel Holtmann 
306185a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
306285a1e930SMarcel Holtmann 
306385a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
306485a1e930SMarcel Holtmann 
3065cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3066cc11b9c1SAndrei Emeltchenko 	if (ie) {
306785a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
306885a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
306985a1e930SMarcel Holtmann 	}
307085a1e930SMarcel Holtmann 
307185a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
307285a1e930SMarcel Holtmann }
307385a1e930SMarcel Holtmann 
30746039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3075807deac2SGustavo Padovan 					     struct sk_buff *skb)
3076a9de9248SMarcel Holtmann {
3077a9de9248SMarcel Holtmann 	struct inquiry_data data;
3078a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
3079388fc8faSJohan Hedberg 	bool name_known, ssp;
3080a9de9248SMarcel Holtmann 
3081a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3082a9de9248SMarcel Holtmann 
3083a9de9248SMarcel Holtmann 	if (!num_rsp)
3084a9de9248SMarcel Holtmann 		return;
3085a9de9248SMarcel Holtmann 
30861519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30871519cc17SAndre Guedes 		return;
30881519cc17SAndre Guedes 
3089a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3090a9de9248SMarcel Holtmann 
3091a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3092138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3093138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3094a9de9248SMarcel Holtmann 
3095e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3096a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3097a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3098a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3099a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3100a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3101a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3102a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
310341a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
31043175405bSJohan Hedberg 
31053175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3106388fc8faSJohan Hedberg 							      false, &ssp);
310748264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3108e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3109388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3110a9de9248SMarcel Holtmann 		}
3111a9de9248SMarcel Holtmann 	} else {
3112a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3113a9de9248SMarcel Holtmann 
3114e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3115a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3116a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3117a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3118a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3119a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3120a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3121a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
312241a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
31233175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3124388fc8faSJohan Hedberg 							      false, &ssp);
312548264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3126e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3127388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3128a9de9248SMarcel Holtmann 		}
3129a9de9248SMarcel Holtmann 	}
3130a9de9248SMarcel Holtmann 
3131a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3132a9de9248SMarcel Holtmann }
3133a9de9248SMarcel Holtmann 
31346039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3135807deac2SGustavo Padovan 					struct sk_buff *skb)
3136a9de9248SMarcel Holtmann {
313741a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
313841a96212SMarcel Holtmann 	struct hci_conn *conn;
313941a96212SMarcel Holtmann 
3140a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
314141a96212SMarcel Holtmann 
314241a96212SMarcel Holtmann 	hci_dev_lock(hdev);
314341a96212SMarcel Holtmann 
314441a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3145ccd556feSJohan Hedberg 	if (!conn)
3146ccd556feSJohan Hedberg 		goto unlock;
3147ccd556feSJohan Hedberg 
3148769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
314941a96212SMarcel Holtmann 		struct inquiry_entry *ie;
315041a96212SMarcel Holtmann 
3151cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3152cc11b9c1SAndrei Emeltchenko 		if (ie)
315302b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
315441a96212SMarcel Holtmann 
315502b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
315658a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
315741a96212SMarcel Holtmann 	}
315841a96212SMarcel Holtmann 
3159ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3160ccd556feSJohan Hedberg 		goto unlock;
3161ccd556feSJohan Hedberg 
3162671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3163127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3164127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3165127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3166127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3167127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3168b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3169b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
317008c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
3171b644ba33SJohan Hedberg 				      conn->dev_class);
3172392599b9SJohan Hedberg 
3173127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3174769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3175769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
3176769be974SMarcel Holtmann 		hci_conn_put(conn);
3177769be974SMarcel Holtmann 	}
3178769be974SMarcel Holtmann 
3179ccd556feSJohan Hedberg unlock:
318041a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3181a9de9248SMarcel Holtmann }
3182a9de9248SMarcel Holtmann 
31836039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3184807deac2SGustavo Padovan 				       struct sk_buff *skb)
3185a9de9248SMarcel Holtmann {
3186b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3187b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3188b6a0dc82SMarcel Holtmann 
31899f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3190b6a0dc82SMarcel Holtmann 
3191b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3192b6a0dc82SMarcel Holtmann 
3193b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
31949dc0a3afSMarcel Holtmann 	if (!conn) {
31959dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
31969dc0a3afSMarcel Holtmann 			goto unlock;
31979dc0a3afSMarcel Holtmann 
31989dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3199b6a0dc82SMarcel Holtmann 		if (!conn)
3200b6a0dc82SMarcel Holtmann 			goto unlock;
3201b6a0dc82SMarcel Holtmann 
32029dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
32039dc0a3afSMarcel Holtmann 	}
32049dc0a3afSMarcel Holtmann 
3205732547f9SMarcel Holtmann 	switch (ev->status) {
3206732547f9SMarcel Holtmann 	case 0x00:
3207732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3208732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3209732547f9SMarcel Holtmann 
32109eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
3211732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3212732547f9SMarcel Holtmann 		break;
3213732547f9SMarcel Holtmann 
3214705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3215732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
32161038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3217732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
3218732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
3219efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3220efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
3221efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
3222efc7688bSMarcel Holtmann 			goto unlock;
3223efc7688bSMarcel Holtmann 		}
3224732547f9SMarcel Holtmann 		/* fall through */
3225efc7688bSMarcel Holtmann 
3226732547f9SMarcel Holtmann 	default:
3227b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3228732547f9SMarcel Holtmann 		break;
3229732547f9SMarcel Holtmann 	}
3230b6a0dc82SMarcel Holtmann 
3231b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3232b6a0dc82SMarcel Holtmann 	if (ev->status)
3233b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3234b6a0dc82SMarcel Holtmann 
3235b6a0dc82SMarcel Holtmann unlock:
3236b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3237a9de9248SMarcel Holtmann }
3238a9de9248SMarcel Holtmann 
32396039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
3240a9de9248SMarcel Holtmann {
3241a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3242a9de9248SMarcel Holtmann }
3243a9de9248SMarcel Holtmann 
32446039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
324504837f64SMarcel Holtmann {
3246a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
324704837f64SMarcel Holtmann 
32489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
324904837f64SMarcel Holtmann }
325004837f64SMarcel Holtmann 
32516039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3252807deac2SGustavo Padovan 					    struct sk_buff *skb)
3253a9de9248SMarcel Holtmann {
3254a9de9248SMarcel Holtmann 	struct inquiry_data data;
3255a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3256a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
32579d939d94SVishal Agarwal 	size_t eir_len;
3258a9de9248SMarcel Holtmann 
3259a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3260a9de9248SMarcel Holtmann 
3261a9de9248SMarcel Holtmann 	if (!num_rsp)
3262a9de9248SMarcel Holtmann 		return;
3263a9de9248SMarcel Holtmann 
32641519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
32651519cc17SAndre Guedes 		return;
32661519cc17SAndre Guedes 
3267a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3268a9de9248SMarcel Holtmann 
3269e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3270388fc8faSJohan Hedberg 		bool name_known, ssp;
3271561aafbcSJohan Hedberg 
3272a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3273a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3274a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3275a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3276a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3277a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3278a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
327941a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3280561aafbcSJohan Hedberg 
3281a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
32824ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
32834ddb1930SJohan Hedberg 						       sizeof(info->data),
32844ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3285561aafbcSJohan Hedberg 		else
3286561aafbcSJohan Hedberg 			name_known = true;
3287561aafbcSJohan Hedberg 
3288388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3289388fc8faSJohan Hedberg 						      &ssp);
32909d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
329148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
329204124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
32939d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3294a9de9248SMarcel Holtmann 	}
3295a9de9248SMarcel Holtmann 
3296a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3297a9de9248SMarcel Holtmann }
3298a9de9248SMarcel Holtmann 
32991c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
33001c2e0041SJohan Hedberg 					 struct sk_buff *skb)
33011c2e0041SJohan Hedberg {
33021c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
33031c2e0041SJohan Hedberg 	struct hci_conn *conn;
33041c2e0041SJohan Hedberg 
33059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
33061c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
33071c2e0041SJohan Hedberg 
33081c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
33091c2e0041SJohan Hedberg 
33101c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
33111c2e0041SJohan Hedberg 	if (!conn)
33121c2e0041SJohan Hedberg 		goto unlock;
33131c2e0041SJohan Hedberg 
33141c2e0041SJohan Hedberg 	if (!ev->status)
33151c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
33161c2e0041SJohan Hedberg 
33171c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
33181c2e0041SJohan Hedberg 
33191c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
33201c2e0041SJohan Hedberg 		hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
33211c2e0041SJohan Hedberg 		hci_conn_put(conn);
33221c2e0041SJohan Hedberg 		goto unlock;
33231c2e0041SJohan Hedberg 	}
33241c2e0041SJohan Hedberg 
33251c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
33261c2e0041SJohan Hedberg 		if (!ev->status)
33271c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
33281c2e0041SJohan Hedberg 
33291c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
33301c2e0041SJohan Hedberg 		hci_conn_put(conn);
33311c2e0041SJohan Hedberg 	} else {
33321c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
33331c2e0041SJohan Hedberg 
33341c2e0041SJohan Hedberg 		hci_conn_hold(conn);
33351c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
33361c2e0041SJohan Hedberg 		hci_conn_put(conn);
33371c2e0041SJohan Hedberg 	}
33381c2e0041SJohan Hedberg 
33391c2e0041SJohan Hedberg unlock:
33401c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
33411c2e0041SJohan Hedberg }
33421c2e0041SJohan Hedberg 
33436039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
334417fa4b9dSJohan Hedberg {
334517fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
334617fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
334717fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
334817fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
334917fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
335017fa4b9dSJohan Hedberg 			return 0x02;
335117fa4b9dSJohan Hedberg 		else
335217fa4b9dSJohan Hedberg 			return 0x03;
335317fa4b9dSJohan Hedberg 	}
335417fa4b9dSJohan Hedberg 
335517fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
335617fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
335758797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
335817fa4b9dSJohan Hedberg 
335917fa4b9dSJohan Hedberg 	return conn->auth_type;
336017fa4b9dSJohan Hedberg }
336117fa4b9dSJohan Hedberg 
33626039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
33630493684eSMarcel Holtmann {
33640493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
33650493684eSMarcel Holtmann 	struct hci_conn *conn;
33660493684eSMarcel Holtmann 
33670493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
33680493684eSMarcel Holtmann 
33690493684eSMarcel Holtmann 	hci_dev_lock(hdev);
33700493684eSMarcel Holtmann 
33710493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
337203b555e1SJohan Hedberg 	if (!conn)
337303b555e1SJohan Hedberg 		goto unlock;
337403b555e1SJohan Hedberg 
33750493684eSMarcel Holtmann 	hci_conn_hold(conn);
33760493684eSMarcel Holtmann 
3377a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
337803b555e1SJohan Hedberg 		goto unlock;
337903b555e1SJohan Hedberg 
3380a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
338103b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
338217fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
338317fa4b9dSJohan Hedberg 
338417fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
33857a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
33867a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
33877a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
33887a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
33897cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
33907cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
339117fa4b9dSJohan Hedberg 
33928fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
33938fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3394ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3395ce85ee13SSzymon Janc 		else
3396ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3397ce85ee13SSzymon Janc 
339817fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
339917fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
340003b555e1SJohan Hedberg 	} else {
340103b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
340203b555e1SJohan Hedberg 
340303b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
34049f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
340503b555e1SJohan Hedberg 
340603b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
340703b555e1SJohan Hedberg 			     sizeof(cp), &cp);
340803b555e1SJohan Hedberg 	}
340903b555e1SJohan Hedberg 
341003b555e1SJohan Hedberg unlock:
341103b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
341203b555e1SJohan Hedberg }
341303b555e1SJohan Hedberg 
34146039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
341503b555e1SJohan Hedberg {
341603b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
341703b555e1SJohan Hedberg 	struct hci_conn *conn;
341803b555e1SJohan Hedberg 
341903b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
342003b555e1SJohan Hedberg 
342103b555e1SJohan Hedberg 	hci_dev_lock(hdev);
342203b555e1SJohan Hedberg 
342303b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
342403b555e1SJohan Hedberg 	if (!conn)
342503b555e1SJohan Hedberg 		goto unlock;
342603b555e1SJohan Hedberg 
342703b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
342803b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
342958a681efSJohan Hedberg 	if (ev->oob_data)
343058a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
343103b555e1SJohan Hedberg 
343203b555e1SJohan Hedberg unlock:
34330493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
34340493684eSMarcel Holtmann }
34350493684eSMarcel Holtmann 
34366039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3437a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3438a5c29683SJohan Hedberg {
3439a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
344055bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
34417a828908SJohan Hedberg 	struct hci_conn *conn;
3442a5c29683SJohan Hedberg 
3443a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3444a5c29683SJohan Hedberg 
3445a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3446a5c29683SJohan Hedberg 
3447a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
34487a828908SJohan Hedberg 		goto unlock;
34497a828908SJohan Hedberg 
34507a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
34517a828908SJohan Hedberg 	if (!conn)
34527a828908SJohan Hedberg 		goto unlock;
34537a828908SJohan Hedberg 
34547a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
34557a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
34567a828908SJohan Hedberg 
34577a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
34587a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
34597a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
34607a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
34617a828908SJohan Hedberg 	 * bit set. */
34627a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
34637a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
34647a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
34657a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
34667a828908SJohan Hedberg 		goto unlock;
34677a828908SJohan Hedberg 	}
34687a828908SJohan Hedberg 
34697a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
34707a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
34717a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
347255bc1a37SJohan Hedberg 
347355bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
347455bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
347555bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
347651a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
347755bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
347855bc1a37SJohan Hedberg 			confirm_hint = 1;
347955bc1a37SJohan Hedberg 			goto confirm;
348055bc1a37SJohan Hedberg 		}
348155bc1a37SJohan Hedberg 
34829f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
34839f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
34849f61656aSJohan Hedberg 
34859f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
34869f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
34879f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
34889f61656aSJohan Hedberg 			goto unlock;
34899f61656aSJohan Hedberg 		}
34909f61656aSJohan Hedberg 
34917a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
34927a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
34937a828908SJohan Hedberg 		goto unlock;
34947a828908SJohan Hedberg 	}
34957a828908SJohan Hedberg 
349655bc1a37SJohan Hedberg confirm:
3497272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
349855bc1a37SJohan Hedberg 				  confirm_hint);
3499a5c29683SJohan Hedberg 
35007a828908SJohan Hedberg unlock:
3501a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3502a5c29683SJohan Hedberg }
3503a5c29683SJohan Hedberg 
35046039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
35051143d458SBrian Gix 					 struct sk_buff *skb)
35061143d458SBrian Gix {
35071143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
35081143d458SBrian Gix 
35091143d458SBrian Gix 	BT_DBG("%s", hdev->name);
35101143d458SBrian Gix 
3511a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3512272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
35131143d458SBrian Gix }
35141143d458SBrian Gix 
351592a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
351692a25256SJohan Hedberg 					struct sk_buff *skb)
351792a25256SJohan Hedberg {
351892a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
351992a25256SJohan Hedberg 	struct hci_conn *conn;
352092a25256SJohan Hedberg 
352192a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
352292a25256SJohan Hedberg 
352392a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
352492a25256SJohan Hedberg 	if (!conn)
352592a25256SJohan Hedberg 		return;
352692a25256SJohan Hedberg 
352792a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
352892a25256SJohan Hedberg 	conn->passkey_entered = 0;
352992a25256SJohan Hedberg 
353092a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
353192a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
353292a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
353392a25256SJohan Hedberg 					 conn->passkey_entered);
353492a25256SJohan Hedberg }
353592a25256SJohan Hedberg 
353692a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
353792a25256SJohan Hedberg {
353892a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
353992a25256SJohan Hedberg 	struct hci_conn *conn;
354092a25256SJohan Hedberg 
354192a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
354292a25256SJohan Hedberg 
354392a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
354492a25256SJohan Hedberg 	if (!conn)
354592a25256SJohan Hedberg 		return;
354692a25256SJohan Hedberg 
354792a25256SJohan Hedberg 	switch (ev->type) {
354892a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
354992a25256SJohan Hedberg 		conn->passkey_entered = 0;
355092a25256SJohan Hedberg 		return;
355192a25256SJohan Hedberg 
355292a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
355392a25256SJohan Hedberg 		conn->passkey_entered++;
355492a25256SJohan Hedberg 		break;
355592a25256SJohan Hedberg 
355692a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
355792a25256SJohan Hedberg 		conn->passkey_entered--;
355892a25256SJohan Hedberg 		break;
355992a25256SJohan Hedberg 
356092a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
356192a25256SJohan Hedberg 		conn->passkey_entered = 0;
356292a25256SJohan Hedberg 		break;
356392a25256SJohan Hedberg 
356492a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
356592a25256SJohan Hedberg 		return;
356692a25256SJohan Hedberg 	}
356792a25256SJohan Hedberg 
356892a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
356992a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
357092a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
357192a25256SJohan Hedberg 					 conn->passkey_entered);
357292a25256SJohan Hedberg }
357392a25256SJohan Hedberg 
35746039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3575807deac2SGustavo Padovan 					 struct sk_buff *skb)
35760493684eSMarcel Holtmann {
35770493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
35780493684eSMarcel Holtmann 	struct hci_conn *conn;
35790493684eSMarcel Holtmann 
35800493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
35810493684eSMarcel Holtmann 
35820493684eSMarcel Holtmann 	hci_dev_lock(hdev);
35830493684eSMarcel Holtmann 
35840493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
35852a611692SJohan Hedberg 	if (!conn)
35862a611692SJohan Hedberg 		goto unlock;
35872a611692SJohan Hedberg 
35882a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
35892a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
35902a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
35912a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
35922a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3593fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3594bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3595bab73cb6SJohan Hedberg 				 ev->status);
35962a611692SJohan Hedberg 
35970493684eSMarcel Holtmann 	hci_conn_put(conn);
35980493684eSMarcel Holtmann 
35992a611692SJohan Hedberg unlock:
36000493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
36010493684eSMarcel Holtmann }
36020493684eSMarcel Holtmann 
36036039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3604807deac2SGustavo Padovan 					 struct sk_buff *skb)
360541a96212SMarcel Holtmann {
360641a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
360741a96212SMarcel Holtmann 	struct inquiry_entry *ie;
360841a96212SMarcel Holtmann 
360941a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
361041a96212SMarcel Holtmann 
361141a96212SMarcel Holtmann 	hci_dev_lock(hdev);
361241a96212SMarcel Holtmann 
3613cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3614cc11b9c1SAndrei Emeltchenko 	if (ie)
361502b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
361641a96212SMarcel Holtmann 
361741a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
361841a96212SMarcel Holtmann }
361941a96212SMarcel Holtmann 
36206039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
36212763eda6SSzymon Janc 					    struct sk_buff *skb)
36222763eda6SSzymon Janc {
36232763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
36242763eda6SSzymon Janc 	struct oob_data *data;
36252763eda6SSzymon Janc 
36262763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
36272763eda6SSzymon Janc 
36282763eda6SSzymon Janc 	hci_dev_lock(hdev);
36292763eda6SSzymon Janc 
3630a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3631e1ba1f15SSzymon Janc 		goto unlock;
3632e1ba1f15SSzymon Janc 
36332763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
36342763eda6SSzymon Janc 	if (data) {
36352763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
36362763eda6SSzymon Janc 
36372763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
36382763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
36392763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
36402763eda6SSzymon Janc 
36412763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
36422763eda6SSzymon Janc 			     &cp);
36432763eda6SSzymon Janc 	} else {
36442763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
36452763eda6SSzymon Janc 
36462763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
36472763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
36482763eda6SSzymon Janc 			     &cp);
36492763eda6SSzymon Janc 	}
36502763eda6SSzymon Janc 
3651e1ba1f15SSzymon Janc unlock:
36522763eda6SSzymon Janc 	hci_dev_unlock(hdev);
36532763eda6SSzymon Janc }
36542763eda6SSzymon Janc 
3655d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev,
3656d5e91192SAndrei Emeltchenko 				      struct sk_buff *skb)
3657d5e91192SAndrei Emeltchenko {
3658d5e91192SAndrei Emeltchenko 	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
3659d5e91192SAndrei Emeltchenko 	struct hci_conn *hcon, *bredr_hcon;
3660d5e91192SAndrei Emeltchenko 
3661d5e91192SAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
3662d5e91192SAndrei Emeltchenko 	       ev->status);
3663d5e91192SAndrei Emeltchenko 
3664d5e91192SAndrei Emeltchenko 	hci_dev_lock(hdev);
3665d5e91192SAndrei Emeltchenko 
3666d5e91192SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3667d5e91192SAndrei Emeltchenko 	if (!hcon) {
3668d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3669d5e91192SAndrei Emeltchenko 		return;
3670d5e91192SAndrei Emeltchenko 	}
3671d5e91192SAndrei Emeltchenko 
3672d5e91192SAndrei Emeltchenko 	if (ev->status) {
3673d5e91192SAndrei Emeltchenko 		hci_conn_del(hcon);
3674d5e91192SAndrei Emeltchenko 		hci_dev_unlock(hdev);
3675d5e91192SAndrei Emeltchenko 		return;
3676d5e91192SAndrei Emeltchenko 	}
3677d5e91192SAndrei Emeltchenko 
3678d5e91192SAndrei Emeltchenko 	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
3679d5e91192SAndrei Emeltchenko 
3680d5e91192SAndrei Emeltchenko 	hcon->state = BT_CONNECTED;
3681d5e91192SAndrei Emeltchenko 	bacpy(&hcon->dst, &bredr_hcon->dst);
3682d5e91192SAndrei Emeltchenko 
3683d5e91192SAndrei Emeltchenko 	hci_conn_hold(hcon);
3684d5e91192SAndrei Emeltchenko 	hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3685d5e91192SAndrei Emeltchenko 	hci_conn_put(hcon);
3686d5e91192SAndrei Emeltchenko 
3687d5e91192SAndrei Emeltchenko 	hci_conn_hold_device(hcon);
3688d5e91192SAndrei Emeltchenko 	hci_conn_add_sysfs(hcon);
3689d5e91192SAndrei Emeltchenko 
3690d5e91192SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3691d5e91192SAndrei Emeltchenko 
3692d5e91192SAndrei Emeltchenko 	if (hcon->out) {
3693d5e91192SAndrei Emeltchenko 		struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev);
3694d5e91192SAndrei Emeltchenko 
3695d5e91192SAndrei Emeltchenko 		if (!bredr_hdev)
3696d5e91192SAndrei Emeltchenko 			return;
3697d5e91192SAndrei Emeltchenko 
3698d5e91192SAndrei Emeltchenko 		/* Placeholder - create chan req
3699d5e91192SAndrei Emeltchenko 		l2cap_chan_create_cfm(bredr_hcon, hcon->remote_id);
3700d5e91192SAndrei Emeltchenko 		*/
3701d5e91192SAndrei Emeltchenko 
3702d5e91192SAndrei Emeltchenko 		hci_dev_put(bredr_hdev);
3703d5e91192SAndrei Emeltchenko 	}
3704d5e91192SAndrei Emeltchenko }
3705d5e91192SAndrei Emeltchenko 
370627695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
370727695fb4SAndrei Emeltchenko {
370827695fb4SAndrei Emeltchenko 	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
370927695fb4SAndrei Emeltchenko 	struct hci_conn *hcon;
371027695fb4SAndrei Emeltchenko 	struct hci_chan *hchan;
371127695fb4SAndrei Emeltchenko 	struct amp_mgr *mgr;
371227695fb4SAndrei Emeltchenko 
371327695fb4SAndrei Emeltchenko 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
371427695fb4SAndrei Emeltchenko 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
371527695fb4SAndrei Emeltchenko 	       ev->status);
371627695fb4SAndrei Emeltchenko 
371727695fb4SAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
371827695fb4SAndrei Emeltchenko 	if (!hcon)
371927695fb4SAndrei Emeltchenko 		return;
372027695fb4SAndrei Emeltchenko 
372127695fb4SAndrei Emeltchenko 	/* Create AMP hchan */
372227695fb4SAndrei Emeltchenko 	hchan = hci_chan_create(hcon);
372327695fb4SAndrei Emeltchenko 	if (!hchan)
372427695fb4SAndrei Emeltchenko 		return;
372527695fb4SAndrei Emeltchenko 
372627695fb4SAndrei Emeltchenko 	hchan->handle = le16_to_cpu(ev->handle);
372727695fb4SAndrei Emeltchenko 
372827695fb4SAndrei Emeltchenko 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
372927695fb4SAndrei Emeltchenko 
373027695fb4SAndrei Emeltchenko 	mgr = hcon->amp_mgr;
373127695fb4SAndrei Emeltchenko 	if (mgr && mgr->bredr_chan) {
373227695fb4SAndrei Emeltchenko 		struct l2cap_chan *bredr_chan = mgr->bredr_chan;
373327695fb4SAndrei Emeltchenko 
373427695fb4SAndrei Emeltchenko 		l2cap_chan_lock(bredr_chan);
373527695fb4SAndrei Emeltchenko 
373627695fb4SAndrei Emeltchenko 		bredr_chan->conn->mtu = hdev->block_mtu;
373727695fb4SAndrei Emeltchenko 		l2cap_logical_cfm(bredr_chan, hchan, 0);
373827695fb4SAndrei Emeltchenko 		hci_conn_hold(hcon);
373927695fb4SAndrei Emeltchenko 
374027695fb4SAndrei Emeltchenko 		l2cap_chan_unlock(bredr_chan);
374127695fb4SAndrei Emeltchenko 	}
374227695fb4SAndrei Emeltchenko }
374327695fb4SAndrei Emeltchenko 
3744606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
3745606e2a10SAndrei Emeltchenko 					     struct sk_buff *skb)
3746606e2a10SAndrei Emeltchenko {
3747606e2a10SAndrei Emeltchenko 	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
3748606e2a10SAndrei Emeltchenko 	struct hci_chan *hchan;
3749606e2a10SAndrei Emeltchenko 
3750606e2a10SAndrei Emeltchenko 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
3751606e2a10SAndrei Emeltchenko 	       le16_to_cpu(ev->handle), ev->status);
3752606e2a10SAndrei Emeltchenko 
3753606e2a10SAndrei Emeltchenko 	if (ev->status)
3754606e2a10SAndrei Emeltchenko 		return;
3755606e2a10SAndrei Emeltchenko 
3756606e2a10SAndrei Emeltchenko 	hci_dev_lock(hdev);
3757606e2a10SAndrei Emeltchenko 
3758606e2a10SAndrei Emeltchenko 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
3759606e2a10SAndrei Emeltchenko 	if (!hchan)
3760606e2a10SAndrei Emeltchenko 		goto unlock;
3761606e2a10SAndrei Emeltchenko 
3762606e2a10SAndrei Emeltchenko 	amp_destroy_logical_link(hchan, ev->reason);
3763606e2a10SAndrei Emeltchenko 
3764606e2a10SAndrei Emeltchenko unlock:
3765606e2a10SAndrei Emeltchenko 	hci_dev_unlock(hdev);
3766606e2a10SAndrei Emeltchenko }
3767606e2a10SAndrei Emeltchenko 
37689eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
37699eef6b3aSAndrei Emeltchenko 					     struct sk_buff *skb)
37709eef6b3aSAndrei Emeltchenko {
37719eef6b3aSAndrei Emeltchenko 	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
37729eef6b3aSAndrei Emeltchenko 	struct hci_conn *hcon;
37739eef6b3aSAndrei Emeltchenko 
37749eef6b3aSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
37759eef6b3aSAndrei Emeltchenko 
37769eef6b3aSAndrei Emeltchenko 	if (ev->status)
37779eef6b3aSAndrei Emeltchenko 		return;
37789eef6b3aSAndrei Emeltchenko 
37799eef6b3aSAndrei Emeltchenko 	hci_dev_lock(hdev);
37809eef6b3aSAndrei Emeltchenko 
37819eef6b3aSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
37829eef6b3aSAndrei Emeltchenko 	if (hcon) {
37839eef6b3aSAndrei Emeltchenko 		hcon->state = BT_CLOSED;
37849eef6b3aSAndrei Emeltchenko 		hci_conn_del(hcon);
37859eef6b3aSAndrei Emeltchenko 	}
37869eef6b3aSAndrei Emeltchenko 
37879eef6b3aSAndrei Emeltchenko 	hci_dev_unlock(hdev);
37889eef6b3aSAndrei Emeltchenko }
37899eef6b3aSAndrei Emeltchenko 
37906039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3791fcd89c09SVille Tervo {
3792fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3793fcd89c09SVille Tervo 	struct hci_conn *conn;
3794fcd89c09SVille Tervo 
37959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3796fcd89c09SVille Tervo 
3797fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3798fcd89c09SVille Tervo 
37994f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3800b62f328bSVille Tervo 	if (!conn) {
3801b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3802b62f328bSVille Tervo 		if (!conn) {
3803b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3804230fd16aSAndre Guedes 			goto unlock;
3805b62f328bSVille Tervo 		}
380629b7988aSAndre Guedes 
380729b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3808b9b343d2SAndre Guedes 
3809b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3810b9b343d2SAndre Guedes 			conn->out = true;
3811b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3812b9b343d2SAndre Guedes 		}
3813b62f328bSVille Tervo 	}
3814fcd89c09SVille Tervo 
3815cd17decbSAndre Guedes 	if (ev->status) {
3816cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3817cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3818cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3819cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3820cd17decbSAndre Guedes 		hci_conn_del(conn);
3821cd17decbSAndre Guedes 		goto unlock;
3822cd17decbSAndre Guedes 	}
3823cd17decbSAndre Guedes 
3824b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3825b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
382695b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
382783bc71b4SVinicius Costa Gomes 
38287b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3829fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3830fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3831fcd89c09SVille Tervo 
3832fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3833fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3834fcd89c09SVille Tervo 
3835fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3836fcd89c09SVille Tervo 
3837fcd89c09SVille Tervo unlock:
3838fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3839fcd89c09SVille Tervo }
3840fcd89c09SVille Tervo 
38416039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
38429aa04c91SAndre Guedes {
3843e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3844e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
38453c9e9195SAndre Guedes 	s8 rssi;
38469aa04c91SAndre Guedes 
38479aa04c91SAndre Guedes 	hci_dev_lock(hdev);
38489aa04c91SAndre Guedes 
3849e95beb41SAndre Guedes 	while (num_reports--) {
3850e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3851e95beb41SAndre Guedes 
38523c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
38533c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
385404124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
38553c9e9195SAndre Guedes 
3856e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
38579aa04c91SAndre Guedes 	}
38589aa04c91SAndre Guedes 
38599aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
38609aa04c91SAndre Guedes }
38619aa04c91SAndre Guedes 
38626039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3863a7a595f6SVinicius Costa Gomes {
3864a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3865a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3866bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3867a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3868c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3869a7a595f6SVinicius Costa Gomes 
38709f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3871a7a595f6SVinicius Costa Gomes 
3872a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3873a7a595f6SVinicius Costa Gomes 
3874a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3875bea710feSVinicius Costa Gomes 	if (conn == NULL)
3876bea710feSVinicius Costa Gomes 		goto not_found;
3877a7a595f6SVinicius Costa Gomes 
3878bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3879bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3880bea710feSVinicius Costa Gomes 		goto not_found;
3881bea710feSVinicius Costa Gomes 
3882bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3883a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3884c9839a11SVinicius Costa Gomes 
3885c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3886c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3887a7a595f6SVinicius Costa Gomes 
3888a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3889a7a595f6SVinicius Costa Gomes 
3890c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3891c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3892c9839a11SVinicius Costa Gomes 		kfree(ltk);
3893c9839a11SVinicius Costa Gomes 	}
3894c9839a11SVinicius Costa Gomes 
3895a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3896bea710feSVinicius Costa Gomes 
3897bea710feSVinicius Costa Gomes 	return;
3898bea710feSVinicius Costa Gomes 
3899bea710feSVinicius Costa Gomes not_found:
3900bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3901bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3902bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3903a7a595f6SVinicius Costa Gomes }
3904a7a595f6SVinicius Costa Gomes 
39056039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3906fcd89c09SVille Tervo {
3907fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3908fcd89c09SVille Tervo 
3909fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3910fcd89c09SVille Tervo 
3911fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3912fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3913fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3914fcd89c09SVille Tervo 		break;
3915fcd89c09SVille Tervo 
39169aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
39179aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
39189aa04c91SAndre Guedes 		break;
39199aa04c91SAndre Guedes 
3920a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3921a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3922a7a595f6SVinicius Costa Gomes 		break;
3923a7a595f6SVinicius Costa Gomes 
3924fcd89c09SVille Tervo 	default:
3925fcd89c09SVille Tervo 		break;
3926fcd89c09SVille Tervo 	}
3927fcd89c09SVille Tervo }
3928fcd89c09SVille Tervo 
39299495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
39309495b2eeSAndrei Emeltchenko {
39319495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
39329495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
39339495b2eeSAndrei Emeltchenko 
39349495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
39359495b2eeSAndrei Emeltchenko 
39369495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
39379495b2eeSAndrei Emeltchenko 
39389495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
39399495b2eeSAndrei Emeltchenko 	if (!hcon)
39409495b2eeSAndrei Emeltchenko 		return;
39419495b2eeSAndrei Emeltchenko 
39429495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
39439495b2eeSAndrei Emeltchenko }
39449495b2eeSAndrei Emeltchenko 
39451da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
39461da177e4SLinus Torvalds {
3947a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3948a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
39491da177e4SLinus Torvalds 
39501da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
39511da177e4SLinus Torvalds 
3952a9de9248SMarcel Holtmann 	switch (event) {
39531da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
39541da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
39551da177e4SLinus Torvalds 		break;
39561da177e4SLinus Torvalds 
39571da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
39581da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
39591da177e4SLinus Torvalds 		break;
39601da177e4SLinus Torvalds 
3961a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3962a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
396321d9e30eSMarcel Holtmann 		break;
396421d9e30eSMarcel Holtmann 
39651da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
39661da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
39671da177e4SLinus Torvalds 		break;
39681da177e4SLinus Torvalds 
39691da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
39701da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
39711da177e4SLinus Torvalds 		break;
39721da177e4SLinus Torvalds 
39731da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
39741da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
39751da177e4SLinus Torvalds 		break;
39761da177e4SLinus Torvalds 
3977a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3978a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3979a9de9248SMarcel Holtmann 		break;
3980a9de9248SMarcel Holtmann 
39811da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
39821da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
39831da177e4SLinus Torvalds 		break;
39841da177e4SLinus Torvalds 
3985a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3986a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3987a9de9248SMarcel Holtmann 		break;
3988a9de9248SMarcel Holtmann 
3989a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3990a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3991a9de9248SMarcel Holtmann 		break;
3992a9de9248SMarcel Holtmann 
3993a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3994a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3995a9de9248SMarcel Holtmann 		break;
3996a9de9248SMarcel Holtmann 
3997a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3998a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3999a9de9248SMarcel Holtmann 		break;
4000a9de9248SMarcel Holtmann 
4001a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
4002a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
4003a9de9248SMarcel Holtmann 		break;
4004a9de9248SMarcel Holtmann 
4005a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
4006a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
4007a9de9248SMarcel Holtmann 		break;
4008a9de9248SMarcel Holtmann 
4009a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
4010a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
4011a9de9248SMarcel Holtmann 		break;
4012a9de9248SMarcel Holtmann 
4013a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
4014a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
4015a9de9248SMarcel Holtmann 		break;
4016a9de9248SMarcel Holtmann 
4017a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
4018a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
40191da177e4SLinus Torvalds 		break;
40201da177e4SLinus Torvalds 
40211da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
40221da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
40231da177e4SLinus Torvalds 		break;
40241da177e4SLinus Torvalds 
40251da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
40261da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
40271da177e4SLinus Torvalds 		break;
40281da177e4SLinus Torvalds 
40291da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
40301da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
40311da177e4SLinus Torvalds 		break;
40321da177e4SLinus Torvalds 
40331da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
40341da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
40351da177e4SLinus Torvalds 		break;
40361da177e4SLinus Torvalds 
4037a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
4038a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
4039a8746417SMarcel Holtmann 		break;
4040a8746417SMarcel Holtmann 
404185a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
404285a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
404385a1e930SMarcel Holtmann 		break;
404485a1e930SMarcel Holtmann 
4045a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
4046a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
4047a9de9248SMarcel Holtmann 		break;
4048a9de9248SMarcel Holtmann 
4049a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
4050a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
4051a9de9248SMarcel Holtmann 		break;
4052a9de9248SMarcel Holtmann 
4053a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
4054a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
4055a9de9248SMarcel Holtmann 		break;
4056a9de9248SMarcel Holtmann 
4057a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
4058a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
4059a9de9248SMarcel Holtmann 		break;
4060a9de9248SMarcel Holtmann 
406104837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
406204837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
406304837f64SMarcel Holtmann 		break;
406404837f64SMarcel Holtmann 
4065a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
4066a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
40671da177e4SLinus Torvalds 		break;
40681da177e4SLinus Torvalds 
40691c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
40701c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
40711c2e0041SJohan Hedberg 		break;
40721c2e0041SJohan Hedberg 
40730493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
40740493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
40750493684eSMarcel Holtmann 		break;
40760493684eSMarcel Holtmann 
407703b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
407803b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
407903b555e1SJohan Hedberg 		break;
408003b555e1SJohan Hedberg 
4081a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
4082a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
4083a5c29683SJohan Hedberg 		break;
4084a5c29683SJohan Hedberg 
40851143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
40861143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
40871143d458SBrian Gix 		break;
40881143d458SBrian Gix 
408992a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
409092a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
409192a25256SJohan Hedberg 		break;
409292a25256SJohan Hedberg 
409392a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
409492a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
409592a25256SJohan Hedberg 		break;
409692a25256SJohan Hedberg 
40970493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
40980493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
40990493684eSMarcel Holtmann 		break;
41000493684eSMarcel Holtmann 
410141a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
410241a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
410341a96212SMarcel Holtmann 		break;
410441a96212SMarcel Holtmann 
4105fcd89c09SVille Tervo 	case HCI_EV_LE_META:
4106fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
4107fcd89c09SVille Tervo 		break;
4108fcd89c09SVille Tervo 
41099495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
41109495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
41119495b2eeSAndrei Emeltchenko 		break;
41129495b2eeSAndrei Emeltchenko 
41132763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
41142763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
41152763eda6SSzymon Janc 		break;
41162763eda6SSzymon Janc 
4117d5e91192SAndrei Emeltchenko 	case HCI_EV_PHY_LINK_COMPLETE:
4118d5e91192SAndrei Emeltchenko 		hci_phy_link_complete_evt(hdev, skb);
4119d5e91192SAndrei Emeltchenko 		break;
4120d5e91192SAndrei Emeltchenko 
412127695fb4SAndrei Emeltchenko 	case HCI_EV_LOGICAL_LINK_COMPLETE:
412227695fb4SAndrei Emeltchenko 		hci_loglink_complete_evt(hdev, skb);
412327695fb4SAndrei Emeltchenko 		break;
412427695fb4SAndrei Emeltchenko 
4125606e2a10SAndrei Emeltchenko 	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
4126606e2a10SAndrei Emeltchenko 		hci_disconn_loglink_complete_evt(hdev, skb);
4127606e2a10SAndrei Emeltchenko 		break;
4128606e2a10SAndrei Emeltchenko 
41299eef6b3aSAndrei Emeltchenko 	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
41309eef6b3aSAndrei Emeltchenko 		hci_disconn_phylink_complete_evt(hdev, skb);
41319eef6b3aSAndrei Emeltchenko 		break;
41329eef6b3aSAndrei Emeltchenko 
413325e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
413425e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
413525e89e99SAndrei Emeltchenko 		break;
413625e89e99SAndrei Emeltchenko 
41371da177e4SLinus Torvalds 	default:
41389f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
41391da177e4SLinus Torvalds 		break;
41401da177e4SLinus Torvalds 	}
41411da177e4SLinus Torvalds 
41421da177e4SLinus Torvalds 	kfree_skb(skb);
41431da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
41441da177e4SLinus Torvalds }
4145