xref: /openbmc/linux/net/bluetooth/hci_event.c (revision 976eb20e)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds    BlueZ - Bluetooth protocol stack for Linux
32d0a0346SRon Shaffer    Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds    This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds    it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds    published by the Free Software Foundation;
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
121da177e4SLinus Torvalds    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131da177e4SLinus Torvalds    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
141da177e4SLinus Torvalds    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
151da177e4SLinus Torvalds    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
161da177e4SLinus Torvalds    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
171da177e4SLinus Torvalds    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
181da177e4SLinus Torvalds    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
211da177e4SLinus Torvalds    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
221da177e4SLinus Torvalds    SOFTWARE IS DISCLAIMED.
231da177e4SLinus Torvalds */
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */
261da177e4SLinus Torvalds 
278c520a59SGustavo Padovan #include <linux/export.h>
281da177e4SLinus Torvalds #include <asm/unaligned.h>
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
311da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
32f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h>
338e2a0d92SAndrei Emeltchenko #include <net/bluetooth/a2mp.h>
34903e4541SAndrei Emeltchenko #include <net/bluetooth/amp.h>
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds /* Handle HCI Event packets */
371da177e4SLinus Torvalds 
38a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
391da177e4SLinus Torvalds {
40a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
411da177e4SLinus Torvalds 
429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
431da177e4SLinus Torvalds 
44e6d465cbSAndre Guedes 	if (status) {
45e6d465cbSAndre Guedes 		hci_dev_lock(hdev);
46e6d465cbSAndre Guedes 		mgmt_stop_discovery_failed(hdev, status);
47e6d465cbSAndre Guedes 		hci_dev_unlock(hdev);
48a9de9248SMarcel Holtmann 		return;
49e6d465cbSAndre Guedes 	}
501da177e4SLinus Torvalds 
5189352e7dSAndre Guedes 	clear_bit(HCI_INQUIRY, &hdev->flags);
5289352e7dSAndre Guedes 
5356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
54ff9ef578SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
5556e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
56a9de9248SMarcel Holtmann 
5723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
58a9de9248SMarcel Holtmann 
59a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
601da177e4SLinus Torvalds }
616bd57416SMarcel Holtmann 
624d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
634d93483bSAndre Guedes {
644d93483bSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
654d93483bSAndre Guedes 
669f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
67ae854a70SAndre Guedes 
68ae854a70SAndre Guedes 	if (status)
69ae854a70SAndre Guedes 		return;
70ae854a70SAndre Guedes 
71ae854a70SAndre Guedes 	set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
724d93483bSAndre Guedes }
734d93483bSAndre Guedes 
74a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
751da177e4SLinus Torvalds {
76a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
77a9de9248SMarcel Holtmann 
789f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
79a9de9248SMarcel Holtmann 
80a9de9248SMarcel Holtmann 	if (status)
81a9de9248SMarcel Holtmann 		return;
82a9de9248SMarcel Holtmann 
83ae854a70SAndre Guedes 	clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
84ae854a70SAndre Guedes 
85a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
86a9de9248SMarcel Holtmann }
87a9de9248SMarcel Holtmann 
88807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
89807deac2SGustavo Padovan 					  struct sk_buff *skb)
90a9de9248SMarcel Holtmann {
91a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
92a9de9248SMarcel Holtmann }
93a9de9248SMarcel Holtmann 
94a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
95a9de9248SMarcel Holtmann {
96a9de9248SMarcel Holtmann 	struct hci_rp_role_discovery *rp = (void *) skb->data;
971da177e4SLinus Torvalds 	struct hci_conn *conn;
981da177e4SLinus Torvalds 
999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1001da177e4SLinus Torvalds 
101a9de9248SMarcel Holtmann 	if (rp->status)
102a9de9248SMarcel Holtmann 		return;
1031da177e4SLinus Torvalds 
1041da177e4SLinus Torvalds 	hci_dev_lock(hdev);
1051da177e4SLinus Torvalds 
106a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
1071da177e4SLinus Torvalds 	if (conn) {
108a9de9248SMarcel Holtmann 		if (rp->role)
1091da177e4SLinus Torvalds 			conn->link_mode &= ~HCI_LM_MASTER;
1101da177e4SLinus Torvalds 		else
1111da177e4SLinus Torvalds 			conn->link_mode |= HCI_LM_MASTER;
1121da177e4SLinus Torvalds 	}
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
115a9de9248SMarcel Holtmann }
1161da177e4SLinus Torvalds 
117e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
118e4e8e37cSMarcel Holtmann {
119e4e8e37cSMarcel Holtmann 	struct hci_rp_read_link_policy *rp = (void *) skb->data;
120e4e8e37cSMarcel Holtmann 	struct hci_conn *conn;
121e4e8e37cSMarcel Holtmann 
1229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
123e4e8e37cSMarcel Holtmann 
124e4e8e37cSMarcel Holtmann 	if (rp->status)
125e4e8e37cSMarcel Holtmann 		return;
126e4e8e37cSMarcel Holtmann 
127e4e8e37cSMarcel Holtmann 	hci_dev_lock(hdev);
128e4e8e37cSMarcel Holtmann 
129e4e8e37cSMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
130e4e8e37cSMarcel Holtmann 	if (conn)
131e4e8e37cSMarcel Holtmann 		conn->link_policy = __le16_to_cpu(rp->policy);
132e4e8e37cSMarcel Holtmann 
133e4e8e37cSMarcel Holtmann 	hci_dev_unlock(hdev);
134e4e8e37cSMarcel Holtmann }
135e4e8e37cSMarcel Holtmann 
136a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
137a9de9248SMarcel Holtmann {
138a9de9248SMarcel Holtmann 	struct hci_rp_write_link_policy *rp = (void *) skb->data;
139a9de9248SMarcel Holtmann 	struct hci_conn *conn;
140a9de9248SMarcel Holtmann 	void *sent;
141a9de9248SMarcel Holtmann 
1429f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
143a9de9248SMarcel Holtmann 
144a9de9248SMarcel Holtmann 	if (rp->status)
145a9de9248SMarcel Holtmann 		return;
146a9de9248SMarcel Holtmann 
147a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
14804837f64SMarcel Holtmann 	if (!sent)
149a9de9248SMarcel Holtmann 		return;
15004837f64SMarcel Holtmann 
15104837f64SMarcel Holtmann 	hci_dev_lock(hdev);
15204837f64SMarcel Holtmann 
153a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
154e4e8e37cSMarcel Holtmann 	if (conn)
15583985319SHarvey Harrison 		conn->link_policy = get_unaligned_le16(sent + 2);
15604837f64SMarcel Holtmann 
15704837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
1581da177e4SLinus Torvalds }
1591da177e4SLinus Torvalds 
160807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
161807deac2SGustavo Padovan 					struct sk_buff *skb)
162e4e8e37cSMarcel Holtmann {
163e4e8e37cSMarcel Holtmann 	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
164e4e8e37cSMarcel Holtmann 
1659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
166e4e8e37cSMarcel Holtmann 
167e4e8e37cSMarcel Holtmann 	if (rp->status)
168e4e8e37cSMarcel Holtmann 		return;
169e4e8e37cSMarcel Holtmann 
170e4e8e37cSMarcel Holtmann 	hdev->link_policy = __le16_to_cpu(rp->policy);
171e4e8e37cSMarcel Holtmann }
172e4e8e37cSMarcel Holtmann 
173807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
174807deac2SGustavo Padovan 					 struct sk_buff *skb)
175e4e8e37cSMarcel Holtmann {
176e4e8e37cSMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
177e4e8e37cSMarcel Holtmann 	void *sent;
178e4e8e37cSMarcel Holtmann 
1799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
180e4e8e37cSMarcel Holtmann 
181e4e8e37cSMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
182e4e8e37cSMarcel Holtmann 	if (!sent)
183e4e8e37cSMarcel Holtmann 		return;
184e4e8e37cSMarcel Holtmann 
185e4e8e37cSMarcel Holtmann 	if (!status)
186e4e8e37cSMarcel Holtmann 		hdev->link_policy = get_unaligned_le16(sent);
187e4e8e37cSMarcel Holtmann 
18823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
189e4e8e37cSMarcel Holtmann }
190e4e8e37cSMarcel Holtmann 
191a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
1921da177e4SLinus Torvalds {
193a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
194a9de9248SMarcel Holtmann 
1959f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
196a9de9248SMarcel Holtmann 
19710572132SGustavo F. Padovan 	clear_bit(HCI_RESET, &hdev->flags);
19810572132SGustavo F. Padovan 
19923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_RESET, status);
200d23264a8SAndre Guedes 
201a297e97cSJohan Hedberg 	/* Reset all non-persistent flags */
202ae854a70SAndre Guedes 	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
203ae854a70SAndre Guedes 			     BIT(HCI_PERIODIC_INQ));
20469775ff6SAndre Guedes 
20569775ff6SAndre Guedes 	hdev->discovery.state = DISCOVERY_STOPPED;
206a9de9248SMarcel Holtmann }
207a9de9248SMarcel Holtmann 
208a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
209a9de9248SMarcel Holtmann {
210a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
2111da177e4SLinus Torvalds 	void *sent;
2121da177e4SLinus Torvalds 
2139f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
2141da177e4SLinus Torvalds 
215a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
2161da177e4SLinus Torvalds 	if (!sent)
217a9de9248SMarcel Holtmann 		return;
2181da177e4SLinus Torvalds 
21956e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
22056e5cb86SJohan Hedberg 
221f51d5b24SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
222f51d5b24SJohan Hedberg 		mgmt_set_local_name_complete(hdev, sent, status);
22328cc7bdeSJohan Hedberg 	else if (!status)
22428cc7bdeSJohan Hedberg 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
225f51d5b24SJohan Hedberg 
22656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
2273159d384SJohan Hedberg 
2283159d384SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
229a9de9248SMarcel Holtmann }
230a9de9248SMarcel Holtmann 
231a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
232a9de9248SMarcel Holtmann {
233a9de9248SMarcel Holtmann 	struct hci_rp_read_local_name *rp = (void *) skb->data;
234a9de9248SMarcel Holtmann 
2359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
236a9de9248SMarcel Holtmann 
237a9de9248SMarcel Holtmann 	if (rp->status)
238a9de9248SMarcel Holtmann 		return;
239a9de9248SMarcel Holtmann 
240db99b5fcSJohan Hedberg 	if (test_bit(HCI_SETUP, &hdev->dev_flags))
2411f6c6378SJohan Hedberg 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
242a9de9248SMarcel Holtmann }
243a9de9248SMarcel Holtmann 
244a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
245a9de9248SMarcel Holtmann {
246a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
247a9de9248SMarcel Holtmann 	void *sent;
248a9de9248SMarcel Holtmann 
2499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
250a9de9248SMarcel Holtmann 
251a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
252a9de9248SMarcel Holtmann 	if (!sent)
253a9de9248SMarcel Holtmann 		return;
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds 	if (!status) {
256a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
257a9de9248SMarcel Holtmann 
2581da177e4SLinus Torvalds 		if (param == AUTH_ENABLED)
2591da177e4SLinus Torvalds 			set_bit(HCI_AUTH, &hdev->flags);
2601da177e4SLinus Torvalds 		else
2611da177e4SLinus Torvalds 			clear_bit(HCI_AUTH, &hdev->flags);
2621da177e4SLinus Torvalds 	}
263a9de9248SMarcel Holtmann 
26433ef95edSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
26533ef95edSJohan Hedberg 		mgmt_auth_enable_complete(hdev, status);
26633ef95edSJohan Hedberg 
26723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
268a9de9248SMarcel Holtmann }
2691da177e4SLinus Torvalds 
270a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
271a9de9248SMarcel Holtmann {
272a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
273a9de9248SMarcel Holtmann 	void *sent;
274a9de9248SMarcel Holtmann 
2759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
276a9de9248SMarcel Holtmann 
277a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
2781da177e4SLinus Torvalds 	if (!sent)
279a9de9248SMarcel Holtmann 		return;
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds 	if (!status) {
282a9de9248SMarcel Holtmann 		__u8 param = *((__u8 *) sent);
283a9de9248SMarcel Holtmann 
2841da177e4SLinus Torvalds 		if (param)
2851da177e4SLinus Torvalds 			set_bit(HCI_ENCRYPT, &hdev->flags);
2861da177e4SLinus Torvalds 		else
2871da177e4SLinus Torvalds 			clear_bit(HCI_ENCRYPT, &hdev->flags);
2881da177e4SLinus Torvalds 	}
289a9de9248SMarcel Holtmann 
29023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
2911da177e4SLinus Torvalds }
2921da177e4SLinus Torvalds 
293a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
294a9de9248SMarcel Holtmann {
29536f7fc7eSJohan Hedberg 	__u8 param, status = *((__u8 *) skb->data);
29636f7fc7eSJohan Hedberg 	int old_pscan, old_iscan;
297a9de9248SMarcel Holtmann 	void *sent;
2981da177e4SLinus Torvalds 
2999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
300a9de9248SMarcel Holtmann 
301a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
3021da177e4SLinus Torvalds 	if (!sent)
303a9de9248SMarcel Holtmann 		return;
3041da177e4SLinus Torvalds 
30536f7fc7eSJohan Hedberg 	param = *((__u8 *) sent);
306a9de9248SMarcel Holtmann 
30756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
30856e5cb86SJohan Hedberg 
309fa1bd918SMikel Astiz 	if (status) {
310744cf19eSJohan Hedberg 		mgmt_write_scan_failed(hdev, param, status);
3112d7cee58SJohan Hedberg 		hdev->discov_timeout = 0;
3122d7cee58SJohan Hedberg 		goto done;
3132d7cee58SJohan Hedberg 	}
3142d7cee58SJohan Hedberg 
3159fbcbb45SJohan Hedberg 	old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
3169fbcbb45SJohan Hedberg 	old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
317a9de9248SMarcel Holtmann 
31873f22f62SJohan Hedberg 	if (param & SCAN_INQUIRY) {
3191da177e4SLinus Torvalds 		set_bit(HCI_ISCAN, &hdev->flags);
3209fbcbb45SJohan Hedberg 		if (!old_iscan)
321744cf19eSJohan Hedberg 			mgmt_discoverable(hdev, 1);
32216ab91abSJohan Hedberg 		if (hdev->discov_timeout > 0) {
32316ab91abSJohan Hedberg 			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
32416ab91abSJohan Hedberg 			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
32516ab91abSJohan Hedberg 					   to);
32616ab91abSJohan Hedberg 		}
3279fbcbb45SJohan Hedberg 	} else if (old_iscan)
328744cf19eSJohan Hedberg 		mgmt_discoverable(hdev, 0);
3291da177e4SLinus Torvalds 
3309fbcbb45SJohan Hedberg 	if (param & SCAN_PAGE) {
3311da177e4SLinus Torvalds 		set_bit(HCI_PSCAN, &hdev->flags);
3329fbcbb45SJohan Hedberg 		if (!old_pscan)
333744cf19eSJohan Hedberg 			mgmt_connectable(hdev, 1);
3349fbcbb45SJohan Hedberg 	} else if (old_pscan)
335744cf19eSJohan Hedberg 		mgmt_connectable(hdev, 0);
336a9de9248SMarcel Holtmann 
33736f7fc7eSJohan Hedberg done:
33856e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
33923bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
3401da177e4SLinus Torvalds }
3411da177e4SLinus Torvalds 
342a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
343a9de9248SMarcel Holtmann {
344a9de9248SMarcel Holtmann 	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
345a9de9248SMarcel Holtmann 
3469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
347a9de9248SMarcel Holtmann 
348a9de9248SMarcel Holtmann 	if (rp->status)
349a9de9248SMarcel Holtmann 		return;
350a9de9248SMarcel Holtmann 
351a9de9248SMarcel Holtmann 	memcpy(hdev->dev_class, rp->dev_class, 3);
352a9de9248SMarcel Holtmann 
353a9de9248SMarcel Holtmann 	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
354a9de9248SMarcel Holtmann 	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
355a9de9248SMarcel Holtmann }
356a9de9248SMarcel Holtmann 
357a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
358a9de9248SMarcel Holtmann {
359a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
360a9de9248SMarcel Holtmann 	void *sent;
361a9de9248SMarcel Holtmann 
3629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
363a9de9248SMarcel Holtmann 
364a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
365a9de9248SMarcel Holtmann 	if (!sent)
366a9de9248SMarcel Holtmann 		return;
367a9de9248SMarcel Holtmann 
3687f9a903cSMarcel Holtmann 	hci_dev_lock(hdev);
3697f9a903cSMarcel Holtmann 
3707f9a903cSMarcel Holtmann 	if (status == 0)
371a9de9248SMarcel Holtmann 		memcpy(hdev->dev_class, sent, 3);
3727f9a903cSMarcel Holtmann 
3737f9a903cSMarcel Holtmann 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3747f9a903cSMarcel Holtmann 		mgmt_set_class_of_dev_complete(hdev, sent, status);
3757f9a903cSMarcel Holtmann 
3767f9a903cSMarcel Holtmann 	hci_dev_unlock(hdev);
377a9de9248SMarcel Holtmann }
378a9de9248SMarcel Holtmann 
379a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
380a9de9248SMarcel Holtmann {
381a9de9248SMarcel Holtmann 	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
382a9de9248SMarcel Holtmann 	__u16 setting;
383a9de9248SMarcel Holtmann 
3849f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
385a9de9248SMarcel Holtmann 
386a9de9248SMarcel Holtmann 	if (rp->status)
387a9de9248SMarcel Holtmann 		return;
388a9de9248SMarcel Holtmann 
389a9de9248SMarcel Holtmann 	setting = __le16_to_cpu(rp->voice_setting);
390a9de9248SMarcel Holtmann 
391a9de9248SMarcel Holtmann 	if (hdev->voice_setting == setting)
392a9de9248SMarcel Holtmann 		return;
393a9de9248SMarcel Holtmann 
394a9de9248SMarcel Holtmann 	hdev->voice_setting = setting;
395a9de9248SMarcel Holtmann 
3969f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
397a9de9248SMarcel Holtmann 
3983c54711cSGustavo F. Padovan 	if (hdev->notify)
399a9de9248SMarcel Holtmann 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
400a9de9248SMarcel Holtmann }
401a9de9248SMarcel Holtmann 
4028fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev,
4038fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
404a9de9248SMarcel Holtmann {
405a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
406f383f275SMarcel Holtmann 	__u16 setting;
407a9de9248SMarcel Holtmann 	void *sent;
408a9de9248SMarcel Holtmann 
4099f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
410a9de9248SMarcel Holtmann 
411f383f275SMarcel Holtmann 	if (status)
412f383f275SMarcel Holtmann 		return;
413f383f275SMarcel Holtmann 
414a9de9248SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
415a9de9248SMarcel Holtmann 	if (!sent)
416a9de9248SMarcel Holtmann 		return;
417a9de9248SMarcel Holtmann 
418f383f275SMarcel Holtmann 	setting = get_unaligned_le16(sent);
4191da177e4SLinus Torvalds 
420f383f275SMarcel Holtmann 	if (hdev->voice_setting == setting)
421f383f275SMarcel Holtmann 		return;
422f383f275SMarcel Holtmann 
4231da177e4SLinus Torvalds 	hdev->voice_setting = setting;
4241da177e4SLinus Torvalds 
4259f1db00cSAndrei Emeltchenko 	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
4261da177e4SLinus Torvalds 
4273c54711cSGustavo F. Padovan 	if (hdev->notify)
4281da177e4SLinus Torvalds 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
4291da177e4SLinus Torvalds }
4301da177e4SLinus Torvalds 
431a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
4321da177e4SLinus Torvalds {
433a9de9248SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
4341da177e4SLinus Torvalds 
4359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
4361da177e4SLinus Torvalds 
43723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
4381143e5a6SMarcel Holtmann }
4391143e5a6SMarcel Holtmann 
440333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
441333140b5SMarcel Holtmann {
442333140b5SMarcel Holtmann 	__u8 status = *((__u8 *) skb->data);
443333140b5SMarcel Holtmann 	void *sent;
444333140b5SMarcel Holtmann 
4459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
446333140b5SMarcel Holtmann 
447333140b5SMarcel Holtmann 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
448333140b5SMarcel Holtmann 	if (!sent)
449333140b5SMarcel Holtmann 		return;
450333140b5SMarcel Holtmann 
451c0ecddc2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
452c0ecddc2SJohan Hedberg 		mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
453c0ecddc2SJohan Hedberg 	else if (!status) {
45484bde9d6SJohan Hedberg 		if (*((u8 *) sent))
45584bde9d6SJohan Hedberg 			set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
45684bde9d6SJohan Hedberg 		else
45784bde9d6SJohan Hedberg 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
458c0ecddc2SJohan Hedberg 	}
459333140b5SMarcel Holtmann }
460333140b5SMarcel Holtmann 
461d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
462d5859e22SJohan Hedberg {
463976eb20eSJohan Hedberg 	if (lmp_ext_inq_capable(hdev))
464d5859e22SJohan Hedberg 		return 2;
465d5859e22SJohan Hedberg 
466976eb20eSJohan Hedberg 	if (lmp_inq_rssi_capable(hdev))
467d5859e22SJohan Hedberg 		return 1;
468d5859e22SJohan Hedberg 
469d5859e22SJohan Hedberg 	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
470d5859e22SJohan Hedberg 	    hdev->lmp_subver == 0x0757)
471d5859e22SJohan Hedberg 		return 1;
472d5859e22SJohan Hedberg 
473d5859e22SJohan Hedberg 	if (hdev->manufacturer == 15) {
474d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
475d5859e22SJohan Hedberg 			return 1;
476d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
477d5859e22SJohan Hedberg 			return 1;
478d5859e22SJohan Hedberg 		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
479d5859e22SJohan Hedberg 			return 1;
480d5859e22SJohan Hedberg 	}
481d5859e22SJohan Hedberg 
482d5859e22SJohan Hedberg 	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
483d5859e22SJohan Hedberg 	    hdev->lmp_subver == 0x1805)
484d5859e22SJohan Hedberg 		return 1;
485d5859e22SJohan Hedberg 
486d5859e22SJohan Hedberg 	return 0;
487d5859e22SJohan Hedberg }
488d5859e22SJohan Hedberg 
489d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev)
490d5859e22SJohan Hedberg {
491d5859e22SJohan Hedberg 	u8 mode;
492d5859e22SJohan Hedberg 
493d5859e22SJohan Hedberg 	mode = hci_get_inquiry_mode(hdev);
494d5859e22SJohan Hedberg 
495d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
496d5859e22SJohan Hedberg }
497d5859e22SJohan Hedberg 
498d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev)
499d5859e22SJohan Hedberg {
500d5859e22SJohan Hedberg 	/* The second byte is 0xff instead of 0x9f (two reserved bits
501d5859e22SJohan Hedberg 	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
502d5859e22SJohan Hedberg 	 * command otherwise */
503d5859e22SJohan Hedberg 	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
504d5859e22SJohan Hedberg 
5056de6c18dSVille Tervo 	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
5066de6c18dSVille Tervo 	 * any event mask for pre 1.2 devices */
5075a13b095SAndrei Emeltchenko 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
5086de6c18dSVille Tervo 		return;
5096de6c18dSVille Tervo 
510e1171e8dSJohan Hedberg 	if (lmp_bredr_capable(hdev)) {
511d5859e22SJohan Hedberg 		events[4] |= 0x01; /* Flow Specification Complete */
512d5859e22SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
513d5859e22SJohan Hedberg 		events[4] |= 0x04; /* Read Remote Extended Features Complete */
514d5859e22SJohan Hedberg 		events[5] |= 0x08; /* Synchronous Connection Complete */
515d5859e22SJohan Hedberg 		events[5] |= 0x10; /* Synchronous Connection Changed */
516e1171e8dSJohan Hedberg 	}
517d5859e22SJohan Hedberg 
518976eb20eSJohan Hedberg 	if (lmp_inq_rssi_capable(hdev))
519a24299e6SJohan Hedberg 		events[4] |= 0x02; /* Inquiry Result with RSSI */
520d5859e22SJohan Hedberg 
521999dcd10SAndre Guedes 	if (lmp_sniffsubr_capable(hdev))
522d5859e22SJohan Hedberg 		events[5] |= 0x20; /* Sniff Subrating */
523d5859e22SJohan Hedberg 
524976eb20eSJohan Hedberg 	if (lmp_pause_enc_capable(hdev))
525d5859e22SJohan Hedberg 		events[5] |= 0x80; /* Encryption Key Refresh Complete */
526d5859e22SJohan Hedberg 
527976eb20eSJohan Hedberg 	if (lmp_ext_inq_capable(hdev))
528d5859e22SJohan Hedberg 		events[5] |= 0x40; /* Extended Inquiry Result */
529d5859e22SJohan Hedberg 
530c58e810eSAndre Guedes 	if (lmp_no_flush_capable(hdev))
531d5859e22SJohan Hedberg 		events[7] |= 0x01; /* Enhanced Flush Complete */
532d5859e22SJohan Hedberg 
533976eb20eSJohan Hedberg 	if (lmp_lsto_capable(hdev))
534d5859e22SJohan Hedberg 		events[6] |= 0x80; /* Link Supervision Timeout Changed */
535d5859e22SJohan Hedberg 
5369a1a1996SAndre Guedes 	if (lmp_ssp_capable(hdev)) {
537d5859e22SJohan Hedberg 		events[6] |= 0x01;	/* IO Capability Request */
538d5859e22SJohan Hedberg 		events[6] |= 0x02;	/* IO Capability Response */
539d5859e22SJohan Hedberg 		events[6] |= 0x04;	/* User Confirmation Request */
540d5859e22SJohan Hedberg 		events[6] |= 0x08;	/* User Passkey Request */
541d5859e22SJohan Hedberg 		events[6] |= 0x10;	/* Remote OOB Data Request */
542d5859e22SJohan Hedberg 		events[6] |= 0x20;	/* Simple Pairing Complete */
543d5859e22SJohan Hedberg 		events[7] |= 0x04;	/* User Passkey Notification */
544d5859e22SJohan Hedberg 		events[7] |= 0x08;	/* Keypress Notification */
545d5859e22SJohan Hedberg 		events[7] |= 0x10;	/* Remote Host Supported
546d5859e22SJohan Hedberg 					 * Features Notification */
547d5859e22SJohan Hedberg 	}
548d5859e22SJohan Hedberg 
549c383ddc4SAndre Guedes 	if (lmp_le_capable(hdev))
550d5859e22SJohan Hedberg 		events[7] |= 0x20;	/* LE Meta-Event */
551d5859e22SJohan Hedberg 
552d5859e22SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
553e36b04c8SJohan Hedberg 
554e36b04c8SJohan Hedberg 	if (lmp_le_capable(hdev)) {
555e36b04c8SJohan Hedberg 		memset(events, 0, sizeof(events));
556e36b04c8SJohan Hedberg 		events[0] = 0x1f;
557e36b04c8SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
558e36b04c8SJohan Hedberg 			     sizeof(events), events);
559e36b04c8SJohan Hedberg 	}
560d5859e22SJohan Hedberg }
561d5859e22SJohan Hedberg 
5624611dfa8SGustavo Padovan static void bredr_setup(struct hci_dev *hdev)
563e1171e8dSJohan Hedberg {
564e1171e8dSJohan Hedberg 	struct hci_cp_delete_stored_link_key cp;
565e1171e8dSJohan Hedberg 	__le16 param;
566e1171e8dSJohan Hedberg 	__u8 flt_type;
567e1171e8dSJohan Hedberg 
568e1171e8dSJohan Hedberg 	/* Read Buffer Size (ACL mtu, max pkt, etc.) */
569e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
570e1171e8dSJohan Hedberg 
571e1171e8dSJohan Hedberg 	/* Read Class of Device */
572e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
573e1171e8dSJohan Hedberg 
574e1171e8dSJohan Hedberg 	/* Read Local Name */
575e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
576e1171e8dSJohan Hedberg 
577e1171e8dSJohan Hedberg 	/* Read Voice Setting */
578e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
579e1171e8dSJohan Hedberg 
580e1171e8dSJohan Hedberg 	/* Clear Event Filters */
581e1171e8dSJohan Hedberg 	flt_type = HCI_FLT_CLEAR_ALL;
582e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
583e1171e8dSJohan Hedberg 
584e1171e8dSJohan Hedberg 	/* Connection accept timeout ~20 secs */
585e1171e8dSJohan Hedberg 	param = __constant_cpu_to_le16(0x7d00);
586e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
587e1171e8dSJohan Hedberg 
588e1171e8dSJohan Hedberg 	bacpy(&cp.bdaddr, BDADDR_ANY);
589e1171e8dSJohan Hedberg 	cp.delete_all = 1;
590e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
591e1171e8dSJohan Hedberg }
592e1171e8dSJohan Hedberg 
5934611dfa8SGustavo Padovan static void le_setup(struct hci_dev *hdev)
594e1171e8dSJohan Hedberg {
595e1171e8dSJohan Hedberg 	/* Read LE Buffer Size */
596e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
5978fa19098SJohan Hedberg 
5988fa19098SJohan Hedberg 	/* Read LE Advertising Channel TX Power */
5998fa19098SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
600e1171e8dSJohan Hedberg }
601e1171e8dSJohan Hedberg 
602d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev)
603d5859e22SJohan Hedberg {
604e61ef499SAndrei Emeltchenko 	if (hdev->dev_type != HCI_BREDR)
605e61ef499SAndrei Emeltchenko 		return;
606e61ef499SAndrei Emeltchenko 
607e1171e8dSJohan Hedberg 	/* Read BD Address */
608e1171e8dSJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
609e1171e8dSJohan Hedberg 
610e1171e8dSJohan Hedberg 	if (lmp_bredr_capable(hdev))
6114611dfa8SGustavo Padovan 		bredr_setup(hdev);
612e1171e8dSJohan Hedberg 
613e1171e8dSJohan Hedberg 	if (lmp_le_capable(hdev))
6144611dfa8SGustavo Padovan 		le_setup(hdev);
615e1171e8dSJohan Hedberg 
616d5859e22SJohan Hedberg 	hci_setup_event_mask(hdev);
617d5859e22SJohan Hedberg 
618d095c1ebSAndrei Emeltchenko 	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
619d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
620d5859e22SJohan Hedberg 
6216d3c730fSGustavo Padovan 	if (lmp_ssp_capable(hdev)) {
62254d04dbbSJohan Hedberg 		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
623d5859e22SJohan Hedberg 			u8 mode = 0x01;
62454d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
62554d04dbbSJohan Hedberg 				     sizeof(mode), &mode);
62654d04dbbSJohan Hedberg 		} else {
62754d04dbbSJohan Hedberg 			struct hci_cp_write_eir cp;
62854d04dbbSJohan Hedberg 
62954d04dbbSJohan Hedberg 			memset(hdev->eir, 0, sizeof(hdev->eir));
63054d04dbbSJohan Hedberg 			memset(&cp, 0, sizeof(cp));
63154d04dbbSJohan Hedberg 
63254d04dbbSJohan Hedberg 			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
63354d04dbbSJohan Hedberg 		}
634d5859e22SJohan Hedberg 	}
635d5859e22SJohan Hedberg 
636976eb20eSJohan Hedberg 	if (lmp_inq_rssi_capable(hdev))
637d5859e22SJohan Hedberg 		hci_setup_inquiry_mode(hdev);
638d5859e22SJohan Hedberg 
639976eb20eSJohan Hedberg 	if (lmp_inq_tx_pwr_capable(hdev))
640d5859e22SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
641971e3a4bSAndre Guedes 
642976eb20eSJohan Hedberg 	if (lmp_ext_feat_capable(hdev)) {
643971e3a4bSAndre Guedes 		struct hci_cp_read_local_ext_features cp;
644971e3a4bSAndre Guedes 
645971e3a4bSAndre Guedes 		cp.page = 0x01;
64604124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
64704124681SGustavo F. Padovan 			     &cp);
648971e3a4bSAndre Guedes 	}
649e6100a25SAndre Guedes 
65047990ea0SJohan Hedberg 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
65147990ea0SJohan Hedberg 		u8 enable = 1;
65204124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
65304124681SGustavo F. Padovan 			     &enable);
65447990ea0SJohan Hedberg 	}
655d5859e22SJohan Hedberg }
656d5859e22SJohan Hedberg 
657a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
658a9de9248SMarcel Holtmann {
659a9de9248SMarcel Holtmann 	struct hci_rp_read_local_version *rp = (void *) skb->data;
6601143e5a6SMarcel Holtmann 
6619f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
6621143e5a6SMarcel Holtmann 
663a9de9248SMarcel Holtmann 	if (rp->status)
66428b8df77SAndrei Emeltchenko 		goto done;
6651143e5a6SMarcel Holtmann 
666a9de9248SMarcel Holtmann 	hdev->hci_ver = rp->hci_ver;
667e4e8e37cSMarcel Holtmann 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
668d5859e22SJohan Hedberg 	hdev->lmp_ver = rp->lmp_ver;
669e4e8e37cSMarcel Holtmann 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
670d5859e22SJohan Hedberg 	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
6711da177e4SLinus Torvalds 
6729f1db00cSAndrei Emeltchenko 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
673807deac2SGustavo Padovan 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
674d5859e22SJohan Hedberg 
675d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags))
676d5859e22SJohan Hedberg 		hci_setup(hdev);
67728b8df77SAndrei Emeltchenko 
67828b8df77SAndrei Emeltchenko done:
67928b8df77SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
680d5859e22SJohan Hedberg }
681d5859e22SJohan Hedberg 
682d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev)
683d5859e22SJohan Hedberg {
684035100c8SAndrei Emeltchenko 	struct hci_cp_write_def_link_policy cp;
685d5859e22SJohan Hedberg 	u16 link_policy = 0;
686d5859e22SJohan Hedberg 
6879f92ebf6SAndre Guedes 	if (lmp_rswitch_capable(hdev))
688d5859e22SJohan Hedberg 		link_policy |= HCI_LP_RSWITCH;
689976eb20eSJohan Hedberg 	if (lmp_hold_capable(hdev))
690d5859e22SJohan Hedberg 		link_policy |= HCI_LP_HOLD;
6916eded100SAndre Guedes 	if (lmp_sniff_capable(hdev))
692d5859e22SJohan Hedberg 		link_policy |= HCI_LP_SNIFF;
693976eb20eSJohan Hedberg 	if (lmp_park_capable(hdev))
694d5859e22SJohan Hedberg 		link_policy |= HCI_LP_PARK;
695d5859e22SJohan Hedberg 
696035100c8SAndrei Emeltchenko 	cp.policy = cpu_to_le16(link_policy);
697035100c8SAndrei Emeltchenko 	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
6981da177e4SLinus Torvalds }
6991da177e4SLinus Torvalds 
7008fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev,
7018fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
702a9de9248SMarcel Holtmann {
703a9de9248SMarcel Holtmann 	struct hci_rp_read_local_commands *rp = (void *) skb->data;
704a9de9248SMarcel Holtmann 
7059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
706a9de9248SMarcel Holtmann 
707a9de9248SMarcel Holtmann 	if (rp->status)
708d5859e22SJohan Hedberg 		goto done;
709a9de9248SMarcel Holtmann 
710a9de9248SMarcel Holtmann 	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
711d5859e22SJohan Hedberg 
712d5859e22SJohan Hedberg 	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
713d5859e22SJohan Hedberg 		hci_setup_link_policy(hdev);
714d5859e22SJohan Hedberg 
715d5859e22SJohan Hedberg done:
716d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
717a9de9248SMarcel Holtmann }
718a9de9248SMarcel Holtmann 
7198fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev,
7208fc9ced3SGustavo Padovan 				       struct sk_buff *skb)
721a9de9248SMarcel Holtmann {
722a9de9248SMarcel Holtmann 	struct hci_rp_read_local_features *rp = (void *) skb->data;
723a9de9248SMarcel Holtmann 
7249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
725a9de9248SMarcel Holtmann 
726a9de9248SMarcel Holtmann 	if (rp->status)
727a9de9248SMarcel Holtmann 		return;
728a9de9248SMarcel Holtmann 
729a9de9248SMarcel Holtmann 	memcpy(hdev->features, rp->features, 8);
7301da177e4SLinus Torvalds 
7311da177e4SLinus Torvalds 	/* Adjust default settings according to features
7321da177e4SLinus Torvalds 	 * supported by device. */
733a9de9248SMarcel Holtmann 
7341da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_3SLOT)
7351da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
7361da177e4SLinus Torvalds 
7371da177e4SLinus Torvalds 	if (hdev->features[0] & LMP_5SLOT)
7381da177e4SLinus Torvalds 		hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
7391da177e4SLinus Torvalds 
7405b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV2) {
7411da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV2);
7425b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV2);
7435b7f9909SMarcel Holtmann 	}
7441da177e4SLinus Torvalds 
7455b7f9909SMarcel Holtmann 	if (hdev->features[1] & LMP_HV3) {
7461da177e4SLinus Torvalds 		hdev->pkt_type  |= (HCI_HV3);
7475b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_HV3);
7485b7f9909SMarcel Holtmann 	}
7495b7f9909SMarcel Holtmann 
75045db810fSAndre Guedes 	if (lmp_esco_capable(hdev))
7515b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV3);
7525b7f9909SMarcel Holtmann 
7535b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV4)
7545b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV4);
7555b7f9909SMarcel Holtmann 
7565b7f9909SMarcel Holtmann 	if (hdev->features[4] & LMP_EV5)
7575b7f9909SMarcel Holtmann 		hdev->esco_type |= (ESCO_EV5);
7581da177e4SLinus Torvalds 
759efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_2M)
760efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV3);
761efc7688bSMarcel Holtmann 
762efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_ESCO_3M)
763efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_3EV3);
764efc7688bSMarcel Holtmann 
765efc7688bSMarcel Holtmann 	if (hdev->features[5] & LMP_EDR_3S_ESCO)
766efc7688bSMarcel Holtmann 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
767efc7688bSMarcel Holtmann 
768a9de9248SMarcel Holtmann 	BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
769a9de9248SMarcel Holtmann 	       hdev->features[0], hdev->features[1],
770a9de9248SMarcel Holtmann 	       hdev->features[2], hdev->features[3],
771a9de9248SMarcel Holtmann 	       hdev->features[4], hdev->features[5],
772a9de9248SMarcel Holtmann 	       hdev->features[6], hdev->features[7]);
7731da177e4SLinus Torvalds }
7741da177e4SLinus Torvalds 
7758f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev)
7768f984dfaSJohan Hedberg {
7778f984dfaSJohan Hedberg 	struct hci_cp_write_le_host_supported cp;
7788f984dfaSJohan Hedberg 
7798f984dfaSJohan Hedberg 	memset(&cp, 0, sizeof(cp));
7808f984dfaSJohan Hedberg 
7819d42820fSMarcel Holtmann 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
7828f984dfaSJohan Hedberg 		cp.le = 1;
783976eb20eSJohan Hedberg 		cp.simul = !!lmp_le_br_capable(hdev);
7848f984dfaSJohan Hedberg 	}
7858f984dfaSJohan Hedberg 
786976eb20eSJohan Hedberg 	if (cp.le != !!lmp_host_le_capable(hdev))
78704124681SGustavo F. Padovan 		hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
78804124681SGustavo F. Padovan 			     &cp);
7898f984dfaSJohan Hedberg }
7908f984dfaSJohan Hedberg 
791971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
792971e3a4bSAndre Guedes 					   struct sk_buff *skb)
793971e3a4bSAndre Guedes {
794971e3a4bSAndre Guedes 	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
795971e3a4bSAndre Guedes 
7969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
797971e3a4bSAndre Guedes 
798971e3a4bSAndre Guedes 	if (rp->status)
7998f984dfaSJohan Hedberg 		goto done;
800971e3a4bSAndre Guedes 
801b5b32b65SAndre Guedes 	switch (rp->page) {
802b5b32b65SAndre Guedes 	case 0:
803b5b32b65SAndre Guedes 		memcpy(hdev->features, rp->features, 8);
804b5b32b65SAndre Guedes 		break;
805b5b32b65SAndre Guedes 	case 1:
80659e29406SAndre Guedes 		memcpy(hdev->host_features, rp->features, 8);
807b5b32b65SAndre Guedes 		break;
808b5b32b65SAndre Guedes 	}
809971e3a4bSAndre Guedes 
810c383ddc4SAndre Guedes 	if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
8118f984dfaSJohan Hedberg 		hci_set_le_support(hdev);
8128f984dfaSJohan Hedberg 
8138f984dfaSJohan Hedberg done:
814971e3a4bSAndre Guedes 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
815971e3a4bSAndre Guedes }
816971e3a4bSAndre Guedes 
8171e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
8181e89cffbSAndrei Emeltchenko 					  struct sk_buff *skb)
8191e89cffbSAndrei Emeltchenko {
8201e89cffbSAndrei Emeltchenko 	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
8211e89cffbSAndrei Emeltchenko 
8229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
8231e89cffbSAndrei Emeltchenko 
8241e89cffbSAndrei Emeltchenko 	if (rp->status)
8251e89cffbSAndrei Emeltchenko 		return;
8261e89cffbSAndrei Emeltchenko 
8271e89cffbSAndrei Emeltchenko 	hdev->flow_ctl_mode = rp->mode;
8281e89cffbSAndrei Emeltchenko 
8291e89cffbSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
8301e89cffbSAndrei Emeltchenko }
8311e89cffbSAndrei Emeltchenko 
832a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
833a9de9248SMarcel Holtmann {
834a9de9248SMarcel Holtmann 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
835a9de9248SMarcel Holtmann 
8369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
837a9de9248SMarcel Holtmann 
838a9de9248SMarcel Holtmann 	if (rp->status)
839a9de9248SMarcel Holtmann 		return;
840a9de9248SMarcel Holtmann 
841a9de9248SMarcel Holtmann 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
842a9de9248SMarcel Holtmann 	hdev->sco_mtu  = rp->sco_mtu;
843a9de9248SMarcel Holtmann 	hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
844a9de9248SMarcel Holtmann 	hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
845da1f5198SMarcel Holtmann 
846da1f5198SMarcel Holtmann 	if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
847da1f5198SMarcel Holtmann 		hdev->sco_mtu  = 64;
848da1f5198SMarcel Holtmann 		hdev->sco_pkts = 8;
849da1f5198SMarcel Holtmann 	}
850da1f5198SMarcel Holtmann 
851da1f5198SMarcel Holtmann 	hdev->acl_cnt = hdev->acl_pkts;
852da1f5198SMarcel Holtmann 	hdev->sco_cnt = hdev->sco_pkts;
8531da177e4SLinus Torvalds 
854807deac2SGustavo Padovan 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
855807deac2SGustavo Padovan 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
8561da177e4SLinus Torvalds }
8571da177e4SLinus Torvalds 
858a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
859a9de9248SMarcel Holtmann {
860a9de9248SMarcel Holtmann 	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
8611da177e4SLinus Torvalds 
8629f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
863a9de9248SMarcel Holtmann 
864a9de9248SMarcel Holtmann 	if (!rp->status)
865a9de9248SMarcel Holtmann 		bacpy(&hdev->bdaddr, &rp->bdaddr);
866a9de9248SMarcel Holtmann 
86723bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
86823bb5763SJohan Hedberg }
86923bb5763SJohan Hedberg 
870350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev,
871350ee4cfSAndrei Emeltchenko 					struct sk_buff *skb)
872350ee4cfSAndrei Emeltchenko {
873350ee4cfSAndrei Emeltchenko 	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
874350ee4cfSAndrei Emeltchenko 
8759f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
876350ee4cfSAndrei Emeltchenko 
877350ee4cfSAndrei Emeltchenko 	if (rp->status)
878350ee4cfSAndrei Emeltchenko 		return;
879350ee4cfSAndrei Emeltchenko 
880350ee4cfSAndrei Emeltchenko 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
881350ee4cfSAndrei Emeltchenko 	hdev->block_len = __le16_to_cpu(rp->block_len);
882350ee4cfSAndrei Emeltchenko 	hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
883350ee4cfSAndrei Emeltchenko 
884350ee4cfSAndrei Emeltchenko 	hdev->block_cnt = hdev->num_blocks;
885350ee4cfSAndrei Emeltchenko 
886350ee4cfSAndrei Emeltchenko 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
887350ee4cfSAndrei Emeltchenko 	       hdev->block_cnt, hdev->block_len);
888350ee4cfSAndrei Emeltchenko 
889350ee4cfSAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
890350ee4cfSAndrei Emeltchenko }
891350ee4cfSAndrei Emeltchenko 
89223bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
89323bb5763SJohan Hedberg {
89423bb5763SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
89523bb5763SJohan Hedberg 
8969f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
89723bb5763SJohan Hedberg 
89823bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
8991da177e4SLinus Torvalds }
9001da177e4SLinus Torvalds 
901928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
902928abaa7SAndrei Emeltchenko 				       struct sk_buff *skb)
903928abaa7SAndrei Emeltchenko {
904928abaa7SAndrei Emeltchenko 	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
905928abaa7SAndrei Emeltchenko 
9069f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
907928abaa7SAndrei Emeltchenko 
908928abaa7SAndrei Emeltchenko 	if (rp->status)
9098e2a0d92SAndrei Emeltchenko 		goto a2mp_rsp;
910928abaa7SAndrei Emeltchenko 
911928abaa7SAndrei Emeltchenko 	hdev->amp_status = rp->amp_status;
912928abaa7SAndrei Emeltchenko 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
913928abaa7SAndrei Emeltchenko 	hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
914928abaa7SAndrei Emeltchenko 	hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
915928abaa7SAndrei Emeltchenko 	hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
916928abaa7SAndrei Emeltchenko 	hdev->amp_type = rp->amp_type;
917928abaa7SAndrei Emeltchenko 	hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
918928abaa7SAndrei Emeltchenko 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
919928abaa7SAndrei Emeltchenko 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
920928abaa7SAndrei Emeltchenko 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
921928abaa7SAndrei Emeltchenko 
922928abaa7SAndrei Emeltchenko 	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
9238e2a0d92SAndrei Emeltchenko 
9248e2a0d92SAndrei Emeltchenko a2mp_rsp:
9258e2a0d92SAndrei Emeltchenko 	a2mp_send_getinfo_rsp(hdev);
926928abaa7SAndrei Emeltchenko }
927928abaa7SAndrei Emeltchenko 
928903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
929903e4541SAndrei Emeltchenko 					struct sk_buff *skb)
930903e4541SAndrei Emeltchenko {
931903e4541SAndrei Emeltchenko 	struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
932903e4541SAndrei Emeltchenko 	struct amp_assoc *assoc = &hdev->loc_assoc;
933903e4541SAndrei Emeltchenko 	size_t rem_len, frag_len;
934903e4541SAndrei Emeltchenko 
935903e4541SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
936903e4541SAndrei Emeltchenko 
937903e4541SAndrei Emeltchenko 	if (rp->status)
938903e4541SAndrei Emeltchenko 		goto a2mp_rsp;
939903e4541SAndrei Emeltchenko 
940903e4541SAndrei Emeltchenko 	frag_len = skb->len - sizeof(*rp);
941903e4541SAndrei Emeltchenko 	rem_len = __le16_to_cpu(rp->rem_len);
942903e4541SAndrei Emeltchenko 
943903e4541SAndrei Emeltchenko 	if (rem_len > frag_len) {
9442e430be3SAndrei Emeltchenko 		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
945903e4541SAndrei Emeltchenko 
946903e4541SAndrei Emeltchenko 		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
947903e4541SAndrei Emeltchenko 		assoc->offset += frag_len;
948903e4541SAndrei Emeltchenko 
949903e4541SAndrei Emeltchenko 		/* Read other fragments */
950903e4541SAndrei Emeltchenko 		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
951903e4541SAndrei Emeltchenko 
952903e4541SAndrei Emeltchenko 		return;
953903e4541SAndrei Emeltchenko 	}
954903e4541SAndrei Emeltchenko 
955903e4541SAndrei Emeltchenko 	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
956903e4541SAndrei Emeltchenko 	assoc->len = assoc->offset + rem_len;
957903e4541SAndrei Emeltchenko 	assoc->offset = 0;
958903e4541SAndrei Emeltchenko 
959903e4541SAndrei Emeltchenko a2mp_rsp:
960903e4541SAndrei Emeltchenko 	/* Send A2MP Rsp when all fragments are received */
961903e4541SAndrei Emeltchenko 	a2mp_send_getampassoc_rsp(hdev, rp->status);
9629495b2eeSAndrei Emeltchenko 	a2mp_send_create_phy_link_req(hdev, rp->status);
963903e4541SAndrei Emeltchenko }
964903e4541SAndrei Emeltchenko 
965b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
966b0916ea0SJohan Hedberg 					  struct sk_buff *skb)
967b0916ea0SJohan Hedberg {
968b0916ea0SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
969b0916ea0SJohan Hedberg 
9709f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
971b0916ea0SJohan Hedberg 
972b0916ea0SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
973b0916ea0SJohan Hedberg }
974b0916ea0SJohan Hedberg 
975d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
976d5859e22SJohan Hedberg {
977d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
978d5859e22SJohan Hedberg 
9799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
980d5859e22SJohan Hedberg 
981d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
982d5859e22SJohan Hedberg }
983d5859e22SJohan Hedberg 
984d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
985d5859e22SJohan Hedberg 				      struct sk_buff *skb)
986d5859e22SJohan Hedberg {
987d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
988d5859e22SJohan Hedberg 
9899f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
990d5859e22SJohan Hedberg 
991d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
992d5859e22SJohan Hedberg }
993d5859e22SJohan Hedberg 
994d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
995d5859e22SJohan Hedberg 					 struct sk_buff *skb)
996d5859e22SJohan Hedberg {
99791c4e9b1SMarcel Holtmann 	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
998d5859e22SJohan Hedberg 
9999f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1000d5859e22SJohan Hedberg 
100191c4e9b1SMarcel Holtmann 	if (!rp->status)
100291c4e9b1SMarcel Holtmann 		hdev->inq_tx_power = rp->tx_power;
100391c4e9b1SMarcel Holtmann 
100491c4e9b1SMarcel Holtmann 	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
1005d5859e22SJohan Hedberg }
1006d5859e22SJohan Hedberg 
1007d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
1008d5859e22SJohan Hedberg {
1009d5859e22SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
1010d5859e22SJohan Hedberg 
10119f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1012d5859e22SJohan Hedberg 
1013d5859e22SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
1014d5859e22SJohan Hedberg }
1015d5859e22SJohan Hedberg 
1016980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
1017980e1a53SJohan Hedberg {
1018980e1a53SJohan Hedberg 	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
1019980e1a53SJohan Hedberg 	struct hci_cp_pin_code_reply *cp;
1020980e1a53SJohan Hedberg 	struct hci_conn *conn;
1021980e1a53SJohan Hedberg 
10229f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1023980e1a53SJohan Hedberg 
102456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
102556e5cb86SJohan Hedberg 
1026a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1027744cf19eSJohan Hedberg 		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
1028980e1a53SJohan Hedberg 
1029fa1bd918SMikel Astiz 	if (rp->status)
103056e5cb86SJohan Hedberg 		goto unlock;
1031980e1a53SJohan Hedberg 
1032980e1a53SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
1033980e1a53SJohan Hedberg 	if (!cp)
103456e5cb86SJohan Hedberg 		goto unlock;
1035980e1a53SJohan Hedberg 
1036980e1a53SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1037980e1a53SJohan Hedberg 	if (conn)
1038980e1a53SJohan Hedberg 		conn->pin_length = cp->pin_len;
103956e5cb86SJohan Hedberg 
104056e5cb86SJohan Hedberg unlock:
104156e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1042980e1a53SJohan Hedberg }
1043980e1a53SJohan Hedberg 
1044980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1045980e1a53SJohan Hedberg {
1046980e1a53SJohan Hedberg 	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
1047980e1a53SJohan Hedberg 
10489f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1049980e1a53SJohan Hedberg 
105056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
105156e5cb86SJohan Hedberg 
1052a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1053744cf19eSJohan Hedberg 		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
1054980e1a53SJohan Hedberg 						 rp->status);
105556e5cb86SJohan Hedberg 
105656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1057980e1a53SJohan Hedberg }
105856e5cb86SJohan Hedberg 
10596ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
10606ed58ec5SVille Tervo 				       struct sk_buff *skb)
10616ed58ec5SVille Tervo {
10626ed58ec5SVille Tervo 	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
10636ed58ec5SVille Tervo 
10649f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10656ed58ec5SVille Tervo 
10666ed58ec5SVille Tervo 	if (rp->status)
10676ed58ec5SVille Tervo 		return;
10686ed58ec5SVille Tervo 
10696ed58ec5SVille Tervo 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
10706ed58ec5SVille Tervo 	hdev->le_pkts = rp->le_max_pkt;
10716ed58ec5SVille Tervo 
10726ed58ec5SVille Tervo 	hdev->le_cnt = hdev->le_pkts;
10736ed58ec5SVille Tervo 
10746ed58ec5SVille Tervo 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
10756ed58ec5SVille Tervo 
10766ed58ec5SVille Tervo 	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
10776ed58ec5SVille Tervo }
1078980e1a53SJohan Hedberg 
10798fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
10808fa19098SJohan Hedberg 					struct sk_buff *skb)
10818fa19098SJohan Hedberg {
10828fa19098SJohan Hedberg 	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
10838fa19098SJohan Hedberg 
10848fa19098SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
10858fa19098SJohan Hedberg 
10868fa19098SJohan Hedberg 	if (!rp->status)
10878fa19098SJohan Hedberg 		hdev->adv_tx_power = rp->tx_power;
10888fa19098SJohan Hedberg 
10898fa19098SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
10908fa19098SJohan Hedberg }
10918fa19098SJohan Hedberg 
1092e36b04c8SJohan Hedberg static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
1093e36b04c8SJohan Hedberg {
1094e36b04c8SJohan Hedberg 	__u8 status = *((__u8 *) skb->data);
1095e36b04c8SJohan Hedberg 
1096e36b04c8SJohan Hedberg 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1097e36b04c8SJohan Hedberg 
1098e36b04c8SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
1099e36b04c8SJohan Hedberg }
1100e36b04c8SJohan Hedberg 
1101a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
1102a5c29683SJohan Hedberg {
1103a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1104a5c29683SJohan Hedberg 
11059f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1106a5c29683SJohan Hedberg 
110756e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
110856e5cb86SJohan Hedberg 
1109a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
111004124681SGustavo F. Padovan 		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
111104124681SGustavo F. Padovan 						 rp->status);
111256e5cb86SJohan Hedberg 
111356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1114a5c29683SJohan Hedberg }
1115a5c29683SJohan Hedberg 
1116a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
1117a5c29683SJohan Hedberg 					  struct sk_buff *skb)
1118a5c29683SJohan Hedberg {
1119a5c29683SJohan Hedberg 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
1120a5c29683SJohan Hedberg 
11219f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1122a5c29683SJohan Hedberg 
112356e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
112456e5cb86SJohan Hedberg 
1125a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1126744cf19eSJohan Hedberg 		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
112704124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
112856e5cb86SJohan Hedberg 
112956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1130a5c29683SJohan Hedberg }
1131a5c29683SJohan Hedberg 
11321143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
11331143d458SBrian Gix {
11341143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
11351143d458SBrian Gix 
11369f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
11371143d458SBrian Gix 
11381143d458SBrian Gix 	hci_dev_lock(hdev);
11391143d458SBrian Gix 
1140a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1141272d90dfSJohan Hedberg 		mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
1142272d90dfSJohan Hedberg 						 0, rp->status);
11431143d458SBrian Gix 
11441143d458SBrian Gix 	hci_dev_unlock(hdev);
11451143d458SBrian Gix }
11461143d458SBrian Gix 
11471143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
11481143d458SBrian Gix 					  struct sk_buff *skb)
11491143d458SBrian Gix {
11501143d458SBrian Gix 	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
11511143d458SBrian Gix 
11529f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
11531143d458SBrian Gix 
11541143d458SBrian Gix 	hci_dev_lock(hdev);
11551143d458SBrian Gix 
1156a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
11571143d458SBrian Gix 		mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
115804124681SGustavo F. Padovan 						     ACL_LINK, 0, rp->status);
11591143d458SBrian Gix 
11601143d458SBrian Gix 	hci_dev_unlock(hdev);
11611143d458SBrian Gix }
11621143d458SBrian Gix 
1163c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
1164c35938b2SSzymon Janc 					     struct sk_buff *skb)
1165c35938b2SSzymon Janc {
1166c35938b2SSzymon Janc 	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
1167c35938b2SSzymon Janc 
11689f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1169c35938b2SSzymon Janc 
117056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1171744cf19eSJohan Hedberg 	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
1172c35938b2SSzymon Janc 						rp->randomizer, rp->status);
117356e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1174c35938b2SSzymon Janc }
1175c35938b2SSzymon Janc 
117607f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
117707f7fa5dSAndre Guedes {
117807f7fa5dSAndre Guedes 	__u8 status = *((__u8 *) skb->data);
117907f7fa5dSAndre Guedes 
11809f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
11817ba8b4beSAndre Guedes 
11827ba8b4beSAndre Guedes 	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
11833fd24153SAndre Guedes 
11843fd24153SAndre Guedes 	if (status) {
11853fd24153SAndre Guedes 		hci_dev_lock(hdev);
11863fd24153SAndre Guedes 		mgmt_start_discovery_failed(hdev, status);
11873fd24153SAndre Guedes 		hci_dev_unlock(hdev);
11883fd24153SAndre Guedes 		return;
11893fd24153SAndre Guedes 	}
119007f7fa5dSAndre Guedes }
119107f7fa5dSAndre Guedes 
1192eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1193eb9d91f5SAndre Guedes 				      struct sk_buff *skb)
1194eb9d91f5SAndre Guedes {
1195eb9d91f5SAndre Guedes 	struct hci_cp_le_set_scan_enable *cp;
1196eb9d91f5SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1197eb9d91f5SAndre Guedes 
11989f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1199eb9d91f5SAndre Guedes 
1200eb9d91f5SAndre Guedes 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1201eb9d91f5SAndre Guedes 	if (!cp)
1202eb9d91f5SAndre Guedes 		return;
1203eb9d91f5SAndre Guedes 
120468a8aea4SAndrei Emeltchenko 	switch (cp->enable) {
120568a8aea4SAndrei Emeltchenko 	case LE_SCANNING_ENABLED:
12067ba8b4beSAndre Guedes 		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
12077ba8b4beSAndre Guedes 
12083fd24153SAndre Guedes 		if (status) {
12093fd24153SAndre Guedes 			hci_dev_lock(hdev);
12103fd24153SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
12113fd24153SAndre Guedes 			hci_dev_unlock(hdev);
12127ba8b4beSAndre Guedes 			return;
12133fd24153SAndre Guedes 		}
12147ba8b4beSAndre Guedes 
1215d23264a8SAndre Guedes 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1216d23264a8SAndre Guedes 
1217a8f13c8cSAndre Guedes 		hci_dev_lock(hdev);
1218343f935bSAndre Guedes 		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1219a8f13c8cSAndre Guedes 		hci_dev_unlock(hdev);
122068a8aea4SAndrei Emeltchenko 		break;
122168a8aea4SAndrei Emeltchenko 
122268a8aea4SAndrei Emeltchenko 	case LE_SCANNING_DISABLED:
1223c9ecc48eSAndre Guedes 		if (status) {
1224c9ecc48eSAndre Guedes 			hci_dev_lock(hdev);
1225c9ecc48eSAndre Guedes 			mgmt_stop_discovery_failed(hdev, status);
1226c9ecc48eSAndre Guedes 			hci_dev_unlock(hdev);
12277ba8b4beSAndre Guedes 			return;
1228c9ecc48eSAndre Guedes 		}
12297ba8b4beSAndre Guedes 
1230d23264a8SAndre Guedes 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1231d23264a8SAndre Guedes 
1232bc3dd33cSAndre Guedes 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
1233bc3dd33cSAndre Guedes 		    hdev->discovery.state == DISCOVERY_FINDING) {
12345e0452c0SAndre Guedes 			mgmt_interleaved_discovery(hdev);
12355e0452c0SAndre Guedes 		} else {
1236c599008fSAndre Guedes 			hci_dev_lock(hdev);
1237c599008fSAndre Guedes 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1238c599008fSAndre Guedes 			hci_dev_unlock(hdev);
12395e0452c0SAndre Guedes 		}
1240c599008fSAndre Guedes 
124168a8aea4SAndrei Emeltchenko 		break;
124268a8aea4SAndrei Emeltchenko 
124368a8aea4SAndrei Emeltchenko 	default:
124468a8aea4SAndrei Emeltchenko 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
124568a8aea4SAndrei Emeltchenko 		break;
124635815085SAndre Guedes 	}
1247eb9d91f5SAndre Guedes }
1248eb9d91f5SAndre Guedes 
1249a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
1250a7a595f6SVinicius Costa Gomes {
1251a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
1252a7a595f6SVinicius Costa Gomes 
12539f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1254a7a595f6SVinicius Costa Gomes 
1255a7a595f6SVinicius Costa Gomes 	if (rp->status)
1256a7a595f6SVinicius Costa Gomes 		return;
1257a7a595f6SVinicius Costa Gomes 
1258a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
1259a7a595f6SVinicius Costa Gomes }
1260a7a595f6SVinicius Costa Gomes 
1261a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
1262a7a595f6SVinicius Costa Gomes {
1263a7a595f6SVinicius Costa Gomes 	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
1264a7a595f6SVinicius Costa Gomes 
12659f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1266a7a595f6SVinicius Costa Gomes 
1267a7a595f6SVinicius Costa Gomes 	if (rp->status)
1268a7a595f6SVinicius Costa Gomes 		return;
1269a7a595f6SVinicius Costa Gomes 
1270a7a595f6SVinicius Costa Gomes 	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
1271a7a595f6SVinicius Costa Gomes }
1272a7a595f6SVinicius Costa Gomes 
12736039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
1274f9b49306SAndre Guedes 					   struct sk_buff *skb)
1275f9b49306SAndre Guedes {
127606199cf8SJohan Hedberg 	struct hci_cp_write_le_host_supported *sent;
1277f9b49306SAndre Guedes 	__u8 status = *((__u8 *) skb->data);
1278f9b49306SAndre Guedes 
12799f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1280f9b49306SAndre Guedes 
128106199cf8SJohan Hedberg 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
12828f984dfaSJohan Hedberg 	if (!sent)
1283f9b49306SAndre Guedes 		return;
1284f9b49306SAndre Guedes 
12858f984dfaSJohan Hedberg 	if (!status) {
12868f984dfaSJohan Hedberg 		if (sent->le)
12878f984dfaSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE;
12888f984dfaSJohan Hedberg 		else
12898f984dfaSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE;
129053b2caabSJohan Hedberg 
129153b2caabSJohan Hedberg 		if (sent->simul)
129253b2caabSJohan Hedberg 			hdev->host_features[0] |= LMP_HOST_LE_BREDR;
129353b2caabSJohan Hedberg 		else
129453b2caabSJohan Hedberg 			hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
12958f984dfaSJohan Hedberg 	}
12968f984dfaSJohan Hedberg 
12978f984dfaSJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
12988f984dfaSJohan Hedberg 	    !test_bit(HCI_INIT, &hdev->flags))
12998f984dfaSJohan Hedberg 		mgmt_le_enable_complete(hdev, sent->le, status);
13008f984dfaSJohan Hedberg 
13018f984dfaSJohan Hedberg 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
1302f9b49306SAndre Guedes }
1303f9b49306SAndre Guedes 
130493c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
130593c284eeSAndrei Emeltchenko 					  struct sk_buff *skb)
130693c284eeSAndrei Emeltchenko {
130793c284eeSAndrei Emeltchenko 	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
130893c284eeSAndrei Emeltchenko 
130993c284eeSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
131093c284eeSAndrei Emeltchenko 	       hdev->name, rp->status, rp->phy_handle);
131193c284eeSAndrei Emeltchenko 
131293c284eeSAndrei Emeltchenko 	if (rp->status)
131393c284eeSAndrei Emeltchenko 		return;
131493c284eeSAndrei Emeltchenko 
131593c284eeSAndrei Emeltchenko 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
131693c284eeSAndrei Emeltchenko }
131793c284eeSAndrei Emeltchenko 
13186039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
1319a9de9248SMarcel Holtmann {
13209f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1321a9de9248SMarcel Holtmann 
1322a9de9248SMarcel Holtmann 	if (status) {
132323bb5763SJohan Hedberg 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1324a9de9248SMarcel Holtmann 		hci_conn_check_pending(hdev);
132556e5cb86SJohan Hedberg 		hci_dev_lock(hdev);
1326a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
13277a135109SAndre Guedes 			mgmt_start_discovery_failed(hdev, status);
132856e5cb86SJohan Hedberg 		hci_dev_unlock(hdev);
1329314b2381SJohan Hedberg 		return;
1330314b2381SJohan Hedberg 	}
1331314b2381SJohan Hedberg 
133289352e7dSAndre Guedes 	set_bit(HCI_INQUIRY, &hdev->flags);
133389352e7dSAndre Guedes 
133456e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
1335343f935bSAndre Guedes 	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
133656e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
1337a9de9248SMarcel Holtmann }
1338a9de9248SMarcel Holtmann 
13396039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
13401da177e4SLinus Torvalds {
1341a9de9248SMarcel Holtmann 	struct hci_cp_create_conn *cp;
13421da177e4SLinus Torvalds 	struct hci_conn *conn;
13431da177e4SLinus Torvalds 
13449f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1345a9de9248SMarcel Holtmann 
1346a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
13471da177e4SLinus Torvalds 	if (!cp)
13481da177e4SLinus Torvalds 		return;
13491da177e4SLinus Torvalds 
13501da177e4SLinus Torvalds 	hci_dev_lock(hdev);
13511da177e4SLinus Torvalds 
13521da177e4SLinus Torvalds 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
13531da177e4SLinus Torvalds 
13546ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
13551da177e4SLinus Torvalds 
13561da177e4SLinus Torvalds 	if (status) {
13571da177e4SLinus Torvalds 		if (conn && conn->state == BT_CONNECT) {
13584c67bc74SMarcel Holtmann 			if (status != 0x0c || conn->attempt > 2) {
13591da177e4SLinus Torvalds 				conn->state = BT_CLOSED;
13601da177e4SLinus Torvalds 				hci_proto_connect_cfm(conn, status);
13611da177e4SLinus Torvalds 				hci_conn_del(conn);
13624c67bc74SMarcel Holtmann 			} else
13634c67bc74SMarcel Holtmann 				conn->state = BT_CONNECT2;
13641da177e4SLinus Torvalds 		}
13651da177e4SLinus Torvalds 	} else {
13661da177e4SLinus Torvalds 		if (!conn) {
13671da177e4SLinus Torvalds 			conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
13681da177e4SLinus Torvalds 			if (conn) {
1369a0c808b3SJohan Hedberg 				conn->out = true;
13701da177e4SLinus Torvalds 				conn->link_mode |= HCI_LM_MASTER;
13711da177e4SLinus Torvalds 			} else
1372893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
13731da177e4SLinus Torvalds 		}
13741da177e4SLinus Torvalds 	}
13751da177e4SLinus Torvalds 
13761da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
13771da177e4SLinus Torvalds }
13781da177e4SLinus Torvalds 
1379a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
13801da177e4SLinus Torvalds {
1381a9de9248SMarcel Holtmann 	struct hci_cp_add_sco *cp;
13821da177e4SLinus Torvalds 	struct hci_conn *acl, *sco;
13831da177e4SLinus Torvalds 	__u16 handle;
13841da177e4SLinus Torvalds 
13859f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1386b6a0dc82SMarcel Holtmann 
1387a9de9248SMarcel Holtmann 	if (!status)
1388a9de9248SMarcel Holtmann 		return;
1389a9de9248SMarcel Holtmann 
1390a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
13911da177e4SLinus Torvalds 	if (!cp)
1392a9de9248SMarcel Holtmann 		return;
13931da177e4SLinus Torvalds 
13941da177e4SLinus Torvalds 	handle = __le16_to_cpu(cp->handle);
13951da177e4SLinus Torvalds 
13969f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
13971da177e4SLinus Torvalds 
13981da177e4SLinus Torvalds 	hci_dev_lock(hdev);
13991da177e4SLinus Torvalds 
14001da177e4SLinus Torvalds 	acl = hci_conn_hash_lookup_handle(hdev, handle);
14015a08ecceSAndrei Emeltchenko 	if (acl) {
14025a08ecceSAndrei Emeltchenko 		sco = acl->link;
14035a08ecceSAndrei Emeltchenko 		if (sco) {
14041da177e4SLinus Torvalds 			sco->state = BT_CLOSED;
14051da177e4SLinus Torvalds 
14061da177e4SLinus Torvalds 			hci_proto_connect_cfm(sco, status);
14071da177e4SLinus Torvalds 			hci_conn_del(sco);
14081da177e4SLinus Torvalds 		}
14095a08ecceSAndrei Emeltchenko 	}
14101da177e4SLinus Torvalds 
14111da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
14121da177e4SLinus Torvalds }
14131da177e4SLinus Torvalds 
1414f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
1415f8558555SMarcel Holtmann {
1416f8558555SMarcel Holtmann 	struct hci_cp_auth_requested *cp;
1417f8558555SMarcel Holtmann 	struct hci_conn *conn;
1418f8558555SMarcel Holtmann 
14199f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1420f8558555SMarcel Holtmann 
1421f8558555SMarcel Holtmann 	if (!status)
1422f8558555SMarcel Holtmann 		return;
1423f8558555SMarcel Holtmann 
1424f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
1425f8558555SMarcel Holtmann 	if (!cp)
1426f8558555SMarcel Holtmann 		return;
1427f8558555SMarcel Holtmann 
1428f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1429f8558555SMarcel Holtmann 
1430f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1431f8558555SMarcel Holtmann 	if (conn) {
1432f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1433f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1434f8558555SMarcel Holtmann 			hci_conn_put(conn);
1435f8558555SMarcel Holtmann 		}
1436f8558555SMarcel Holtmann 	}
1437f8558555SMarcel Holtmann 
1438f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1439f8558555SMarcel Holtmann }
1440f8558555SMarcel Holtmann 
1441f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
1442f8558555SMarcel Holtmann {
1443f8558555SMarcel Holtmann 	struct hci_cp_set_conn_encrypt *cp;
1444f8558555SMarcel Holtmann 	struct hci_conn *conn;
1445f8558555SMarcel Holtmann 
14469f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1447f8558555SMarcel Holtmann 
1448f8558555SMarcel Holtmann 	if (!status)
1449f8558555SMarcel Holtmann 		return;
1450f8558555SMarcel Holtmann 
1451f8558555SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
1452f8558555SMarcel Holtmann 	if (!cp)
1453f8558555SMarcel Holtmann 		return;
1454f8558555SMarcel Holtmann 
1455f8558555SMarcel Holtmann 	hci_dev_lock(hdev);
1456f8558555SMarcel Holtmann 
1457f8558555SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1458f8558555SMarcel Holtmann 	if (conn) {
1459f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1460f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1461f8558555SMarcel Holtmann 			hci_conn_put(conn);
1462f8558555SMarcel Holtmann 		}
1463f8558555SMarcel Holtmann 	}
1464f8558555SMarcel Holtmann 
1465f8558555SMarcel Holtmann 	hci_dev_unlock(hdev);
1466f8558555SMarcel Holtmann }
1467f8558555SMarcel Holtmann 
1468127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev,
1469392599b9SJohan Hedberg 				    struct hci_conn *conn)
1470392599b9SJohan Hedberg {
1471392599b9SJohan Hedberg 	if (conn->state != BT_CONFIG || !conn->out)
1472392599b9SJohan Hedberg 		return 0;
1473392599b9SJohan Hedberg 
1474765c2a96SJohan Hedberg 	if (conn->pending_sec_level == BT_SECURITY_SDP)
1475392599b9SJohan Hedberg 		return 0;
1476392599b9SJohan Hedberg 
1477392599b9SJohan Hedberg 	/* Only request authentication for SSP connections or non-SSP
1478e9bf2bf0SVinicius Costa Gomes 	 * devices with sec_level HIGH or if MITM protection is requested */
1479807deac2SGustavo Padovan 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
1480807deac2SGustavo Padovan 	    conn->pending_sec_level != BT_SECURITY_HIGH)
1481392599b9SJohan Hedberg 		return 0;
1482392599b9SJohan Hedberg 
1483392599b9SJohan Hedberg 	return 1;
1484392599b9SJohan Hedberg }
1485392599b9SJohan Hedberg 
14866039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev,
148700abfe44SGustavo F. Padovan 				   struct inquiry_entry *e)
148830dc78e1SJohan Hedberg {
148930dc78e1SJohan Hedberg 	struct hci_cp_remote_name_req cp;
149030dc78e1SJohan Hedberg 
149130dc78e1SJohan Hedberg 	memset(&cp, 0, sizeof(cp));
149230dc78e1SJohan Hedberg 
149330dc78e1SJohan Hedberg 	bacpy(&cp.bdaddr, &e->data.bdaddr);
149430dc78e1SJohan Hedberg 	cp.pscan_rep_mode = e->data.pscan_rep_mode;
149530dc78e1SJohan Hedberg 	cp.pscan_mode = e->data.pscan_mode;
149630dc78e1SJohan Hedberg 	cp.clock_offset = e->data.clock_offset;
149730dc78e1SJohan Hedberg 
149830dc78e1SJohan Hedberg 	return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
149930dc78e1SJohan Hedberg }
150030dc78e1SJohan Hedberg 
1501b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev)
150230dc78e1SJohan Hedberg {
150330dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
150430dc78e1SJohan Hedberg 	struct inquiry_entry *e;
150530dc78e1SJohan Hedberg 
1506b644ba33SJohan Hedberg 	if (list_empty(&discov->resolve))
1507b644ba33SJohan Hedberg 		return false;
1508b644ba33SJohan Hedberg 
1509b644ba33SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
1510c810089cSRam Malovany 	if (!e)
1511c810089cSRam Malovany 		return false;
1512c810089cSRam Malovany 
1513b644ba33SJohan Hedberg 	if (hci_resolve_name(hdev, e) == 0) {
1514b644ba33SJohan Hedberg 		e->name_state = NAME_PENDING;
1515b644ba33SJohan Hedberg 		return true;
1516b644ba33SJohan Hedberg 	}
1517b644ba33SJohan Hedberg 
1518b644ba33SJohan Hedberg 	return false;
1519b644ba33SJohan Hedberg }
1520b644ba33SJohan Hedberg 
1521b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
1522b644ba33SJohan Hedberg 				   bdaddr_t *bdaddr, u8 *name, u8 name_len)
1523b644ba33SJohan Hedberg {
1524b644ba33SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
1525b644ba33SJohan Hedberg 	struct inquiry_entry *e;
1526b644ba33SJohan Hedberg 
1527b644ba33SJohan Hedberg 	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
152804124681SGustavo F. Padovan 		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
152904124681SGustavo F. Padovan 				      name_len, conn->dev_class);
1530b644ba33SJohan Hedberg 
1531b644ba33SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPED)
1532b644ba33SJohan Hedberg 		return;
1533b644ba33SJohan Hedberg 
153430dc78e1SJohan Hedberg 	if (discov->state == DISCOVERY_STOPPING)
153530dc78e1SJohan Hedberg 		goto discov_complete;
153630dc78e1SJohan Hedberg 
153730dc78e1SJohan Hedberg 	if (discov->state != DISCOVERY_RESOLVING)
153830dc78e1SJohan Hedberg 		return;
153930dc78e1SJohan Hedberg 
154030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
15417cc8380eSRam Malovany 	/* If the device was not found in a list of found devices names of which
15427cc8380eSRam Malovany 	 * are pending. there is no need to continue resolving a next name as it
15437cc8380eSRam Malovany 	 * will be done upon receiving another Remote Name Request Complete
15447cc8380eSRam Malovany 	 * Event */
15457cc8380eSRam Malovany 	if (!e)
15467cc8380eSRam Malovany 		return;
15477cc8380eSRam Malovany 
154830dc78e1SJohan Hedberg 	list_del(&e->list);
15497cc8380eSRam Malovany 	if (name) {
15507cc8380eSRam Malovany 		e->name_state = NAME_KNOWN;
1551b644ba33SJohan Hedberg 		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
1552b644ba33SJohan Hedberg 				 e->data.rssi, name, name_len);
1553c3e7c0d9SRam Malovany 	} else {
1554c3e7c0d9SRam Malovany 		e->name_state = NAME_NOT_KNOWN;
155530dc78e1SJohan Hedberg 	}
155630dc78e1SJohan Hedberg 
1557b644ba33SJohan Hedberg 	if (hci_resolve_next_name(hdev))
155830dc78e1SJohan Hedberg 		return;
155930dc78e1SJohan Hedberg 
156030dc78e1SJohan Hedberg discov_complete:
156130dc78e1SJohan Hedberg 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
156230dc78e1SJohan Hedberg }
156330dc78e1SJohan Hedberg 
1564a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
15651da177e4SLinus Torvalds {
1566127178d2SJohan Hedberg 	struct hci_cp_remote_name_req *cp;
1567127178d2SJohan Hedberg 	struct hci_conn *conn;
1568127178d2SJohan Hedberg 
15699f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1570127178d2SJohan Hedberg 
1571127178d2SJohan Hedberg 	/* If successful wait for the name req complete event before
1572127178d2SJohan Hedberg 	 * checking for the need to do authentication */
1573127178d2SJohan Hedberg 	if (!status)
1574127178d2SJohan Hedberg 		return;
1575127178d2SJohan Hedberg 
1576127178d2SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
1577127178d2SJohan Hedberg 	if (!cp)
1578127178d2SJohan Hedberg 		return;
1579127178d2SJohan Hedberg 
1580127178d2SJohan Hedberg 	hci_dev_lock(hdev);
1581127178d2SJohan Hedberg 
1582127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1583b644ba33SJohan Hedberg 
1584b644ba33SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
1585b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
1586b644ba33SJohan Hedberg 
158779c6c70cSJohan Hedberg 	if (!conn)
158879c6c70cSJohan Hedberg 		goto unlock;
158979c6c70cSJohan Hedberg 
159079c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
159179c6c70cSJohan Hedberg 		goto unlock;
159279c6c70cSJohan Hedberg 
159351a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
1594127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
1595127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
1596127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1597127178d2SJohan Hedberg 	}
1598127178d2SJohan Hedberg 
159979c6c70cSJohan Hedberg unlock:
1600127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
1601a9de9248SMarcel Holtmann }
16021da177e4SLinus Torvalds 
1603769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
1604769be974SMarcel Holtmann {
1605769be974SMarcel Holtmann 	struct hci_cp_read_remote_features *cp;
1606769be974SMarcel Holtmann 	struct hci_conn *conn;
1607769be974SMarcel Holtmann 
16089f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1609769be974SMarcel Holtmann 
1610769be974SMarcel Holtmann 	if (!status)
1611769be974SMarcel Holtmann 		return;
1612769be974SMarcel Holtmann 
1613769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
1614769be974SMarcel Holtmann 	if (!cp)
1615769be974SMarcel Holtmann 		return;
1616769be974SMarcel Holtmann 
1617769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1618769be974SMarcel Holtmann 
1619769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1620769be974SMarcel Holtmann 	if (conn) {
1621769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1622769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1623769be974SMarcel Holtmann 			hci_conn_put(conn);
1624769be974SMarcel Holtmann 		}
1625769be974SMarcel Holtmann 	}
1626769be974SMarcel Holtmann 
1627769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1628769be974SMarcel Holtmann }
1629769be974SMarcel Holtmann 
1630769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
1631769be974SMarcel Holtmann {
1632769be974SMarcel Holtmann 	struct hci_cp_read_remote_ext_features *cp;
1633769be974SMarcel Holtmann 	struct hci_conn *conn;
1634769be974SMarcel Holtmann 
16359f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1636769be974SMarcel Holtmann 
1637769be974SMarcel Holtmann 	if (!status)
1638769be974SMarcel Holtmann 		return;
1639769be974SMarcel Holtmann 
1640769be974SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
1641769be974SMarcel Holtmann 	if (!cp)
1642769be974SMarcel Holtmann 		return;
1643769be974SMarcel Holtmann 
1644769be974SMarcel Holtmann 	hci_dev_lock(hdev);
1645769be974SMarcel Holtmann 
1646769be974SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1647769be974SMarcel Holtmann 	if (conn) {
1648769be974SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
1649769be974SMarcel Holtmann 			hci_proto_connect_cfm(conn, status);
1650769be974SMarcel Holtmann 			hci_conn_put(conn);
1651769be974SMarcel Holtmann 		}
1652769be974SMarcel Holtmann 	}
1653769be974SMarcel Holtmann 
1654769be974SMarcel Holtmann 	hci_dev_unlock(hdev);
1655769be974SMarcel Holtmann }
1656769be974SMarcel Holtmann 
1657a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
1658a9de9248SMarcel Holtmann {
1659b6a0dc82SMarcel Holtmann 	struct hci_cp_setup_sync_conn *cp;
1660b6a0dc82SMarcel Holtmann 	struct hci_conn *acl, *sco;
1661b6a0dc82SMarcel Holtmann 	__u16 handle;
1662b6a0dc82SMarcel Holtmann 
16639f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1664b6a0dc82SMarcel Holtmann 
1665b6a0dc82SMarcel Holtmann 	if (!status)
1666b6a0dc82SMarcel Holtmann 		return;
1667b6a0dc82SMarcel Holtmann 
1668b6a0dc82SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
1669b6a0dc82SMarcel Holtmann 	if (!cp)
1670b6a0dc82SMarcel Holtmann 		return;
1671b6a0dc82SMarcel Holtmann 
1672b6a0dc82SMarcel Holtmann 	handle = __le16_to_cpu(cp->handle);
1673b6a0dc82SMarcel Holtmann 
16749f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
1675b6a0dc82SMarcel Holtmann 
1676b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
1677b6a0dc82SMarcel Holtmann 
1678b6a0dc82SMarcel Holtmann 	acl = hci_conn_hash_lookup_handle(hdev, handle);
16795a08ecceSAndrei Emeltchenko 	if (acl) {
16805a08ecceSAndrei Emeltchenko 		sco = acl->link;
16815a08ecceSAndrei Emeltchenko 		if (sco) {
1682b6a0dc82SMarcel Holtmann 			sco->state = BT_CLOSED;
1683b6a0dc82SMarcel Holtmann 
1684b6a0dc82SMarcel Holtmann 			hci_proto_connect_cfm(sco, status);
1685b6a0dc82SMarcel Holtmann 			hci_conn_del(sco);
1686b6a0dc82SMarcel Holtmann 		}
16875a08ecceSAndrei Emeltchenko 	}
1688b6a0dc82SMarcel Holtmann 
1689b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
1690a9de9248SMarcel Holtmann }
1691a9de9248SMarcel Holtmann 
1692a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
1693a9de9248SMarcel Holtmann {
1694a9de9248SMarcel Holtmann 	struct hci_cp_sniff_mode *cp;
169504837f64SMarcel Holtmann 	struct hci_conn *conn;
169604837f64SMarcel Holtmann 
16979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1698a9de9248SMarcel Holtmann 
1699a9de9248SMarcel Holtmann 	if (!status)
1700a9de9248SMarcel Holtmann 		return;
1701a9de9248SMarcel Holtmann 
1702a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
170304837f64SMarcel Holtmann 	if (!cp)
1704a9de9248SMarcel Holtmann 		return;
170504837f64SMarcel Holtmann 
170604837f64SMarcel Holtmann 	hci_dev_lock(hdev);
170704837f64SMarcel Holtmann 
170804837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1709e73439d8SMarcel Holtmann 	if (conn) {
171051a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
171104837f64SMarcel Holtmann 
171251a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1713e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1714e73439d8SMarcel Holtmann 	}
1715e73439d8SMarcel Holtmann 
171604837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
171704837f64SMarcel Holtmann }
171804837f64SMarcel Holtmann 
1719a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1720a9de9248SMarcel Holtmann {
1721a9de9248SMarcel Holtmann 	struct hci_cp_exit_sniff_mode *cp;
172204837f64SMarcel Holtmann 	struct hci_conn *conn;
172304837f64SMarcel Holtmann 
17249f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1725a9de9248SMarcel Holtmann 
1726a9de9248SMarcel Holtmann 	if (!status)
1727a9de9248SMarcel Holtmann 		return;
1728a9de9248SMarcel Holtmann 
1729a9de9248SMarcel Holtmann 	cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
173004837f64SMarcel Holtmann 	if (!cp)
1731a9de9248SMarcel Holtmann 		return;
173204837f64SMarcel Holtmann 
173304837f64SMarcel Holtmann 	hci_dev_lock(hdev);
173404837f64SMarcel Holtmann 
173504837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1736e73439d8SMarcel Holtmann 	if (conn) {
173751a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
173804837f64SMarcel Holtmann 
173951a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
1740e73439d8SMarcel Holtmann 			hci_sco_setup(conn, status);
1741e73439d8SMarcel Holtmann 	}
1742e73439d8SMarcel Holtmann 
174304837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
174404837f64SMarcel Holtmann }
174504837f64SMarcel Holtmann 
174688c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
174788c3df13SJohan Hedberg {
174888c3df13SJohan Hedberg 	struct hci_cp_disconnect *cp;
174988c3df13SJohan Hedberg 	struct hci_conn *conn;
175088c3df13SJohan Hedberg 
175188c3df13SJohan Hedberg 	if (!status)
175288c3df13SJohan Hedberg 		return;
175388c3df13SJohan Hedberg 
175488c3df13SJohan Hedberg 	cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
175588c3df13SJohan Hedberg 	if (!cp)
175688c3df13SJohan Hedberg 		return;
175788c3df13SJohan Hedberg 
175888c3df13SJohan Hedberg 	hci_dev_lock(hdev);
175988c3df13SJohan Hedberg 
176088c3df13SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
176188c3df13SJohan Hedberg 	if (conn)
176288c3df13SJohan Hedberg 		mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
176388c3df13SJohan Hedberg 				       conn->dst_type, status);
176488c3df13SJohan Hedberg 
176588c3df13SJohan Hedberg 	hci_dev_unlock(hdev);
176688c3df13SJohan Hedberg }
176788c3df13SJohan Hedberg 
1768fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1769fcd89c09SVille Tervo {
1770fcd89c09SVille Tervo 	struct hci_conn *conn;
1771fcd89c09SVille Tervo 
17729f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1773fcd89c09SVille Tervo 
1774f00a06acSAndre Guedes 	if (status) {
1775fcd89c09SVille Tervo 		hci_dev_lock(hdev);
1776fcd89c09SVille Tervo 
17770c95ab78SAndre Guedes 		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
1778f00a06acSAndre Guedes 		if (!conn) {
1779f00a06acSAndre Guedes 			hci_dev_unlock(hdev);
1780f00a06acSAndre Guedes 			return;
1781f00a06acSAndre Guedes 		}
1782fcd89c09SVille Tervo 
17836ed93dc6SAndrei Emeltchenko 		BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
1784fcd89c09SVille Tervo 
1785fcd89c09SVille Tervo 		conn->state = BT_CLOSED;
17860c95ab78SAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
1787328c9248SHemant Gupta 				    conn->dst_type, status);
1788fcd89c09SVille Tervo 		hci_proto_connect_cfm(conn, status);
1789fcd89c09SVille Tervo 		hci_conn_del(conn);
1790fcd89c09SVille Tervo 
1791fcd89c09SVille Tervo 		hci_dev_unlock(hdev);
1792fcd89c09SVille Tervo 	}
1793f00a06acSAndre Guedes }
1794fcd89c09SVille Tervo 
1795a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1796a7a595f6SVinicius Costa Gomes {
17979f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
1798a7a595f6SVinicius Costa Gomes }
1799a7a595f6SVinicius Costa Gomes 
1800a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1801a02226d6SAndrei Emeltchenko {
180293c284eeSAndrei Emeltchenko 	struct hci_cp_create_phy_link *cp;
180393c284eeSAndrei Emeltchenko 
1804a02226d6SAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
180593c284eeSAndrei Emeltchenko 
180693c284eeSAndrei Emeltchenko 	if (status)
180793c284eeSAndrei Emeltchenko 		return;
180893c284eeSAndrei Emeltchenko 
180993c284eeSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
181093c284eeSAndrei Emeltchenko 	if (!cp)
181193c284eeSAndrei Emeltchenko 		return;
181293c284eeSAndrei Emeltchenko 
181393c284eeSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
1814a02226d6SAndrei Emeltchenko }
1815a02226d6SAndrei Emeltchenko 
18160b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
18170b26ab9dSAndrei Emeltchenko {
18180b26ab9dSAndrei Emeltchenko 	struct hci_cp_accept_phy_link *cp;
18190b26ab9dSAndrei Emeltchenko 
18200b26ab9dSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18210b26ab9dSAndrei Emeltchenko 
18220b26ab9dSAndrei Emeltchenko 	if (status)
18230b26ab9dSAndrei Emeltchenko 		return;
18240b26ab9dSAndrei Emeltchenko 
18250b26ab9dSAndrei Emeltchenko 	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
18260b26ab9dSAndrei Emeltchenko 	if (!cp)
18270b26ab9dSAndrei Emeltchenko 		return;
18280b26ab9dSAndrei Emeltchenko 
18290b26ab9dSAndrei Emeltchenko 	amp_write_remote_assoc(hdev, cp->phy_handle);
18300b26ab9dSAndrei Emeltchenko }
18310b26ab9dSAndrei Emeltchenko 
18326039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
18331da177e4SLinus Torvalds {
18341da177e4SLinus Torvalds 	__u8 status = *((__u8 *) skb->data);
183530dc78e1SJohan Hedberg 	struct discovery_state *discov = &hdev->discovery;
183630dc78e1SJohan Hedberg 	struct inquiry_entry *e;
18371da177e4SLinus Torvalds 
18389f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
18391da177e4SLinus Torvalds 
184023bb5763SJohan Hedberg 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
18416bd57416SMarcel Holtmann 
1842a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
184389352e7dSAndre Guedes 
184489352e7dSAndre Guedes 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
184589352e7dSAndre Guedes 		return;
184689352e7dSAndre Guedes 
1847a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
184830dc78e1SJohan Hedberg 		return;
184930dc78e1SJohan Hedberg 
185056e5cb86SJohan Hedberg 	hci_dev_lock(hdev);
185130dc78e1SJohan Hedberg 
1852343f935bSAndre Guedes 	if (discov->state != DISCOVERY_FINDING)
185330dc78e1SJohan Hedberg 		goto unlock;
185430dc78e1SJohan Hedberg 
185530dc78e1SJohan Hedberg 	if (list_empty(&discov->resolve)) {
1856ff9ef578SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
185730dc78e1SJohan Hedberg 		goto unlock;
185830dc78e1SJohan Hedberg 	}
185930dc78e1SJohan Hedberg 
186030dc78e1SJohan Hedberg 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
186130dc78e1SJohan Hedberg 	if (e && hci_resolve_name(hdev, e) == 0) {
186230dc78e1SJohan Hedberg 		e->name_state = NAME_PENDING;
186330dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
186430dc78e1SJohan Hedberg 	} else {
186530dc78e1SJohan Hedberg 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
186630dc78e1SJohan Hedberg 	}
186730dc78e1SJohan Hedberg 
186830dc78e1SJohan Hedberg unlock:
186956e5cb86SJohan Hedberg 	hci_dev_unlock(hdev);
18701da177e4SLinus Torvalds }
18711da177e4SLinus Torvalds 
18726039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
18731da177e4SLinus Torvalds {
187445bb4bf0SMarcel Holtmann 	struct inquiry_data data;
1875a9de9248SMarcel Holtmann 	struct inquiry_info *info = (void *) (skb->data + 1);
18761da177e4SLinus Torvalds 	int num_rsp = *((__u8 *) skb->data);
18771da177e4SLinus Torvalds 
18781da177e4SLinus Torvalds 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
18791da177e4SLinus Torvalds 
188045bb4bf0SMarcel Holtmann 	if (!num_rsp)
188145bb4bf0SMarcel Holtmann 		return;
188245bb4bf0SMarcel Holtmann 
18831519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
18841519cc17SAndre Guedes 		return;
18851519cc17SAndre Guedes 
18861da177e4SLinus Torvalds 	hci_dev_lock(hdev);
188745bb4bf0SMarcel Holtmann 
1888e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
1889388fc8faSJohan Hedberg 		bool name_known, ssp;
18903175405bSJohan Hedberg 
18911da177e4SLinus Torvalds 		bacpy(&data.bdaddr, &info->bdaddr);
18921da177e4SLinus Torvalds 		data.pscan_rep_mode	= info->pscan_rep_mode;
18931da177e4SLinus Torvalds 		data.pscan_period_mode	= info->pscan_period_mode;
18941da177e4SLinus Torvalds 		data.pscan_mode		= info->pscan_mode;
18951da177e4SLinus Torvalds 		memcpy(data.dev_class, info->dev_class, 3);
18961da177e4SLinus Torvalds 		data.clock_offset	= info->clock_offset;
18971da177e4SLinus Torvalds 		data.rssi		= 0x00;
189841a96212SMarcel Holtmann 		data.ssp_mode		= 0x00;
18993175405bSJohan Hedberg 
1900388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
190148264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
190204124681SGustavo F. Padovan 				  info->dev_class, 0, !name_known, ssp, NULL,
190304124681SGustavo F. Padovan 				  0);
19041da177e4SLinus Torvalds 	}
190545bb4bf0SMarcel Holtmann 
19061da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
19071da177e4SLinus Torvalds }
19081da177e4SLinus Torvalds 
19096039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
19101da177e4SLinus Torvalds {
1911a9de9248SMarcel Holtmann 	struct hci_ev_conn_complete *ev = (void *) skb->data;
1912a9de9248SMarcel Holtmann 	struct hci_conn *conn;
19131da177e4SLinus Torvalds 
1914a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
191545bb4bf0SMarcel Holtmann 
19161da177e4SLinus Torvalds 	hci_dev_lock(hdev);
191745bb4bf0SMarcel Holtmann 
1918a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
19199499237aSMarcel Holtmann 	if (!conn) {
19209499237aSMarcel Holtmann 		if (ev->link_type != SCO_LINK)
19219499237aSMarcel Holtmann 			goto unlock;
19229499237aSMarcel Holtmann 
19239499237aSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
1924a9de9248SMarcel Holtmann 		if (!conn)
1925a9de9248SMarcel Holtmann 			goto unlock;
192645bb4bf0SMarcel Holtmann 
19279499237aSMarcel Holtmann 		conn->type = SCO_LINK;
19289499237aSMarcel Holtmann 	}
19299499237aSMarcel Holtmann 
1930a9de9248SMarcel Holtmann 	if (!ev->status) {
1931a9de9248SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
1932769be974SMarcel Holtmann 
1933769be974SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1934769be974SMarcel Holtmann 			conn->state = BT_CONFIG;
1935769be974SMarcel Holtmann 			hci_conn_hold(conn);
1936a9ea3ed9SSzymon Janc 
1937a9ea3ed9SSzymon Janc 			if (!conn->out && !hci_conn_ssp_enabled(conn) &&
1938a9ea3ed9SSzymon Janc 			    !hci_find_link_key(hdev, &ev->bdaddr))
1939a9ea3ed9SSzymon Janc 				conn->disc_timeout = HCI_PAIRING_TIMEOUT;
1940a9ea3ed9SSzymon Janc 			else
1941052b30b0SMarcel Holtmann 				conn->disc_timeout = HCI_DISCONN_TIMEOUT;
1942769be974SMarcel Holtmann 		} else
1943a9de9248SMarcel Holtmann 			conn->state = BT_CONNECTED;
1944a9de9248SMarcel Holtmann 
19459eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
19467d0db0a3SMarcel Holtmann 		hci_conn_add_sysfs(conn);
19477d0db0a3SMarcel Holtmann 
1948a9de9248SMarcel Holtmann 		if (test_bit(HCI_AUTH, &hdev->flags))
1949a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
1950a9de9248SMarcel Holtmann 
1951a9de9248SMarcel Holtmann 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
1952a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_ENCRYPT;
1953a9de9248SMarcel Holtmann 
1954a9de9248SMarcel Holtmann 		/* Get remote features */
1955a9de9248SMarcel Holtmann 		if (conn->type == ACL_LINK) {
1956a9de9248SMarcel Holtmann 			struct hci_cp_read_remote_features cp;
1957a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1958769be974SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
1959769be974SMarcel Holtmann 				     sizeof(cp), &cp);
196045bb4bf0SMarcel Holtmann 		}
1961a9de9248SMarcel Holtmann 
1962a9de9248SMarcel Holtmann 		/* Set packet type for incoming connection */
1963d095c1ebSAndrei Emeltchenko 		if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
1964a9de9248SMarcel Holtmann 			struct hci_cp_change_conn_ptype cp;
1965a9de9248SMarcel Holtmann 			cp.handle = ev->handle;
1966a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
196704124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
196804124681SGustavo F. Padovan 				     &cp);
1969a9de9248SMarcel Holtmann 		}
197017d5c04cSJohan Hedberg 	} else {
1971a9de9248SMarcel Holtmann 		conn->state = BT_CLOSED;
197217d5c04cSJohan Hedberg 		if (conn->type == ACL_LINK)
1973744cf19eSJohan Hedberg 			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
197448264f06SJohan Hedberg 					    conn->dst_type, ev->status);
197517d5c04cSJohan Hedberg 	}
197645bb4bf0SMarcel Holtmann 
1977e73439d8SMarcel Holtmann 	if (conn->type == ACL_LINK)
1978e73439d8SMarcel Holtmann 		hci_sco_setup(conn, ev->status);
197945bb4bf0SMarcel Holtmann 
1980769be974SMarcel Holtmann 	if (ev->status) {
1981a9de9248SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1982a9de9248SMarcel Holtmann 		hci_conn_del(conn);
1983c89b6e6bSMarcel Holtmann 	} else if (ev->link_type != ACL_LINK)
1984c89b6e6bSMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
1985a9de9248SMarcel Holtmann 
1986a9de9248SMarcel Holtmann unlock:
19871da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
1988a9de9248SMarcel Holtmann 
1989a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
19901da177e4SLinus Torvalds }
19911da177e4SLinus Torvalds 
19926039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
19931da177e4SLinus Torvalds {
1994a9de9248SMarcel Holtmann 	struct hci_ev_conn_request *ev = (void *) skb->data;
19951da177e4SLinus Torvalds 	int mask = hdev->link_mode;
19961da177e4SLinus Torvalds 
19976ed93dc6SAndrei Emeltchenko 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
1998807deac2SGustavo Padovan 	       ev->link_type);
19991da177e4SLinus Torvalds 
20001da177e4SLinus Torvalds 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
20011da177e4SLinus Torvalds 
2002138d22efSSzymon Janc 	if ((mask & HCI_LM_ACCEPT) &&
2003138d22efSSzymon Janc 	    !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
20041da177e4SLinus Torvalds 		/* Connection accepted */
2005c7bdd502SMarcel Holtmann 		struct inquiry_entry *ie;
20061da177e4SLinus Torvalds 		struct hci_conn *conn;
20071da177e4SLinus Torvalds 
20081da177e4SLinus Torvalds 		hci_dev_lock(hdev);
2009b6a0dc82SMarcel Holtmann 
2010cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
2011cc11b9c1SAndrei Emeltchenko 		if (ie)
2012c7bdd502SMarcel Holtmann 			memcpy(ie->data.dev_class, ev->dev_class, 3);
2013c7bdd502SMarcel Holtmann 
20148fc9ced3SGustavo Padovan 		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
20158fc9ced3SGustavo Padovan 					       &ev->bdaddr);
20161da177e4SLinus Torvalds 		if (!conn) {
2017cc11b9c1SAndrei Emeltchenko 			conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
2018cc11b9c1SAndrei Emeltchenko 			if (!conn) {
2019893ef971SGustavo F. Padovan 				BT_ERR("No memory for new connection");
20201da177e4SLinus Torvalds 				hci_dev_unlock(hdev);
20211da177e4SLinus Torvalds 				return;
20221da177e4SLinus Torvalds 			}
20231da177e4SLinus Torvalds 		}
2024b6a0dc82SMarcel Holtmann 
20251da177e4SLinus Torvalds 		memcpy(conn->dev_class, ev->dev_class, 3);
20261da177e4SLinus Torvalds 		conn->state = BT_CONNECT;
2027b6a0dc82SMarcel Holtmann 
20281da177e4SLinus Torvalds 		hci_dev_unlock(hdev);
20291da177e4SLinus Torvalds 
2030b6a0dc82SMarcel Holtmann 		if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
2031b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_conn_req cp;
2032b6a0dc82SMarcel Holtmann 
20331da177e4SLinus Torvalds 			bacpy(&cp.bdaddr, &ev->bdaddr);
20341da177e4SLinus Torvalds 
20351da177e4SLinus Torvalds 			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
20361da177e4SLinus Torvalds 				cp.role = 0x00; /* Become master */
20371da177e4SLinus Torvalds 			else
20381da177e4SLinus Torvalds 				cp.role = 0x01; /* Remain slave */
20391da177e4SLinus Torvalds 
204004124681SGustavo F. Padovan 			hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
204104124681SGustavo F. Padovan 				     &cp);
2042b6a0dc82SMarcel Holtmann 		} else {
2043b6a0dc82SMarcel Holtmann 			struct hci_cp_accept_sync_conn_req cp;
2044b6a0dc82SMarcel Holtmann 
2045b6a0dc82SMarcel Holtmann 			bacpy(&cp.bdaddr, &ev->bdaddr);
2046a8746417SMarcel Holtmann 			cp.pkt_type = cpu_to_le16(conn->pkt_type);
2047b6a0dc82SMarcel Holtmann 
204882781e63SAndrei Emeltchenko 			cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
204982781e63SAndrei Emeltchenko 			cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
205082781e63SAndrei Emeltchenko 			cp.max_latency    = __constant_cpu_to_le16(0xffff);
2051b6a0dc82SMarcel Holtmann 			cp.content_format = cpu_to_le16(hdev->voice_setting);
2052b6a0dc82SMarcel Holtmann 			cp.retrans_effort = 0xff;
2053b6a0dc82SMarcel Holtmann 
2054b6a0dc82SMarcel Holtmann 			hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2055b6a0dc82SMarcel Holtmann 				     sizeof(cp), &cp);
2056b6a0dc82SMarcel Holtmann 		}
20571da177e4SLinus Torvalds 	} else {
20581da177e4SLinus Torvalds 		/* Connection rejected */
20591da177e4SLinus Torvalds 		struct hci_cp_reject_conn_req cp;
20601da177e4SLinus Torvalds 
20611da177e4SLinus Torvalds 		bacpy(&cp.bdaddr, &ev->bdaddr);
20629f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_REJ_BAD_ADDR;
2063a9de9248SMarcel Holtmann 		hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
20641da177e4SLinus Torvalds 	}
20651da177e4SLinus Torvalds }
20661da177e4SLinus Torvalds 
2067f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err)
2068f0d6a0eaSMikel Astiz {
2069f0d6a0eaSMikel Astiz 	switch (err) {
2070f0d6a0eaSMikel Astiz 	case HCI_ERROR_CONNECTION_TIMEOUT:
2071f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_TIMEOUT;
2072f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_USER_TERM:
2073f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_LOW_RESOURCES:
2074f0d6a0eaSMikel Astiz 	case HCI_ERROR_REMOTE_POWER_OFF:
2075f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_REMOTE;
2076f0d6a0eaSMikel Astiz 	case HCI_ERROR_LOCAL_HOST_TERM:
2077f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_LOCAL_HOST;
2078f0d6a0eaSMikel Astiz 	default:
2079f0d6a0eaSMikel Astiz 		return MGMT_DEV_DISCONN_UNKNOWN;
2080f0d6a0eaSMikel Astiz 	}
2081f0d6a0eaSMikel Astiz }
2082f0d6a0eaSMikel Astiz 
20836039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
20841da177e4SLinus Torvalds {
2085a9de9248SMarcel Holtmann 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
208604837f64SMarcel Holtmann 	struct hci_conn *conn;
20871da177e4SLinus Torvalds 
20889f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
20891da177e4SLinus Torvalds 
20901da177e4SLinus Torvalds 	hci_dev_lock(hdev);
20911da177e4SLinus Torvalds 
209204837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2093f7520543SJohan Hedberg 	if (!conn)
2094f7520543SJohan Hedberg 		goto unlock;
2095f7520543SJohan Hedberg 
209637d9ef76SJohan Hedberg 	if (ev->status == 0)
20971da177e4SLinus Torvalds 		conn->state = BT_CLOSED;
20987d0db0a3SMarcel Holtmann 
2099b644ba33SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
2100b644ba33SJohan Hedberg 	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
2101f0d6a0eaSMikel Astiz 		if (ev->status) {
210288c3df13SJohan Hedberg 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
210388c3df13SJohan Hedberg 					       conn->dst_type, ev->status);
2104f0d6a0eaSMikel Astiz 		} else {
2105f0d6a0eaSMikel Astiz 			u8 reason = hci_to_mgmt_reason(ev->reason);
2106f0d6a0eaSMikel Astiz 
2107afc747a6SJohan Hedberg 			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
2108f0d6a0eaSMikel Astiz 						 conn->dst_type, reason);
2109f0d6a0eaSMikel Astiz 		}
211037d9ef76SJohan Hedberg 	}
2111f7520543SJohan Hedberg 
211237d9ef76SJohan Hedberg 	if (ev->status == 0) {
21136ec5bcadSVishal Agarwal 		if (conn->type == ACL_LINK && conn->flush_key)
21146ec5bcadSVishal Agarwal 			hci_remove_link_key(hdev, &conn->dst);
21152950f21aSMarcel Holtmann 		hci_proto_disconn_cfm(conn, ev->reason);
21161da177e4SLinus Torvalds 		hci_conn_del(conn);
211737d9ef76SJohan Hedberg 	}
21181da177e4SLinus Torvalds 
2119f7520543SJohan Hedberg unlock:
21201da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
21211da177e4SLinus Torvalds }
21221da177e4SLinus Torvalds 
21236039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2124a9de9248SMarcel Holtmann {
2125a9de9248SMarcel Holtmann 	struct hci_ev_auth_complete *ev = (void *) skb->data;
2126a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2127a9de9248SMarcel Holtmann 
21289f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2129a9de9248SMarcel Holtmann 
2130a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2131a9de9248SMarcel Holtmann 
2132a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2133d7556e20SWaldemar Rymarkiewicz 	if (!conn)
2134d7556e20SWaldemar Rymarkiewicz 		goto unlock;
2135d7556e20SWaldemar Rymarkiewicz 
2136765c2a96SJohan Hedberg 	if (!ev->status) {
2137aa64a8b5SJohan Hedberg 		if (!hci_conn_ssp_enabled(conn) &&
213851a8efd7SJohan Hedberg 		    test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
2139d7556e20SWaldemar Rymarkiewicz 			BT_INFO("re-auth of legacy device is not possible.");
214019f8def0SWaldemar Rymarkiewicz 		} else {
2141a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_AUTH;
2142765c2a96SJohan Hedberg 			conn->sec_level = conn->pending_sec_level;
214319f8def0SWaldemar Rymarkiewicz 		}
21442a611692SJohan Hedberg 	} else {
2145bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
2146bab73cb6SJohan Hedberg 				 ev->status);
21472a611692SJohan Hedberg 	}
2148a9de9248SMarcel Holtmann 
214951a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
215051a8efd7SJohan Hedberg 	clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
2151a9de9248SMarcel Holtmann 
2152f8558555SMarcel Holtmann 	if (conn->state == BT_CONFIG) {
2153aa64a8b5SJohan Hedberg 		if (!ev->status && hci_conn_ssp_enabled(conn)) {
2154f8558555SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2155f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2156f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2157d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2158d7556e20SWaldemar Rymarkiewicz 				     &cp);
2159f8558555SMarcel Holtmann 		} else {
2160f8558555SMarcel Holtmann 			conn->state = BT_CONNECTED;
2161f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2162f8558555SMarcel Holtmann 			hci_conn_put(conn);
2163f8558555SMarcel Holtmann 		}
2164052b30b0SMarcel Holtmann 	} else {
2165a9de9248SMarcel Holtmann 		hci_auth_cfm(conn, ev->status);
2166a9de9248SMarcel Holtmann 
2167052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2168052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2169052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2170052b30b0SMarcel Holtmann 	}
2171052b30b0SMarcel Holtmann 
217251a8efd7SJohan Hedberg 	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
2173a9de9248SMarcel Holtmann 		if (!ev->status) {
2174a9de9248SMarcel Holtmann 			struct hci_cp_set_conn_encrypt cp;
2175f8558555SMarcel Holtmann 			cp.handle  = ev->handle;
2176f8558555SMarcel Holtmann 			cp.encrypt = 0x01;
2177d7556e20SWaldemar Rymarkiewicz 			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
2178d7556e20SWaldemar Rymarkiewicz 				     &cp);
2179a9de9248SMarcel Holtmann 		} else {
218051a8efd7SJohan Hedberg 			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2181a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, 0x00);
2182a9de9248SMarcel Holtmann 		}
2183a9de9248SMarcel Holtmann 	}
2184a9de9248SMarcel Holtmann 
2185d7556e20SWaldemar Rymarkiewicz unlock:
2186a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2187a9de9248SMarcel Holtmann }
2188a9de9248SMarcel Holtmann 
21896039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
2190a9de9248SMarcel Holtmann {
2191127178d2SJohan Hedberg 	struct hci_ev_remote_name *ev = (void *) skb->data;
2192127178d2SJohan Hedberg 	struct hci_conn *conn;
2193127178d2SJohan Hedberg 
2194a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2195a9de9248SMarcel Holtmann 
2196a9de9248SMarcel Holtmann 	hci_conn_check_pending(hdev);
2197127178d2SJohan Hedberg 
2198127178d2SJohan Hedberg 	hci_dev_lock(hdev);
2199127178d2SJohan Hedberg 
2200127178d2SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2201b644ba33SJohan Hedberg 
2202b644ba33SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
2203b644ba33SJohan Hedberg 		goto check_auth;
2204b644ba33SJohan Hedberg 
2205b644ba33SJohan Hedberg 	if (ev->status == 0)
2206b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
2207b644ba33SJohan Hedberg 				       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
2208b644ba33SJohan Hedberg 	else
2209b644ba33SJohan Hedberg 		hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
2210b644ba33SJohan Hedberg 
2211b644ba33SJohan Hedberg check_auth:
221279c6c70cSJohan Hedberg 	if (!conn)
221379c6c70cSJohan Hedberg 		goto unlock;
221479c6c70cSJohan Hedberg 
221579c6c70cSJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn))
221679c6c70cSJohan Hedberg 		goto unlock;
221779c6c70cSJohan Hedberg 
221851a8efd7SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
2219127178d2SJohan Hedberg 		struct hci_cp_auth_requested cp;
2220127178d2SJohan Hedberg 		cp.handle = __cpu_to_le16(conn->handle);
2221127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
2222127178d2SJohan Hedberg 	}
2223127178d2SJohan Hedberg 
222479c6c70cSJohan Hedberg unlock:
2225127178d2SJohan Hedberg 	hci_dev_unlock(hdev);
2226a9de9248SMarcel Holtmann }
2227a9de9248SMarcel Holtmann 
22286039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2229a9de9248SMarcel Holtmann {
2230a9de9248SMarcel Holtmann 	struct hci_ev_encrypt_change *ev = (void *) skb->data;
2231a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2232a9de9248SMarcel Holtmann 
22339f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2234a9de9248SMarcel Holtmann 
2235a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2236a9de9248SMarcel Holtmann 
2237a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2238a9de9248SMarcel Holtmann 	if (conn) {
2239a9de9248SMarcel Holtmann 		if (!ev->status) {
2240ae293196SMarcel Holtmann 			if (ev->encrypt) {
2241ae293196SMarcel Holtmann 				/* Encryption implies authentication */
2242ae293196SMarcel Holtmann 				conn->link_mode |= HCI_LM_AUTH;
2243a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_ENCRYPT;
2244da85e5e5SVinicius Costa Gomes 				conn->sec_level = conn->pending_sec_level;
2245ae293196SMarcel Holtmann 			} else
2246a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_ENCRYPT;
2247a9de9248SMarcel Holtmann 		}
2248a9de9248SMarcel Holtmann 
224951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
2250a9de9248SMarcel Holtmann 
2251a7d7723aSGustavo Padovan 		if (ev->status && conn->state == BT_CONNECTED) {
2252d839c813SGustavo Padovan 			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
2253a7d7723aSGustavo Padovan 			hci_conn_put(conn);
2254a7d7723aSGustavo Padovan 			goto unlock;
2255a7d7723aSGustavo Padovan 		}
2256a7d7723aSGustavo Padovan 
2257f8558555SMarcel Holtmann 		if (conn->state == BT_CONFIG) {
2258f8558555SMarcel Holtmann 			if (!ev->status)
2259f8558555SMarcel Holtmann 				conn->state = BT_CONNECTED;
2260f8558555SMarcel Holtmann 
2261f8558555SMarcel Holtmann 			hci_proto_connect_cfm(conn, ev->status);
2262f8558555SMarcel Holtmann 			hci_conn_put(conn);
2263f8558555SMarcel Holtmann 		} else
2264a9de9248SMarcel Holtmann 			hci_encrypt_cfm(conn, ev->status, ev->encrypt);
2265a9de9248SMarcel Holtmann 	}
2266a9de9248SMarcel Holtmann 
2267a7d7723aSGustavo Padovan unlock:
2268a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2269a9de9248SMarcel Holtmann }
2270a9de9248SMarcel Holtmann 
22716039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
2272807deac2SGustavo Padovan 					     struct sk_buff *skb)
2273a9de9248SMarcel Holtmann {
2274a9de9248SMarcel Holtmann 	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
2275a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2276a9de9248SMarcel Holtmann 
22779f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2278a9de9248SMarcel Holtmann 
2279a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2280a9de9248SMarcel Holtmann 
2281a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2282a9de9248SMarcel Holtmann 	if (conn) {
2283a9de9248SMarcel Holtmann 		if (!ev->status)
2284a9de9248SMarcel Holtmann 			conn->link_mode |= HCI_LM_SECURE;
2285a9de9248SMarcel Holtmann 
228651a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
2287a9de9248SMarcel Holtmann 
2288a9de9248SMarcel Holtmann 		hci_key_change_cfm(conn, ev->status);
2289a9de9248SMarcel Holtmann 	}
2290a9de9248SMarcel Holtmann 
2291a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2292a9de9248SMarcel Holtmann }
2293a9de9248SMarcel Holtmann 
22946039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev,
2295807deac2SGustavo Padovan 				    struct sk_buff *skb)
2296a9de9248SMarcel Holtmann {
2297a9de9248SMarcel Holtmann 	struct hci_ev_remote_features *ev = (void *) skb->data;
2298a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2299a9de9248SMarcel Holtmann 
23009f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2301a9de9248SMarcel Holtmann 
2302a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2303a9de9248SMarcel Holtmann 
2304a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2305ccd556feSJohan Hedberg 	if (!conn)
2306ccd556feSJohan Hedberg 		goto unlock;
2307ccd556feSJohan Hedberg 
2308769be974SMarcel Holtmann 	if (!ev->status)
2309a9de9248SMarcel Holtmann 		memcpy(conn->features, ev->features, 8);
2310a9de9248SMarcel Holtmann 
2311ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
2312ccd556feSJohan Hedberg 		goto unlock;
2313ccd556feSJohan Hedberg 
2314ccd556feSJohan Hedberg 	if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
2315769be974SMarcel Holtmann 		struct hci_cp_read_remote_ext_features cp;
2316769be974SMarcel Holtmann 		cp.handle = ev->handle;
2317769be974SMarcel Holtmann 		cp.page = 0x01;
2318ccd556feSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
2319769be974SMarcel Holtmann 			     sizeof(cp), &cp);
2320392599b9SJohan Hedberg 		goto unlock;
2321392599b9SJohan Hedberg 	}
2322392599b9SJohan Hedberg 
2323671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
2324127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
2325127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
2326127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
2327127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
2328127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
2329b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
2330b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
233108c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
2332b644ba33SJohan Hedberg 				      conn->dev_class);
2333392599b9SJohan Hedberg 
2334127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
2335769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
2336769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
2337769be974SMarcel Holtmann 		hci_conn_put(conn);
2338769be974SMarcel Holtmann 	}
2339769be974SMarcel Holtmann 
2340ccd556feSJohan Hedberg unlock:
2341a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2342a9de9248SMarcel Holtmann }
2343a9de9248SMarcel Holtmann 
23446039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
23456039aa73SGustavo Padovan {
23466039aa73SGustavo Padovan 	BT_DBG("%s", hdev->name);
23476039aa73SGustavo Padovan }
23486039aa73SGustavo Padovan 
23496039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2350807deac2SGustavo Padovan 				       struct sk_buff *skb)
2351a9de9248SMarcel Holtmann {
2352a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2353a9de9248SMarcel Holtmann }
2354a9de9248SMarcel Holtmann 
23556039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2356a9de9248SMarcel Holtmann {
2357a9de9248SMarcel Holtmann 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
2358a9de9248SMarcel Holtmann 	__u16 opcode;
2359a9de9248SMarcel Holtmann 
2360a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2361a9de9248SMarcel Holtmann 
2362a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2363a9de9248SMarcel Holtmann 
2364a9de9248SMarcel Holtmann 	switch (opcode) {
2365a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY_CANCEL:
2366a9de9248SMarcel Holtmann 		hci_cc_inquiry_cancel(hdev, skb);
2367a9de9248SMarcel Holtmann 		break;
2368a9de9248SMarcel Holtmann 
23694d93483bSAndre Guedes 	case HCI_OP_PERIODIC_INQ:
23704d93483bSAndre Guedes 		hci_cc_periodic_inq(hdev, skb);
23714d93483bSAndre Guedes 		break;
23724d93483bSAndre Guedes 
2373a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_PERIODIC_INQ:
2374a9de9248SMarcel Holtmann 		hci_cc_exit_periodic_inq(hdev, skb);
2375a9de9248SMarcel Holtmann 		break;
2376a9de9248SMarcel Holtmann 
2377a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
2378a9de9248SMarcel Holtmann 		hci_cc_remote_name_req_cancel(hdev, skb);
2379a9de9248SMarcel Holtmann 		break;
2380a9de9248SMarcel Holtmann 
2381a9de9248SMarcel Holtmann 	case HCI_OP_ROLE_DISCOVERY:
2382a9de9248SMarcel Holtmann 		hci_cc_role_discovery(hdev, skb);
2383a9de9248SMarcel Holtmann 		break;
2384a9de9248SMarcel Holtmann 
2385e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_LINK_POLICY:
2386e4e8e37cSMarcel Holtmann 		hci_cc_read_link_policy(hdev, skb);
2387e4e8e37cSMarcel Holtmann 		break;
2388e4e8e37cSMarcel Holtmann 
2389a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LINK_POLICY:
2390a9de9248SMarcel Holtmann 		hci_cc_write_link_policy(hdev, skb);
2391a9de9248SMarcel Holtmann 		break;
2392a9de9248SMarcel Holtmann 
2393e4e8e37cSMarcel Holtmann 	case HCI_OP_READ_DEF_LINK_POLICY:
2394e4e8e37cSMarcel Holtmann 		hci_cc_read_def_link_policy(hdev, skb);
2395e4e8e37cSMarcel Holtmann 		break;
2396e4e8e37cSMarcel Holtmann 
2397e4e8e37cSMarcel Holtmann 	case HCI_OP_WRITE_DEF_LINK_POLICY:
2398e4e8e37cSMarcel Holtmann 		hci_cc_write_def_link_policy(hdev, skb);
2399e4e8e37cSMarcel Holtmann 		break;
2400e4e8e37cSMarcel Holtmann 
2401a9de9248SMarcel Holtmann 	case HCI_OP_RESET:
2402a9de9248SMarcel Holtmann 		hci_cc_reset(hdev, skb);
2403a9de9248SMarcel Holtmann 		break;
2404a9de9248SMarcel Holtmann 
2405a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_LOCAL_NAME:
2406a9de9248SMarcel Holtmann 		hci_cc_write_local_name(hdev, skb);
2407a9de9248SMarcel Holtmann 		break;
2408a9de9248SMarcel Holtmann 
2409a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_NAME:
2410a9de9248SMarcel Holtmann 		hci_cc_read_local_name(hdev, skb);
2411a9de9248SMarcel Holtmann 		break;
2412a9de9248SMarcel Holtmann 
2413a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_AUTH_ENABLE:
2414a9de9248SMarcel Holtmann 		hci_cc_write_auth_enable(hdev, skb);
2415a9de9248SMarcel Holtmann 		break;
2416a9de9248SMarcel Holtmann 
2417a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_ENCRYPT_MODE:
2418a9de9248SMarcel Holtmann 		hci_cc_write_encrypt_mode(hdev, skb);
2419a9de9248SMarcel Holtmann 		break;
2420a9de9248SMarcel Holtmann 
2421a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_SCAN_ENABLE:
2422a9de9248SMarcel Holtmann 		hci_cc_write_scan_enable(hdev, skb);
2423a9de9248SMarcel Holtmann 		break;
2424a9de9248SMarcel Holtmann 
2425a9de9248SMarcel Holtmann 	case HCI_OP_READ_CLASS_OF_DEV:
2426a9de9248SMarcel Holtmann 		hci_cc_read_class_of_dev(hdev, skb);
2427a9de9248SMarcel Holtmann 		break;
2428a9de9248SMarcel Holtmann 
2429a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_CLASS_OF_DEV:
2430a9de9248SMarcel Holtmann 		hci_cc_write_class_of_dev(hdev, skb);
2431a9de9248SMarcel Holtmann 		break;
2432a9de9248SMarcel Holtmann 
2433a9de9248SMarcel Holtmann 	case HCI_OP_READ_VOICE_SETTING:
2434a9de9248SMarcel Holtmann 		hci_cc_read_voice_setting(hdev, skb);
2435a9de9248SMarcel Holtmann 		break;
2436a9de9248SMarcel Holtmann 
2437a9de9248SMarcel Holtmann 	case HCI_OP_WRITE_VOICE_SETTING:
2438a9de9248SMarcel Holtmann 		hci_cc_write_voice_setting(hdev, skb);
2439a9de9248SMarcel Holtmann 		break;
2440a9de9248SMarcel Holtmann 
2441a9de9248SMarcel Holtmann 	case HCI_OP_HOST_BUFFER_SIZE:
2442a9de9248SMarcel Holtmann 		hci_cc_host_buffer_size(hdev, skb);
2443a9de9248SMarcel Holtmann 		break;
2444a9de9248SMarcel Holtmann 
2445333140b5SMarcel Holtmann 	case HCI_OP_WRITE_SSP_MODE:
2446333140b5SMarcel Holtmann 		hci_cc_write_ssp_mode(hdev, skb);
2447333140b5SMarcel Holtmann 		break;
2448333140b5SMarcel Holtmann 
2449a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_VERSION:
2450a9de9248SMarcel Holtmann 		hci_cc_read_local_version(hdev, skb);
2451a9de9248SMarcel Holtmann 		break;
2452a9de9248SMarcel Holtmann 
2453a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_COMMANDS:
2454a9de9248SMarcel Holtmann 		hci_cc_read_local_commands(hdev, skb);
2455a9de9248SMarcel Holtmann 		break;
2456a9de9248SMarcel Holtmann 
2457a9de9248SMarcel Holtmann 	case HCI_OP_READ_LOCAL_FEATURES:
2458a9de9248SMarcel Holtmann 		hci_cc_read_local_features(hdev, skb);
2459a9de9248SMarcel Holtmann 		break;
2460a9de9248SMarcel Holtmann 
2461971e3a4bSAndre Guedes 	case HCI_OP_READ_LOCAL_EXT_FEATURES:
2462971e3a4bSAndre Guedes 		hci_cc_read_local_ext_features(hdev, skb);
2463971e3a4bSAndre Guedes 		break;
2464971e3a4bSAndre Guedes 
2465a9de9248SMarcel Holtmann 	case HCI_OP_READ_BUFFER_SIZE:
2466a9de9248SMarcel Holtmann 		hci_cc_read_buffer_size(hdev, skb);
2467a9de9248SMarcel Holtmann 		break;
2468a9de9248SMarcel Holtmann 
2469a9de9248SMarcel Holtmann 	case HCI_OP_READ_BD_ADDR:
2470a9de9248SMarcel Holtmann 		hci_cc_read_bd_addr(hdev, skb);
2471a9de9248SMarcel Holtmann 		break;
2472a9de9248SMarcel Holtmann 
2473350ee4cfSAndrei Emeltchenko 	case HCI_OP_READ_DATA_BLOCK_SIZE:
2474350ee4cfSAndrei Emeltchenko 		hci_cc_read_data_block_size(hdev, skb);
2475350ee4cfSAndrei Emeltchenko 		break;
2476350ee4cfSAndrei Emeltchenko 
247723bb5763SJohan Hedberg 	case HCI_OP_WRITE_CA_TIMEOUT:
247823bb5763SJohan Hedberg 		hci_cc_write_ca_timeout(hdev, skb);
247923bb5763SJohan Hedberg 		break;
248023bb5763SJohan Hedberg 
24811e89cffbSAndrei Emeltchenko 	case HCI_OP_READ_FLOW_CONTROL_MODE:
24821e89cffbSAndrei Emeltchenko 		hci_cc_read_flow_control_mode(hdev, skb);
24831e89cffbSAndrei Emeltchenko 		break;
24841e89cffbSAndrei Emeltchenko 
2485928abaa7SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_INFO:
2486928abaa7SAndrei Emeltchenko 		hci_cc_read_local_amp_info(hdev, skb);
2487928abaa7SAndrei Emeltchenko 		break;
2488928abaa7SAndrei Emeltchenko 
2489903e4541SAndrei Emeltchenko 	case HCI_OP_READ_LOCAL_AMP_ASSOC:
2490903e4541SAndrei Emeltchenko 		hci_cc_read_local_amp_assoc(hdev, skb);
2491903e4541SAndrei Emeltchenko 		break;
2492903e4541SAndrei Emeltchenko 
2493b0916ea0SJohan Hedberg 	case HCI_OP_DELETE_STORED_LINK_KEY:
2494b0916ea0SJohan Hedberg 		hci_cc_delete_stored_link_key(hdev, skb);
2495b0916ea0SJohan Hedberg 		break;
2496b0916ea0SJohan Hedberg 
2497d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_MASK:
2498d5859e22SJohan Hedberg 		hci_cc_set_event_mask(hdev, skb);
2499d5859e22SJohan Hedberg 		break;
2500d5859e22SJohan Hedberg 
2501d5859e22SJohan Hedberg 	case HCI_OP_WRITE_INQUIRY_MODE:
2502d5859e22SJohan Hedberg 		hci_cc_write_inquiry_mode(hdev, skb);
2503d5859e22SJohan Hedberg 		break;
2504d5859e22SJohan Hedberg 
2505d5859e22SJohan Hedberg 	case HCI_OP_READ_INQ_RSP_TX_POWER:
2506d5859e22SJohan Hedberg 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
2507d5859e22SJohan Hedberg 		break;
2508d5859e22SJohan Hedberg 
2509d5859e22SJohan Hedberg 	case HCI_OP_SET_EVENT_FLT:
2510d5859e22SJohan Hedberg 		hci_cc_set_event_flt(hdev, skb);
2511d5859e22SJohan Hedberg 		break;
2512d5859e22SJohan Hedberg 
2513980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_REPLY:
2514980e1a53SJohan Hedberg 		hci_cc_pin_code_reply(hdev, skb);
2515980e1a53SJohan Hedberg 		break;
2516980e1a53SJohan Hedberg 
2517980e1a53SJohan Hedberg 	case HCI_OP_PIN_CODE_NEG_REPLY:
2518980e1a53SJohan Hedberg 		hci_cc_pin_code_neg_reply(hdev, skb);
2519980e1a53SJohan Hedberg 		break;
2520980e1a53SJohan Hedberg 
2521c35938b2SSzymon Janc 	case HCI_OP_READ_LOCAL_OOB_DATA:
2522c35938b2SSzymon Janc 		hci_cc_read_local_oob_data_reply(hdev, skb);
2523c35938b2SSzymon Janc 		break;
2524c35938b2SSzymon Janc 
25256ed58ec5SVille Tervo 	case HCI_OP_LE_READ_BUFFER_SIZE:
25266ed58ec5SVille Tervo 		hci_cc_le_read_buffer_size(hdev, skb);
25276ed58ec5SVille Tervo 		break;
25286ed58ec5SVille Tervo 
25298fa19098SJohan Hedberg 	case HCI_OP_LE_READ_ADV_TX_POWER:
25308fa19098SJohan Hedberg 		hci_cc_le_read_adv_tx_power(hdev, skb);
25318fa19098SJohan Hedberg 		break;
25328fa19098SJohan Hedberg 
2533e36b04c8SJohan Hedberg 	case HCI_OP_LE_SET_EVENT_MASK:
2534e36b04c8SJohan Hedberg 		hci_cc_le_set_event_mask(hdev, skb);
2535e36b04c8SJohan Hedberg 		break;
2536e36b04c8SJohan Hedberg 
2537a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_REPLY:
2538a5c29683SJohan Hedberg 		hci_cc_user_confirm_reply(hdev, skb);
2539a5c29683SJohan Hedberg 		break;
2540a5c29683SJohan Hedberg 
2541a5c29683SJohan Hedberg 	case HCI_OP_USER_CONFIRM_NEG_REPLY:
2542a5c29683SJohan Hedberg 		hci_cc_user_confirm_neg_reply(hdev, skb);
2543a5c29683SJohan Hedberg 		break;
2544a5c29683SJohan Hedberg 
25451143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_REPLY:
25461143d458SBrian Gix 		hci_cc_user_passkey_reply(hdev, skb);
25471143d458SBrian Gix 		break;
25481143d458SBrian Gix 
25491143d458SBrian Gix 	case HCI_OP_USER_PASSKEY_NEG_REPLY:
25501143d458SBrian Gix 		hci_cc_user_passkey_neg_reply(hdev, skb);
255116cde993SSzymon Janc 		break;
255207f7fa5dSAndre Guedes 
255307f7fa5dSAndre Guedes 	case HCI_OP_LE_SET_SCAN_PARAM:
255407f7fa5dSAndre Guedes 		hci_cc_le_set_scan_param(hdev, skb);
25551143d458SBrian Gix 		break;
25561143d458SBrian Gix 
2557eb9d91f5SAndre Guedes 	case HCI_OP_LE_SET_SCAN_ENABLE:
2558eb9d91f5SAndre Guedes 		hci_cc_le_set_scan_enable(hdev, skb);
2559eb9d91f5SAndre Guedes 		break;
2560eb9d91f5SAndre Guedes 
2561a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_REPLY:
2562a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_reply(hdev, skb);
2563a7a595f6SVinicius Costa Gomes 		break;
2564a7a595f6SVinicius Costa Gomes 
2565a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_LTK_NEG_REPLY:
2566a7a595f6SVinicius Costa Gomes 		hci_cc_le_ltk_neg_reply(hdev, skb);
2567a7a595f6SVinicius Costa Gomes 		break;
2568a7a595f6SVinicius Costa Gomes 
2569f9b49306SAndre Guedes 	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
2570f9b49306SAndre Guedes 		hci_cc_write_le_host_supported(hdev, skb);
2571f9b49306SAndre Guedes 		break;
2572f9b49306SAndre Guedes 
257393c284eeSAndrei Emeltchenko 	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
257493c284eeSAndrei Emeltchenko 		hci_cc_write_remote_amp_assoc(hdev, skb);
257593c284eeSAndrei Emeltchenko 		break;
257693c284eeSAndrei Emeltchenko 
2577a9de9248SMarcel Holtmann 	default:
25789f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2579a9de9248SMarcel Holtmann 		break;
2580a9de9248SMarcel Holtmann 	}
2581a9de9248SMarcel Holtmann 
25826bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
25836bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
25846bd32326SVille Tervo 
2585a9de9248SMarcel Holtmann 	if (ev->ncmd) {
2586a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2587a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2588c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2589a9de9248SMarcel Holtmann 	}
2590a9de9248SMarcel Holtmann }
2591a9de9248SMarcel Holtmann 
25926039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2593a9de9248SMarcel Holtmann {
2594a9de9248SMarcel Holtmann 	struct hci_ev_cmd_status *ev = (void *) skb->data;
2595a9de9248SMarcel Holtmann 	__u16 opcode;
2596a9de9248SMarcel Holtmann 
2597a9de9248SMarcel Holtmann 	skb_pull(skb, sizeof(*ev));
2598a9de9248SMarcel Holtmann 
2599a9de9248SMarcel Holtmann 	opcode = __le16_to_cpu(ev->opcode);
2600a9de9248SMarcel Holtmann 
2601a9de9248SMarcel Holtmann 	switch (opcode) {
2602a9de9248SMarcel Holtmann 	case HCI_OP_INQUIRY:
2603a9de9248SMarcel Holtmann 		hci_cs_inquiry(hdev, ev->status);
2604a9de9248SMarcel Holtmann 		break;
2605a9de9248SMarcel Holtmann 
2606a9de9248SMarcel Holtmann 	case HCI_OP_CREATE_CONN:
2607a9de9248SMarcel Holtmann 		hci_cs_create_conn(hdev, ev->status);
2608a9de9248SMarcel Holtmann 		break;
2609a9de9248SMarcel Holtmann 
2610a9de9248SMarcel Holtmann 	case HCI_OP_ADD_SCO:
2611a9de9248SMarcel Holtmann 		hci_cs_add_sco(hdev, ev->status);
2612a9de9248SMarcel Holtmann 		break;
2613a9de9248SMarcel Holtmann 
2614f8558555SMarcel Holtmann 	case HCI_OP_AUTH_REQUESTED:
2615f8558555SMarcel Holtmann 		hci_cs_auth_requested(hdev, ev->status);
2616f8558555SMarcel Holtmann 		break;
2617f8558555SMarcel Holtmann 
2618f8558555SMarcel Holtmann 	case HCI_OP_SET_CONN_ENCRYPT:
2619f8558555SMarcel Holtmann 		hci_cs_set_conn_encrypt(hdev, ev->status);
2620f8558555SMarcel Holtmann 		break;
2621f8558555SMarcel Holtmann 
2622a9de9248SMarcel Holtmann 	case HCI_OP_REMOTE_NAME_REQ:
2623a9de9248SMarcel Holtmann 		hci_cs_remote_name_req(hdev, ev->status);
2624a9de9248SMarcel Holtmann 		break;
2625a9de9248SMarcel Holtmann 
2626769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_FEATURES:
2627769be974SMarcel Holtmann 		hci_cs_read_remote_features(hdev, ev->status);
2628769be974SMarcel Holtmann 		break;
2629769be974SMarcel Holtmann 
2630769be974SMarcel Holtmann 	case HCI_OP_READ_REMOTE_EXT_FEATURES:
2631769be974SMarcel Holtmann 		hci_cs_read_remote_ext_features(hdev, ev->status);
2632769be974SMarcel Holtmann 		break;
2633769be974SMarcel Holtmann 
2634a9de9248SMarcel Holtmann 	case HCI_OP_SETUP_SYNC_CONN:
2635a9de9248SMarcel Holtmann 		hci_cs_setup_sync_conn(hdev, ev->status);
2636a9de9248SMarcel Holtmann 		break;
2637a9de9248SMarcel Holtmann 
2638a9de9248SMarcel Holtmann 	case HCI_OP_SNIFF_MODE:
2639a9de9248SMarcel Holtmann 		hci_cs_sniff_mode(hdev, ev->status);
2640a9de9248SMarcel Holtmann 		break;
2641a9de9248SMarcel Holtmann 
2642a9de9248SMarcel Holtmann 	case HCI_OP_EXIT_SNIFF_MODE:
2643a9de9248SMarcel Holtmann 		hci_cs_exit_sniff_mode(hdev, ev->status);
2644a9de9248SMarcel Holtmann 		break;
2645a9de9248SMarcel Holtmann 
26468962ee74SJohan Hedberg 	case HCI_OP_DISCONNECT:
264788c3df13SJohan Hedberg 		hci_cs_disconnect(hdev, ev->status);
26488962ee74SJohan Hedberg 		break;
26498962ee74SJohan Hedberg 
2650fcd89c09SVille Tervo 	case HCI_OP_LE_CREATE_CONN:
2651fcd89c09SVille Tervo 		hci_cs_le_create_conn(hdev, ev->status);
2652fcd89c09SVille Tervo 		break;
2653fcd89c09SVille Tervo 
2654a7a595f6SVinicius Costa Gomes 	case HCI_OP_LE_START_ENC:
2655a7a595f6SVinicius Costa Gomes 		hci_cs_le_start_enc(hdev, ev->status);
2656a7a595f6SVinicius Costa Gomes 		break;
2657a7a595f6SVinicius Costa Gomes 
2658a02226d6SAndrei Emeltchenko 	case HCI_OP_CREATE_PHY_LINK:
2659a02226d6SAndrei Emeltchenko 		hci_cs_create_phylink(hdev, ev->status);
2660a02226d6SAndrei Emeltchenko 		break;
2661a02226d6SAndrei Emeltchenko 
26620b26ab9dSAndrei Emeltchenko 	case HCI_OP_ACCEPT_PHY_LINK:
26630b26ab9dSAndrei Emeltchenko 		hci_cs_accept_phylink(hdev, ev->status);
26640b26ab9dSAndrei Emeltchenko 		break;
26650b26ab9dSAndrei Emeltchenko 
2666a9de9248SMarcel Holtmann 	default:
26679f1db00cSAndrei Emeltchenko 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2668a9de9248SMarcel Holtmann 		break;
2669a9de9248SMarcel Holtmann 	}
2670a9de9248SMarcel Holtmann 
26716bd32326SVille Tervo 	if (ev->opcode != HCI_OP_NOP)
26726bd32326SVille Tervo 		del_timer(&hdev->cmd_timer);
26736bd32326SVille Tervo 
267410572132SGustavo F. Padovan 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2675a9de9248SMarcel Holtmann 		atomic_set(&hdev->cmd_cnt, 1);
2676a9de9248SMarcel Holtmann 		if (!skb_queue_empty(&hdev->cmd_q))
2677c347b765SGustavo F. Padovan 			queue_work(hdev->workqueue, &hdev->cmd_work);
2678a9de9248SMarcel Holtmann 	}
2679a9de9248SMarcel Holtmann }
2680a9de9248SMarcel Holtmann 
26816039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2682a9de9248SMarcel Holtmann {
2683a9de9248SMarcel Holtmann 	struct hci_ev_role_change *ev = (void *) skb->data;
2684a9de9248SMarcel Holtmann 	struct hci_conn *conn;
2685a9de9248SMarcel Holtmann 
26869f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
2687a9de9248SMarcel Holtmann 
2688a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
2689a9de9248SMarcel Holtmann 
2690a9de9248SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2691a9de9248SMarcel Holtmann 	if (conn) {
2692a9de9248SMarcel Holtmann 		if (!ev->status) {
2693a9de9248SMarcel Holtmann 			if (ev->role)
2694a9de9248SMarcel Holtmann 				conn->link_mode &= ~HCI_LM_MASTER;
2695a9de9248SMarcel Holtmann 			else
2696a9de9248SMarcel Holtmann 				conn->link_mode |= HCI_LM_MASTER;
2697a9de9248SMarcel Holtmann 		}
2698a9de9248SMarcel Holtmann 
269951a8efd7SJohan Hedberg 		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
2700a9de9248SMarcel Holtmann 
2701a9de9248SMarcel Holtmann 		hci_role_switch_cfm(conn, ev->status, ev->role);
2702a9de9248SMarcel Holtmann 	}
2703a9de9248SMarcel Holtmann 
2704a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
2705a9de9248SMarcel Holtmann }
2706a9de9248SMarcel Holtmann 
27076039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
27081da177e4SLinus Torvalds {
2709a9de9248SMarcel Holtmann 	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
27101da177e4SLinus Torvalds 	int i;
27111da177e4SLinus Torvalds 
271232ac5b9bSAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
271332ac5b9bSAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
271432ac5b9bSAndrei Emeltchenko 		return;
271532ac5b9bSAndrei Emeltchenko 	}
271632ac5b9bSAndrei Emeltchenko 
2717c5993de8SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2718c5993de8SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
27191da177e4SLinus Torvalds 		BT_DBG("%s bad parameters", hdev->name);
27201da177e4SLinus Torvalds 		return;
27211da177e4SLinus Torvalds 	}
27221da177e4SLinus Torvalds 
2723c5993de8SAndrei Emeltchenko 	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
2724c5993de8SAndrei Emeltchenko 
2725613a1c0cSAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
2726613a1c0cSAndrei Emeltchenko 		struct hci_comp_pkts_info *info = &ev->handles[i];
27271da177e4SLinus Torvalds 		struct hci_conn *conn;
27281da177e4SLinus Torvalds 		__u16  handle, count;
27291da177e4SLinus Torvalds 
2730613a1c0cSAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
2731613a1c0cSAndrei Emeltchenko 		count  = __le16_to_cpu(info->count);
27321da177e4SLinus Torvalds 
27331da177e4SLinus Torvalds 		conn = hci_conn_hash_lookup_handle(hdev, handle);
2734f4280918SAndrei Emeltchenko 		if (!conn)
2735f4280918SAndrei Emeltchenko 			continue;
2736f4280918SAndrei Emeltchenko 
27371da177e4SLinus Torvalds 		conn->sent -= count;
27381da177e4SLinus Torvalds 
2739f4280918SAndrei Emeltchenko 		switch (conn->type) {
2740f4280918SAndrei Emeltchenko 		case ACL_LINK:
274170f23020SAndrei Emeltchenko 			hdev->acl_cnt += count;
274270f23020SAndrei Emeltchenko 			if (hdev->acl_cnt > hdev->acl_pkts)
27431da177e4SLinus Torvalds 				hdev->acl_cnt = hdev->acl_pkts;
2744f4280918SAndrei Emeltchenko 			break;
2745f4280918SAndrei Emeltchenko 
2746f4280918SAndrei Emeltchenko 		case LE_LINK:
27476ed58ec5SVille Tervo 			if (hdev->le_pkts) {
27486ed58ec5SVille Tervo 				hdev->le_cnt += count;
27496ed58ec5SVille Tervo 				if (hdev->le_cnt > hdev->le_pkts)
27506ed58ec5SVille Tervo 					hdev->le_cnt = hdev->le_pkts;
27516ed58ec5SVille Tervo 			} else {
27526ed58ec5SVille Tervo 				hdev->acl_cnt += count;
27536ed58ec5SVille Tervo 				if (hdev->acl_cnt > hdev->acl_pkts)
27546ed58ec5SVille Tervo 					hdev->acl_cnt = hdev->acl_pkts;
27556ed58ec5SVille Tervo 			}
2756f4280918SAndrei Emeltchenko 			break;
2757f4280918SAndrei Emeltchenko 
2758f4280918SAndrei Emeltchenko 		case SCO_LINK:
275970f23020SAndrei Emeltchenko 			hdev->sco_cnt += count;
276070f23020SAndrei Emeltchenko 			if (hdev->sco_cnt > hdev->sco_pkts)
27615b7f9909SMarcel Holtmann 				hdev->sco_cnt = hdev->sco_pkts;
2762f4280918SAndrei Emeltchenko 			break;
2763f4280918SAndrei Emeltchenko 
2764f4280918SAndrei Emeltchenko 		default:
2765f4280918SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
2766f4280918SAndrei Emeltchenko 			break;
27671da177e4SLinus Torvalds 		}
27681da177e4SLinus Torvalds 	}
2769a9de9248SMarcel Holtmann 
27703eff45eaSGustavo F. Padovan 	queue_work(hdev->workqueue, &hdev->tx_work);
27711da177e4SLinus Torvalds }
27721da177e4SLinus Torvalds 
277376ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
277476ef7cf7SAndrei Emeltchenko 						 __u16 handle)
277576ef7cf7SAndrei Emeltchenko {
277676ef7cf7SAndrei Emeltchenko 	struct hci_chan *chan;
277776ef7cf7SAndrei Emeltchenko 
277876ef7cf7SAndrei Emeltchenko 	switch (hdev->dev_type) {
277976ef7cf7SAndrei Emeltchenko 	case HCI_BREDR:
278076ef7cf7SAndrei Emeltchenko 		return hci_conn_hash_lookup_handle(hdev, handle);
278176ef7cf7SAndrei Emeltchenko 	case HCI_AMP:
278276ef7cf7SAndrei Emeltchenko 		chan = hci_chan_lookup_handle(hdev, handle);
278376ef7cf7SAndrei Emeltchenko 		if (chan)
278476ef7cf7SAndrei Emeltchenko 			return chan->conn;
278576ef7cf7SAndrei Emeltchenko 		break;
278676ef7cf7SAndrei Emeltchenko 	default:
278776ef7cf7SAndrei Emeltchenko 		BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
278876ef7cf7SAndrei Emeltchenko 		break;
278976ef7cf7SAndrei Emeltchenko 	}
279076ef7cf7SAndrei Emeltchenko 
279176ef7cf7SAndrei Emeltchenko 	return NULL;
279276ef7cf7SAndrei Emeltchenko }
279376ef7cf7SAndrei Emeltchenko 
27946039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
279525e89e99SAndrei Emeltchenko {
279625e89e99SAndrei Emeltchenko 	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
279725e89e99SAndrei Emeltchenko 	int i;
279825e89e99SAndrei Emeltchenko 
279925e89e99SAndrei Emeltchenko 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
280025e89e99SAndrei Emeltchenko 		BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
280125e89e99SAndrei Emeltchenko 		return;
280225e89e99SAndrei Emeltchenko 	}
280325e89e99SAndrei Emeltchenko 
280425e89e99SAndrei Emeltchenko 	if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
280525e89e99SAndrei Emeltchenko 	    ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
280625e89e99SAndrei Emeltchenko 		BT_DBG("%s bad parameters", hdev->name);
280725e89e99SAndrei Emeltchenko 		return;
280825e89e99SAndrei Emeltchenko 	}
280925e89e99SAndrei Emeltchenko 
281025e89e99SAndrei Emeltchenko 	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
281125e89e99SAndrei Emeltchenko 	       ev->num_hndl);
281225e89e99SAndrei Emeltchenko 
281325e89e99SAndrei Emeltchenko 	for (i = 0; i < ev->num_hndl; i++) {
281425e89e99SAndrei Emeltchenko 		struct hci_comp_blocks_info *info = &ev->handles[i];
281576ef7cf7SAndrei Emeltchenko 		struct hci_conn *conn = NULL;
281625e89e99SAndrei Emeltchenko 		__u16  handle, block_count;
281725e89e99SAndrei Emeltchenko 
281825e89e99SAndrei Emeltchenko 		handle = __le16_to_cpu(info->handle);
281925e89e99SAndrei Emeltchenko 		block_count = __le16_to_cpu(info->blocks);
282025e89e99SAndrei Emeltchenko 
282176ef7cf7SAndrei Emeltchenko 		conn = __hci_conn_lookup_handle(hdev, handle);
282225e89e99SAndrei Emeltchenko 		if (!conn)
282325e89e99SAndrei Emeltchenko 			continue;
282425e89e99SAndrei Emeltchenko 
282525e89e99SAndrei Emeltchenko 		conn->sent -= block_count;
282625e89e99SAndrei Emeltchenko 
282725e89e99SAndrei Emeltchenko 		switch (conn->type) {
282825e89e99SAndrei Emeltchenko 		case ACL_LINK:
2829bd1eb66bSAndrei Emeltchenko 		case AMP_LINK:
283025e89e99SAndrei Emeltchenko 			hdev->block_cnt += block_count;
283125e89e99SAndrei Emeltchenko 			if (hdev->block_cnt > hdev->num_blocks)
283225e89e99SAndrei Emeltchenko 				hdev->block_cnt = hdev->num_blocks;
283325e89e99SAndrei Emeltchenko 			break;
283425e89e99SAndrei Emeltchenko 
283525e89e99SAndrei Emeltchenko 		default:
283625e89e99SAndrei Emeltchenko 			BT_ERR("Unknown type %d conn %p", conn->type, conn);
283725e89e99SAndrei Emeltchenko 			break;
283825e89e99SAndrei Emeltchenko 		}
283925e89e99SAndrei Emeltchenko 	}
284025e89e99SAndrei Emeltchenko 
284125e89e99SAndrei Emeltchenko 	queue_work(hdev->workqueue, &hdev->tx_work);
284225e89e99SAndrei Emeltchenko }
284325e89e99SAndrei Emeltchenko 
28446039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
28451da177e4SLinus Torvalds {
2846a9de9248SMarcel Holtmann 	struct hci_ev_mode_change *ev = (void *) skb->data;
284704837f64SMarcel Holtmann 	struct hci_conn *conn;
28481da177e4SLinus Torvalds 
28499f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
28501da177e4SLinus Torvalds 
28511da177e4SLinus Torvalds 	hci_dev_lock(hdev);
28521da177e4SLinus Torvalds 
285304837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
285404837f64SMarcel Holtmann 	if (conn) {
285504837f64SMarcel Holtmann 		conn->mode = ev->mode;
285604837f64SMarcel Holtmann 		conn->interval = __le16_to_cpu(ev->interval);
285704837f64SMarcel Holtmann 
28588fc9ced3SGustavo Padovan 		if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
28598fc9ced3SGustavo Padovan 					&conn->flags)) {
286004837f64SMarcel Holtmann 			if (conn->mode == HCI_CM_ACTIVE)
286158a681efSJohan Hedberg 				set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
286204837f64SMarcel Holtmann 			else
286358a681efSJohan Hedberg 				clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
286404837f64SMarcel Holtmann 		}
2865e73439d8SMarcel Holtmann 
286651a8efd7SJohan Hedberg 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
2867e73439d8SMarcel Holtmann 			hci_sco_setup(conn, ev->status);
286804837f64SMarcel Holtmann 	}
286904837f64SMarcel Holtmann 
287004837f64SMarcel Holtmann 	hci_dev_unlock(hdev);
287104837f64SMarcel Holtmann }
287204837f64SMarcel Holtmann 
28736039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
28741da177e4SLinus Torvalds {
2875052b30b0SMarcel Holtmann 	struct hci_ev_pin_code_req *ev = (void *) skb->data;
2876052b30b0SMarcel Holtmann 	struct hci_conn *conn;
2877052b30b0SMarcel Holtmann 
2878a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2879052b30b0SMarcel Holtmann 
2880052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2881052b30b0SMarcel Holtmann 
2882052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2883b6f98044SWaldemar Rymarkiewicz 	if (!conn)
2884b6f98044SWaldemar Rymarkiewicz 		goto unlock;
2885b6f98044SWaldemar Rymarkiewicz 
2886b6f98044SWaldemar Rymarkiewicz 	if (conn->state == BT_CONNECTED) {
2887052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2888052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_PAIRING_TIMEOUT;
2889052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2890052b30b0SMarcel Holtmann 	}
2891052b30b0SMarcel Holtmann 
2892a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
289303b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
289403b555e1SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
2895a8b2d5c2SJohan Hedberg 	else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
2896a770bb5aSWaldemar Rymarkiewicz 		u8 secure;
2897a770bb5aSWaldemar Rymarkiewicz 
2898a770bb5aSWaldemar Rymarkiewicz 		if (conn->pending_sec_level == BT_SECURITY_HIGH)
2899a770bb5aSWaldemar Rymarkiewicz 			secure = 1;
2900a770bb5aSWaldemar Rymarkiewicz 		else
2901a770bb5aSWaldemar Rymarkiewicz 			secure = 0;
2902a770bb5aSWaldemar Rymarkiewicz 
2903744cf19eSJohan Hedberg 		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
2904a770bb5aSWaldemar Rymarkiewicz 	}
2905980e1a53SJohan Hedberg 
2906b6f98044SWaldemar Rymarkiewicz unlock:
2907052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
29081da177e4SLinus Torvalds }
29091da177e4SLinus Torvalds 
29106039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
29111da177e4SLinus Torvalds {
291255ed8ca1SJohan Hedberg 	struct hci_ev_link_key_req *ev = (void *) skb->data;
291355ed8ca1SJohan Hedberg 	struct hci_cp_link_key_reply cp;
291455ed8ca1SJohan Hedberg 	struct hci_conn *conn;
291555ed8ca1SJohan Hedberg 	struct link_key *key;
291655ed8ca1SJohan Hedberg 
2917a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
291855ed8ca1SJohan Hedberg 
2919a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
292055ed8ca1SJohan Hedberg 		return;
292155ed8ca1SJohan Hedberg 
292255ed8ca1SJohan Hedberg 	hci_dev_lock(hdev);
292355ed8ca1SJohan Hedberg 
292455ed8ca1SJohan Hedberg 	key = hci_find_link_key(hdev, &ev->bdaddr);
292555ed8ca1SJohan Hedberg 	if (!key) {
29266ed93dc6SAndrei Emeltchenko 		BT_DBG("%s link key not found for %pMR", hdev->name,
29276ed93dc6SAndrei Emeltchenko 		       &ev->bdaddr);
292855ed8ca1SJohan Hedberg 		goto not_found;
292955ed8ca1SJohan Hedberg 	}
293055ed8ca1SJohan Hedberg 
29316ed93dc6SAndrei Emeltchenko 	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
29326ed93dc6SAndrei Emeltchenko 	       &ev->bdaddr);
293355ed8ca1SJohan Hedberg 
2934a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
2935b6020ba0SWaldemar Rymarkiewicz 	    key->type == HCI_LK_DEBUG_COMBINATION) {
293655ed8ca1SJohan Hedberg 		BT_DBG("%s ignoring debug key", hdev->name);
293755ed8ca1SJohan Hedberg 		goto not_found;
293855ed8ca1SJohan Hedberg 	}
293955ed8ca1SJohan Hedberg 
294055ed8ca1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
294160b83f57SWaldemar Rymarkiewicz 	if (conn) {
294260b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
2943807deac2SGustavo Padovan 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
294455ed8ca1SJohan Hedberg 			BT_DBG("%s ignoring unauthenticated key", hdev->name);
294555ed8ca1SJohan Hedberg 			goto not_found;
294655ed8ca1SJohan Hedberg 		}
294755ed8ca1SJohan Hedberg 
294860b83f57SWaldemar Rymarkiewicz 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
294960b83f57SWaldemar Rymarkiewicz 		    conn->pending_sec_level == BT_SECURITY_HIGH) {
29508fc9ced3SGustavo Padovan 			BT_DBG("%s ignoring key unauthenticated for high security",
29518fc9ced3SGustavo Padovan 			       hdev->name);
295260b83f57SWaldemar Rymarkiewicz 			goto not_found;
295360b83f57SWaldemar Rymarkiewicz 		}
295460b83f57SWaldemar Rymarkiewicz 
295560b83f57SWaldemar Rymarkiewicz 		conn->key_type = key->type;
295660b83f57SWaldemar Rymarkiewicz 		conn->pin_length = key->pin_len;
295760b83f57SWaldemar Rymarkiewicz 	}
295860b83f57SWaldemar Rymarkiewicz 
295955ed8ca1SJohan Hedberg 	bacpy(&cp.bdaddr, &ev->bdaddr);
29609b3b4460SAndrei Emeltchenko 	memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
296155ed8ca1SJohan Hedberg 
296255ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
296355ed8ca1SJohan Hedberg 
296455ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
296555ed8ca1SJohan Hedberg 
296655ed8ca1SJohan Hedberg 	return;
296755ed8ca1SJohan Hedberg 
296855ed8ca1SJohan Hedberg not_found:
296955ed8ca1SJohan Hedberg 	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
297055ed8ca1SJohan Hedberg 	hci_dev_unlock(hdev);
29711da177e4SLinus Torvalds }
29721da177e4SLinus Torvalds 
29736039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
29741da177e4SLinus Torvalds {
2975052b30b0SMarcel Holtmann 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
2976052b30b0SMarcel Holtmann 	struct hci_conn *conn;
297755ed8ca1SJohan Hedberg 	u8 pin_len = 0;
2978052b30b0SMarcel Holtmann 
2979a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2980052b30b0SMarcel Holtmann 
2981052b30b0SMarcel Holtmann 	hci_dev_lock(hdev);
2982052b30b0SMarcel Holtmann 
2983052b30b0SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
2984052b30b0SMarcel Holtmann 	if (conn) {
2985052b30b0SMarcel Holtmann 		hci_conn_hold(conn);
2986052b30b0SMarcel Holtmann 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
2987980e1a53SJohan Hedberg 		pin_len = conn->pin_length;
298813d39315SWaldemar Rymarkiewicz 
298913d39315SWaldemar Rymarkiewicz 		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
299013d39315SWaldemar Rymarkiewicz 			conn->key_type = ev->key_type;
299113d39315SWaldemar Rymarkiewicz 
2992052b30b0SMarcel Holtmann 		hci_conn_put(conn);
2993052b30b0SMarcel Holtmann 	}
2994052b30b0SMarcel Holtmann 
2995a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
2996d25e28abSJohan Hedberg 		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
299755ed8ca1SJohan Hedberg 				 ev->key_type, pin_len);
299855ed8ca1SJohan Hedberg 
2999052b30b0SMarcel Holtmann 	hci_dev_unlock(hdev);
30001da177e4SLinus Torvalds }
30011da177e4SLinus Torvalds 
30026039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
300304837f64SMarcel Holtmann {
3004a9de9248SMarcel Holtmann 	struct hci_ev_clock_offset *ev = (void *) skb->data;
300504837f64SMarcel Holtmann 	struct hci_conn *conn;
300604837f64SMarcel Holtmann 
30079f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
300804837f64SMarcel Holtmann 
300904837f64SMarcel Holtmann 	hci_dev_lock(hdev);
301004837f64SMarcel Holtmann 
301104837f64SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
30121da177e4SLinus Torvalds 	if (conn && !ev->status) {
30131da177e4SLinus Torvalds 		struct inquiry_entry *ie;
30141da177e4SLinus Torvalds 
3015cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3016cc11b9c1SAndrei Emeltchenko 		if (ie) {
30171da177e4SLinus Torvalds 			ie->data.clock_offset = ev->clock_offset;
30181da177e4SLinus Torvalds 			ie->timestamp = jiffies;
30191da177e4SLinus Torvalds 		}
30201da177e4SLinus Torvalds 	}
30211da177e4SLinus Torvalds 
30221da177e4SLinus Torvalds 	hci_dev_unlock(hdev);
30231da177e4SLinus Torvalds }
30241da177e4SLinus Torvalds 
30256039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
3026a8746417SMarcel Holtmann {
3027a8746417SMarcel Holtmann 	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
3028a8746417SMarcel Holtmann 	struct hci_conn *conn;
3029a8746417SMarcel Holtmann 
30309f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3031a8746417SMarcel Holtmann 
3032a8746417SMarcel Holtmann 	hci_dev_lock(hdev);
3033a8746417SMarcel Holtmann 
3034a8746417SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3035a8746417SMarcel Holtmann 	if (conn && !ev->status)
3036a8746417SMarcel Holtmann 		conn->pkt_type = __le16_to_cpu(ev->pkt_type);
3037a8746417SMarcel Holtmann 
3038a8746417SMarcel Holtmann 	hci_dev_unlock(hdev);
3039a8746417SMarcel Holtmann }
3040a8746417SMarcel Holtmann 
30416039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
304285a1e930SMarcel Holtmann {
3043a9de9248SMarcel Holtmann 	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
304485a1e930SMarcel Holtmann 	struct inquiry_entry *ie;
304585a1e930SMarcel Holtmann 
304685a1e930SMarcel Holtmann 	BT_DBG("%s", hdev->name);
304785a1e930SMarcel Holtmann 
304885a1e930SMarcel Holtmann 	hci_dev_lock(hdev);
304985a1e930SMarcel Holtmann 
3050cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3051cc11b9c1SAndrei Emeltchenko 	if (ie) {
305285a1e930SMarcel Holtmann 		ie->data.pscan_rep_mode = ev->pscan_rep_mode;
305385a1e930SMarcel Holtmann 		ie->timestamp = jiffies;
305485a1e930SMarcel Holtmann 	}
305585a1e930SMarcel Holtmann 
305685a1e930SMarcel Holtmann 	hci_dev_unlock(hdev);
305785a1e930SMarcel Holtmann }
305885a1e930SMarcel Holtmann 
30596039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
3060807deac2SGustavo Padovan 					     struct sk_buff *skb)
3061a9de9248SMarcel Holtmann {
3062a9de9248SMarcel Holtmann 	struct inquiry_data data;
3063a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
3064388fc8faSJohan Hedberg 	bool name_known, ssp;
3065a9de9248SMarcel Holtmann 
3066a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3067a9de9248SMarcel Holtmann 
3068a9de9248SMarcel Holtmann 	if (!num_rsp)
3069a9de9248SMarcel Holtmann 		return;
3070a9de9248SMarcel Holtmann 
30711519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
30721519cc17SAndre Guedes 		return;
30731519cc17SAndre Guedes 
3074a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3075a9de9248SMarcel Holtmann 
3076a9de9248SMarcel Holtmann 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
3077138d22efSSzymon Janc 		struct inquiry_info_with_rssi_and_pscan_mode *info;
3078138d22efSSzymon Janc 		info = (void *) (skb->data + 1);
3079a9de9248SMarcel Holtmann 
3080e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3081a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3082a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3083a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3084a9de9248SMarcel Holtmann 			data.pscan_mode		= info->pscan_mode;
3085a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3086a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3087a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
308841a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
30893175405bSJohan Hedberg 
30903175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3091388fc8faSJohan Hedberg 							      false, &ssp);
309248264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3093e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3094388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3095a9de9248SMarcel Holtmann 		}
3096a9de9248SMarcel Holtmann 	} else {
3097a9de9248SMarcel Holtmann 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
3098a9de9248SMarcel Holtmann 
3099e17acd40SJohan Hedberg 		for (; num_rsp; num_rsp--, info++) {
3100a9de9248SMarcel Holtmann 			bacpy(&data.bdaddr, &info->bdaddr);
3101a9de9248SMarcel Holtmann 			data.pscan_rep_mode	= info->pscan_rep_mode;
3102a9de9248SMarcel Holtmann 			data.pscan_period_mode	= info->pscan_period_mode;
3103a9de9248SMarcel Holtmann 			data.pscan_mode		= 0x00;
3104a9de9248SMarcel Holtmann 			memcpy(data.dev_class, info->dev_class, 3);
3105a9de9248SMarcel Holtmann 			data.clock_offset	= info->clock_offset;
3106a9de9248SMarcel Holtmann 			data.rssi		= info->rssi;
310741a96212SMarcel Holtmann 			data.ssp_mode		= 0x00;
31083175405bSJohan Hedberg 			name_known = hci_inquiry_cache_update(hdev, &data,
3109388fc8faSJohan Hedberg 							      false, &ssp);
311048264f06SJohan Hedberg 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
3111e17acd40SJohan Hedberg 					  info->dev_class, info->rssi,
3112388fc8faSJohan Hedberg 					  !name_known, ssp, NULL, 0);
3113a9de9248SMarcel Holtmann 		}
3114a9de9248SMarcel Holtmann 	}
3115a9de9248SMarcel Holtmann 
3116a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3117a9de9248SMarcel Holtmann }
3118a9de9248SMarcel Holtmann 
31196039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev,
3120807deac2SGustavo Padovan 					struct sk_buff *skb)
3121a9de9248SMarcel Holtmann {
312241a96212SMarcel Holtmann 	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
312341a96212SMarcel Holtmann 	struct hci_conn *conn;
312441a96212SMarcel Holtmann 
3125a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
312641a96212SMarcel Holtmann 
312741a96212SMarcel Holtmann 	hci_dev_lock(hdev);
312841a96212SMarcel Holtmann 
312941a96212SMarcel Holtmann 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3130ccd556feSJohan Hedberg 	if (!conn)
3131ccd556feSJohan Hedberg 		goto unlock;
3132ccd556feSJohan Hedberg 
3133769be974SMarcel Holtmann 	if (!ev->status && ev->page == 0x01) {
313441a96212SMarcel Holtmann 		struct inquiry_entry *ie;
313541a96212SMarcel Holtmann 
3136cc11b9c1SAndrei Emeltchenko 		ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
3137cc11b9c1SAndrei Emeltchenko 		if (ie)
313802b7cc62SJohan Hedberg 			ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
313941a96212SMarcel Holtmann 
314002b7cc62SJohan Hedberg 		if (ev->features[0] & LMP_HOST_SSP)
314158a681efSJohan Hedberg 			set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
314241a96212SMarcel Holtmann 	}
314341a96212SMarcel Holtmann 
3144ccd556feSJohan Hedberg 	if (conn->state != BT_CONFIG)
3145ccd556feSJohan Hedberg 		goto unlock;
3146ccd556feSJohan Hedberg 
3147671267bfSJohan Hedberg 	if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
3148127178d2SJohan Hedberg 		struct hci_cp_remote_name_req cp;
3149127178d2SJohan Hedberg 		memset(&cp, 0, sizeof(cp));
3150127178d2SJohan Hedberg 		bacpy(&cp.bdaddr, &conn->dst);
3151127178d2SJohan Hedberg 		cp.pscan_rep_mode = 0x02;
3152127178d2SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
3153b644ba33SJohan Hedberg 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3154b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &conn->dst, conn->type,
315508c79b61SJohan Hedberg 				      conn->dst_type, 0, NULL, 0,
3156b644ba33SJohan Hedberg 				      conn->dev_class);
3157392599b9SJohan Hedberg 
3158127178d2SJohan Hedberg 	if (!hci_outgoing_auth_needed(hdev, conn)) {
3159769be974SMarcel Holtmann 		conn->state = BT_CONNECTED;
3160769be974SMarcel Holtmann 		hci_proto_connect_cfm(conn, ev->status);
3161769be974SMarcel Holtmann 		hci_conn_put(conn);
3162769be974SMarcel Holtmann 	}
3163769be974SMarcel Holtmann 
3164ccd556feSJohan Hedberg unlock:
316541a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
3166a9de9248SMarcel Holtmann }
3167a9de9248SMarcel Holtmann 
31686039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
3169807deac2SGustavo Padovan 				       struct sk_buff *skb)
3170a9de9248SMarcel Holtmann {
3171b6a0dc82SMarcel Holtmann 	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
3172b6a0dc82SMarcel Holtmann 	struct hci_conn *conn;
3173b6a0dc82SMarcel Holtmann 
31749f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3175b6a0dc82SMarcel Holtmann 
3176b6a0dc82SMarcel Holtmann 	hci_dev_lock(hdev);
3177b6a0dc82SMarcel Holtmann 
3178b6a0dc82SMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
31799dc0a3afSMarcel Holtmann 	if (!conn) {
31809dc0a3afSMarcel Holtmann 		if (ev->link_type == ESCO_LINK)
31819dc0a3afSMarcel Holtmann 			goto unlock;
31829dc0a3afSMarcel Holtmann 
31839dc0a3afSMarcel Holtmann 		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
3184b6a0dc82SMarcel Holtmann 		if (!conn)
3185b6a0dc82SMarcel Holtmann 			goto unlock;
3186b6a0dc82SMarcel Holtmann 
31879dc0a3afSMarcel Holtmann 		conn->type = SCO_LINK;
31889dc0a3afSMarcel Holtmann 	}
31899dc0a3afSMarcel Holtmann 
3190732547f9SMarcel Holtmann 	switch (ev->status) {
3191732547f9SMarcel Holtmann 	case 0x00:
3192732547f9SMarcel Holtmann 		conn->handle = __le16_to_cpu(ev->handle);
3193732547f9SMarcel Holtmann 		conn->state  = BT_CONNECTED;
3194732547f9SMarcel Holtmann 
31959eba32b8SMarcel Holtmann 		hci_conn_hold_device(conn);
3196732547f9SMarcel Holtmann 		hci_conn_add_sysfs(conn);
3197732547f9SMarcel Holtmann 		break;
3198732547f9SMarcel Holtmann 
3199705e5711SStephen Coe 	case 0x11:	/* Unsupported Feature or Parameter Value */
3200732547f9SMarcel Holtmann 	case 0x1c:	/* SCO interval rejected */
32011038a00bSNick Pelly 	case 0x1a:	/* Unsupported Remote Feature */
3202732547f9SMarcel Holtmann 	case 0x1f:	/* Unspecified error */
3203732547f9SMarcel Holtmann 		if (conn->out && conn->attempt < 2) {
3204efc7688bSMarcel Holtmann 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
3205efc7688bSMarcel Holtmann 					(hdev->esco_type & EDR_ESCO_MASK);
3206efc7688bSMarcel Holtmann 			hci_setup_sync(conn, conn->link->handle);
3207efc7688bSMarcel Holtmann 			goto unlock;
3208efc7688bSMarcel Holtmann 		}
3209732547f9SMarcel Holtmann 		/* fall through */
3210efc7688bSMarcel Holtmann 
3211732547f9SMarcel Holtmann 	default:
3212b6a0dc82SMarcel Holtmann 		conn->state = BT_CLOSED;
3213732547f9SMarcel Holtmann 		break;
3214732547f9SMarcel Holtmann 	}
3215b6a0dc82SMarcel Holtmann 
3216b6a0dc82SMarcel Holtmann 	hci_proto_connect_cfm(conn, ev->status);
3217b6a0dc82SMarcel Holtmann 	if (ev->status)
3218b6a0dc82SMarcel Holtmann 		hci_conn_del(conn);
3219b6a0dc82SMarcel Holtmann 
3220b6a0dc82SMarcel Holtmann unlock:
3221b6a0dc82SMarcel Holtmann 	hci_dev_unlock(hdev);
3222a9de9248SMarcel Holtmann }
3223a9de9248SMarcel Holtmann 
32246039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
3225a9de9248SMarcel Holtmann {
3226a9de9248SMarcel Holtmann 	BT_DBG("%s", hdev->name);
3227a9de9248SMarcel Holtmann }
3228a9de9248SMarcel Holtmann 
32296039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
323004837f64SMarcel Holtmann {
3231a9de9248SMarcel Holtmann 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
323204837f64SMarcel Holtmann 
32339f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
323404837f64SMarcel Holtmann }
323504837f64SMarcel Holtmann 
32366039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
3237807deac2SGustavo Padovan 					    struct sk_buff *skb)
3238a9de9248SMarcel Holtmann {
3239a9de9248SMarcel Holtmann 	struct inquiry_data data;
3240a9de9248SMarcel Holtmann 	struct extended_inquiry_info *info = (void *) (skb->data + 1);
3241a9de9248SMarcel Holtmann 	int num_rsp = *((__u8 *) skb->data);
32429d939d94SVishal Agarwal 	size_t eir_len;
3243a9de9248SMarcel Holtmann 
3244a9de9248SMarcel Holtmann 	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
3245a9de9248SMarcel Holtmann 
3246a9de9248SMarcel Holtmann 	if (!num_rsp)
3247a9de9248SMarcel Holtmann 		return;
3248a9de9248SMarcel Holtmann 
32491519cc17SAndre Guedes 	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
32501519cc17SAndre Guedes 		return;
32511519cc17SAndre Guedes 
3252a9de9248SMarcel Holtmann 	hci_dev_lock(hdev);
3253a9de9248SMarcel Holtmann 
3254e17acd40SJohan Hedberg 	for (; num_rsp; num_rsp--, info++) {
3255388fc8faSJohan Hedberg 		bool name_known, ssp;
3256561aafbcSJohan Hedberg 
3257a9de9248SMarcel Holtmann 		bacpy(&data.bdaddr, &info->bdaddr);
3258a9de9248SMarcel Holtmann 		data.pscan_rep_mode	= info->pscan_rep_mode;
3259a9de9248SMarcel Holtmann 		data.pscan_period_mode	= info->pscan_period_mode;
3260a9de9248SMarcel Holtmann 		data.pscan_mode		= 0x00;
3261a9de9248SMarcel Holtmann 		memcpy(data.dev_class, info->dev_class, 3);
3262a9de9248SMarcel Holtmann 		data.clock_offset	= info->clock_offset;
3263a9de9248SMarcel Holtmann 		data.rssi		= info->rssi;
326441a96212SMarcel Holtmann 		data.ssp_mode		= 0x01;
3265561aafbcSJohan Hedberg 
3266a8b2d5c2SJohan Hedberg 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
32674ddb1930SJohan Hedberg 			name_known = eir_has_data_type(info->data,
32684ddb1930SJohan Hedberg 						       sizeof(info->data),
32694ddb1930SJohan Hedberg 						       EIR_NAME_COMPLETE);
3270561aafbcSJohan Hedberg 		else
3271561aafbcSJohan Hedberg 			name_known = true;
3272561aafbcSJohan Hedberg 
3273388fc8faSJohan Hedberg 		name_known = hci_inquiry_cache_update(hdev, &data, name_known,
3274388fc8faSJohan Hedberg 						      &ssp);
32759d939d94SVishal Agarwal 		eir_len = eir_get_length(info->data, sizeof(info->data));
327648264f06SJohan Hedberg 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
327704124681SGustavo F. Padovan 				  info->dev_class, info->rssi, !name_known,
32789d939d94SVishal Agarwal 				  ssp, info->data, eir_len);
3279a9de9248SMarcel Holtmann 	}
3280a9de9248SMarcel Holtmann 
3281a9de9248SMarcel Holtmann 	hci_dev_unlock(hdev);
3282a9de9248SMarcel Holtmann }
3283a9de9248SMarcel Holtmann 
32841c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
32851c2e0041SJohan Hedberg 					 struct sk_buff *skb)
32861c2e0041SJohan Hedberg {
32871c2e0041SJohan Hedberg 	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
32881c2e0041SJohan Hedberg 	struct hci_conn *conn;
32891c2e0041SJohan Hedberg 
32909f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
32911c2e0041SJohan Hedberg 	       __le16_to_cpu(ev->handle));
32921c2e0041SJohan Hedberg 
32931c2e0041SJohan Hedberg 	hci_dev_lock(hdev);
32941c2e0041SJohan Hedberg 
32951c2e0041SJohan Hedberg 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
32961c2e0041SJohan Hedberg 	if (!conn)
32971c2e0041SJohan Hedberg 		goto unlock;
32981c2e0041SJohan Hedberg 
32991c2e0041SJohan Hedberg 	if (!ev->status)
33001c2e0041SJohan Hedberg 		conn->sec_level = conn->pending_sec_level;
33011c2e0041SJohan Hedberg 
33021c2e0041SJohan Hedberg 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
33031c2e0041SJohan Hedberg 
33041c2e0041SJohan Hedberg 	if (ev->status && conn->state == BT_CONNECTED) {
33051c2e0041SJohan Hedberg 		hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
33061c2e0041SJohan Hedberg 		hci_conn_put(conn);
33071c2e0041SJohan Hedberg 		goto unlock;
33081c2e0041SJohan Hedberg 	}
33091c2e0041SJohan Hedberg 
33101c2e0041SJohan Hedberg 	if (conn->state == BT_CONFIG) {
33111c2e0041SJohan Hedberg 		if (!ev->status)
33121c2e0041SJohan Hedberg 			conn->state = BT_CONNECTED;
33131c2e0041SJohan Hedberg 
33141c2e0041SJohan Hedberg 		hci_proto_connect_cfm(conn, ev->status);
33151c2e0041SJohan Hedberg 		hci_conn_put(conn);
33161c2e0041SJohan Hedberg 	} else {
33171c2e0041SJohan Hedberg 		hci_auth_cfm(conn, ev->status);
33181c2e0041SJohan Hedberg 
33191c2e0041SJohan Hedberg 		hci_conn_hold(conn);
33201c2e0041SJohan Hedberg 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
33211c2e0041SJohan Hedberg 		hci_conn_put(conn);
33221c2e0041SJohan Hedberg 	}
33231c2e0041SJohan Hedberg 
33241c2e0041SJohan Hedberg unlock:
33251c2e0041SJohan Hedberg 	hci_dev_unlock(hdev);
33261c2e0041SJohan Hedberg }
33271c2e0041SJohan Hedberg 
33286039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn)
332917fa4b9dSJohan Hedberg {
333017fa4b9dSJohan Hedberg 	/* If remote requests dedicated bonding follow that lead */
333117fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
333217fa4b9dSJohan Hedberg 		/* If both remote and local IO capabilities allow MITM
333317fa4b9dSJohan Hedberg 		 * protection then require it, otherwise don't */
333417fa4b9dSJohan Hedberg 		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
333517fa4b9dSJohan Hedberg 			return 0x02;
333617fa4b9dSJohan Hedberg 		else
333717fa4b9dSJohan Hedberg 			return 0x03;
333817fa4b9dSJohan Hedberg 	}
333917fa4b9dSJohan Hedberg 
334017fa4b9dSJohan Hedberg 	/* If remote requests no-bonding follow that lead */
334117fa4b9dSJohan Hedberg 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
334258797bf7SWaldemar Rymarkiewicz 		return conn->remote_auth | (conn->auth_type & 0x01);
334317fa4b9dSJohan Hedberg 
334417fa4b9dSJohan Hedberg 	return conn->auth_type;
334517fa4b9dSJohan Hedberg }
334617fa4b9dSJohan Hedberg 
33476039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
33480493684eSMarcel Holtmann {
33490493684eSMarcel Holtmann 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
33500493684eSMarcel Holtmann 	struct hci_conn *conn;
33510493684eSMarcel Holtmann 
33520493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
33530493684eSMarcel Holtmann 
33540493684eSMarcel Holtmann 	hci_dev_lock(hdev);
33550493684eSMarcel Holtmann 
33560493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
335703b555e1SJohan Hedberg 	if (!conn)
335803b555e1SJohan Hedberg 		goto unlock;
335903b555e1SJohan Hedberg 
33600493684eSMarcel Holtmann 	hci_conn_hold(conn);
33610493684eSMarcel Holtmann 
3362a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
336303b555e1SJohan Hedberg 		goto unlock;
336403b555e1SJohan Hedberg 
3365a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
336603b555e1SJohan Hedberg 	    (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
336717fa4b9dSJohan Hedberg 		struct hci_cp_io_capability_reply cp;
336817fa4b9dSJohan Hedberg 
336917fa4b9dSJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
33707a7f1e7cSHemant Gupta 		/* Change the IO capability from KeyboardDisplay
33717a7f1e7cSHemant Gupta 		 * to DisplayYesNo as it is not supported by BT spec. */
33727a7f1e7cSHemant Gupta 		cp.capability = (conn->io_capability == 0x04) ?
33737a7f1e7cSHemant Gupta 						0x01 : conn->io_capability;
33747cbc9bd9SJohan Hedberg 		conn->auth_type = hci_get_auth_req(conn);
33757cbc9bd9SJohan Hedberg 		cp.authentication = conn->auth_type;
337617fa4b9dSJohan Hedberg 
33778fc9ced3SGustavo Padovan 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
33788fc9ced3SGustavo Padovan 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
3379ce85ee13SSzymon Janc 			cp.oob_data = 0x01;
3380ce85ee13SSzymon Janc 		else
3381ce85ee13SSzymon Janc 			cp.oob_data = 0x00;
3382ce85ee13SSzymon Janc 
338317fa4b9dSJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
338417fa4b9dSJohan Hedberg 			     sizeof(cp), &cp);
338503b555e1SJohan Hedberg 	} else {
338603b555e1SJohan Hedberg 		struct hci_cp_io_capability_neg_reply cp;
338703b555e1SJohan Hedberg 
338803b555e1SJohan Hedberg 		bacpy(&cp.bdaddr, &ev->bdaddr);
33899f5a0d7bSAndrei Emeltchenko 		cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
339003b555e1SJohan Hedberg 
339103b555e1SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
339203b555e1SJohan Hedberg 			     sizeof(cp), &cp);
339303b555e1SJohan Hedberg 	}
339403b555e1SJohan Hedberg 
339503b555e1SJohan Hedberg unlock:
339603b555e1SJohan Hedberg 	hci_dev_unlock(hdev);
339703b555e1SJohan Hedberg }
339803b555e1SJohan Hedberg 
33996039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
340003b555e1SJohan Hedberg {
340103b555e1SJohan Hedberg 	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
340203b555e1SJohan Hedberg 	struct hci_conn *conn;
340303b555e1SJohan Hedberg 
340403b555e1SJohan Hedberg 	BT_DBG("%s", hdev->name);
340503b555e1SJohan Hedberg 
340603b555e1SJohan Hedberg 	hci_dev_lock(hdev);
340703b555e1SJohan Hedberg 
340803b555e1SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
340903b555e1SJohan Hedberg 	if (!conn)
341003b555e1SJohan Hedberg 		goto unlock;
341103b555e1SJohan Hedberg 
341203b555e1SJohan Hedberg 	conn->remote_cap = ev->capability;
341303b555e1SJohan Hedberg 	conn->remote_auth = ev->authentication;
341458a681efSJohan Hedberg 	if (ev->oob_data)
341558a681efSJohan Hedberg 		set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
341603b555e1SJohan Hedberg 
341703b555e1SJohan Hedberg unlock:
34180493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
34190493684eSMarcel Holtmann }
34200493684eSMarcel Holtmann 
34216039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev,
3422a5c29683SJohan Hedberg 					 struct sk_buff *skb)
3423a5c29683SJohan Hedberg {
3424a5c29683SJohan Hedberg 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
342555bc1a37SJohan Hedberg 	int loc_mitm, rem_mitm, confirm_hint = 0;
34267a828908SJohan Hedberg 	struct hci_conn *conn;
3427a5c29683SJohan Hedberg 
3428a5c29683SJohan Hedberg 	BT_DBG("%s", hdev->name);
3429a5c29683SJohan Hedberg 
3430a5c29683SJohan Hedberg 	hci_dev_lock(hdev);
3431a5c29683SJohan Hedberg 
3432a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
34337a828908SJohan Hedberg 		goto unlock;
34347a828908SJohan Hedberg 
34357a828908SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
34367a828908SJohan Hedberg 	if (!conn)
34377a828908SJohan Hedberg 		goto unlock;
34387a828908SJohan Hedberg 
34397a828908SJohan Hedberg 	loc_mitm = (conn->auth_type & 0x01);
34407a828908SJohan Hedberg 	rem_mitm = (conn->remote_auth & 0x01);
34417a828908SJohan Hedberg 
34427a828908SJohan Hedberg 	/* If we require MITM but the remote device can't provide that
34437a828908SJohan Hedberg 	 * (it has NoInputNoOutput) then reject the confirmation
34447a828908SJohan Hedberg 	 * request. The only exception is when we're dedicated bonding
34457a828908SJohan Hedberg 	 * initiators (connect_cfm_cb set) since then we always have the MITM
34467a828908SJohan Hedberg 	 * bit set. */
34477a828908SJohan Hedberg 	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
34487a828908SJohan Hedberg 		BT_DBG("Rejecting request: remote device can't provide MITM");
34497a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
34507a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
34517a828908SJohan Hedberg 		goto unlock;
34527a828908SJohan Hedberg 	}
34537a828908SJohan Hedberg 
34547a828908SJohan Hedberg 	/* If no side requires MITM protection; auto-accept */
34557a828908SJohan Hedberg 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
34567a828908SJohan Hedberg 	    (!rem_mitm || conn->io_capability == 0x03)) {
345755bc1a37SJohan Hedberg 
345855bc1a37SJohan Hedberg 		/* If we're not the initiators request authorization to
345955bc1a37SJohan Hedberg 		 * proceed from user space (mgmt_user_confirm with
346055bc1a37SJohan Hedberg 		 * confirm_hint set to 1). */
346151a8efd7SJohan Hedberg 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
346255bc1a37SJohan Hedberg 			BT_DBG("Confirming auto-accept as acceptor");
346355bc1a37SJohan Hedberg 			confirm_hint = 1;
346455bc1a37SJohan Hedberg 			goto confirm;
346555bc1a37SJohan Hedberg 		}
346655bc1a37SJohan Hedberg 
34679f61656aSJohan Hedberg 		BT_DBG("Auto-accept of user confirmation with %ums delay",
34689f61656aSJohan Hedberg 		       hdev->auto_accept_delay);
34699f61656aSJohan Hedberg 
34709f61656aSJohan Hedberg 		if (hdev->auto_accept_delay > 0) {
34719f61656aSJohan Hedberg 			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
34729f61656aSJohan Hedberg 			mod_timer(&conn->auto_accept_timer, jiffies + delay);
34739f61656aSJohan Hedberg 			goto unlock;
34749f61656aSJohan Hedberg 		}
34759f61656aSJohan Hedberg 
34767a828908SJohan Hedberg 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
34777a828908SJohan Hedberg 			     sizeof(ev->bdaddr), &ev->bdaddr);
34787a828908SJohan Hedberg 		goto unlock;
34797a828908SJohan Hedberg 	}
34807a828908SJohan Hedberg 
348155bc1a37SJohan Hedberg confirm:
3482272d90dfSJohan Hedberg 	mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
348355bc1a37SJohan Hedberg 				  confirm_hint);
3484a5c29683SJohan Hedberg 
34857a828908SJohan Hedberg unlock:
3486a5c29683SJohan Hedberg 	hci_dev_unlock(hdev);
3487a5c29683SJohan Hedberg }
3488a5c29683SJohan Hedberg 
34896039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev,
34901143d458SBrian Gix 					 struct sk_buff *skb)
34911143d458SBrian Gix {
34921143d458SBrian Gix 	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
34931143d458SBrian Gix 
34941143d458SBrian Gix 	BT_DBG("%s", hdev->name);
34951143d458SBrian Gix 
3496a8b2d5c2SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
3497272d90dfSJohan Hedberg 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
34981143d458SBrian Gix }
34991143d458SBrian Gix 
350092a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
350192a25256SJohan Hedberg 					struct sk_buff *skb)
350292a25256SJohan Hedberg {
350392a25256SJohan Hedberg 	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
350492a25256SJohan Hedberg 	struct hci_conn *conn;
350592a25256SJohan Hedberg 
350692a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
350792a25256SJohan Hedberg 
350892a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
350992a25256SJohan Hedberg 	if (!conn)
351092a25256SJohan Hedberg 		return;
351192a25256SJohan Hedberg 
351292a25256SJohan Hedberg 	conn->passkey_notify = __le32_to_cpu(ev->passkey);
351392a25256SJohan Hedberg 	conn->passkey_entered = 0;
351492a25256SJohan Hedberg 
351592a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
351692a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
351792a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
351892a25256SJohan Hedberg 					 conn->passkey_entered);
351992a25256SJohan Hedberg }
352092a25256SJohan Hedberg 
352192a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
352292a25256SJohan Hedberg {
352392a25256SJohan Hedberg 	struct hci_ev_keypress_notify *ev = (void *) skb->data;
352492a25256SJohan Hedberg 	struct hci_conn *conn;
352592a25256SJohan Hedberg 
352692a25256SJohan Hedberg 	BT_DBG("%s", hdev->name);
352792a25256SJohan Hedberg 
352892a25256SJohan Hedberg 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
352992a25256SJohan Hedberg 	if (!conn)
353092a25256SJohan Hedberg 		return;
353192a25256SJohan Hedberg 
353292a25256SJohan Hedberg 	switch (ev->type) {
353392a25256SJohan Hedberg 	case HCI_KEYPRESS_STARTED:
353492a25256SJohan Hedberg 		conn->passkey_entered = 0;
353592a25256SJohan Hedberg 		return;
353692a25256SJohan Hedberg 
353792a25256SJohan Hedberg 	case HCI_KEYPRESS_ENTERED:
353892a25256SJohan Hedberg 		conn->passkey_entered++;
353992a25256SJohan Hedberg 		break;
354092a25256SJohan Hedberg 
354192a25256SJohan Hedberg 	case HCI_KEYPRESS_ERASED:
354292a25256SJohan Hedberg 		conn->passkey_entered--;
354392a25256SJohan Hedberg 		break;
354492a25256SJohan Hedberg 
354592a25256SJohan Hedberg 	case HCI_KEYPRESS_CLEARED:
354692a25256SJohan Hedberg 		conn->passkey_entered = 0;
354792a25256SJohan Hedberg 		break;
354892a25256SJohan Hedberg 
354992a25256SJohan Hedberg 	case HCI_KEYPRESS_COMPLETED:
355092a25256SJohan Hedberg 		return;
355192a25256SJohan Hedberg 	}
355292a25256SJohan Hedberg 
355392a25256SJohan Hedberg 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
355492a25256SJohan Hedberg 		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
355592a25256SJohan Hedberg 					 conn->dst_type, conn->passkey_notify,
355692a25256SJohan Hedberg 					 conn->passkey_entered);
355792a25256SJohan Hedberg }
355892a25256SJohan Hedberg 
35596039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
3560807deac2SGustavo Padovan 					 struct sk_buff *skb)
35610493684eSMarcel Holtmann {
35620493684eSMarcel Holtmann 	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
35630493684eSMarcel Holtmann 	struct hci_conn *conn;
35640493684eSMarcel Holtmann 
35650493684eSMarcel Holtmann 	BT_DBG("%s", hdev->name);
35660493684eSMarcel Holtmann 
35670493684eSMarcel Holtmann 	hci_dev_lock(hdev);
35680493684eSMarcel Holtmann 
35690493684eSMarcel Holtmann 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
35702a611692SJohan Hedberg 	if (!conn)
35712a611692SJohan Hedberg 		goto unlock;
35722a611692SJohan Hedberg 
35732a611692SJohan Hedberg 	/* To avoid duplicate auth_failed events to user space we check
35742a611692SJohan Hedberg 	 * the HCI_CONN_AUTH_PEND flag which will be set if we
35752a611692SJohan Hedberg 	 * initiated the authentication. A traditional auth_complete
35762a611692SJohan Hedberg 	 * event gets always produced as initiator and is also mapped to
35772a611692SJohan Hedberg 	 * the mgmt_auth_failed event */
3578fa1bd918SMikel Astiz 	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
3579bab73cb6SJohan Hedberg 		mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
3580bab73cb6SJohan Hedberg 				 ev->status);
35812a611692SJohan Hedberg 
35820493684eSMarcel Holtmann 	hci_conn_put(conn);
35830493684eSMarcel Holtmann 
35842a611692SJohan Hedberg unlock:
35850493684eSMarcel Holtmann 	hci_dev_unlock(hdev);
35860493684eSMarcel Holtmann }
35870493684eSMarcel Holtmann 
35886039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev,
3589807deac2SGustavo Padovan 					 struct sk_buff *skb)
359041a96212SMarcel Holtmann {
359141a96212SMarcel Holtmann 	struct hci_ev_remote_host_features *ev = (void *) skb->data;
359241a96212SMarcel Holtmann 	struct inquiry_entry *ie;
359341a96212SMarcel Holtmann 
359441a96212SMarcel Holtmann 	BT_DBG("%s", hdev->name);
359541a96212SMarcel Holtmann 
359641a96212SMarcel Holtmann 	hci_dev_lock(hdev);
359741a96212SMarcel Holtmann 
3598cc11b9c1SAndrei Emeltchenko 	ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
3599cc11b9c1SAndrei Emeltchenko 	if (ie)
360002b7cc62SJohan Hedberg 		ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
360141a96212SMarcel Holtmann 
360241a96212SMarcel Holtmann 	hci_dev_unlock(hdev);
360341a96212SMarcel Holtmann }
360441a96212SMarcel Holtmann 
36056039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
36062763eda6SSzymon Janc 					    struct sk_buff *skb)
36072763eda6SSzymon Janc {
36082763eda6SSzymon Janc 	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
36092763eda6SSzymon Janc 	struct oob_data *data;
36102763eda6SSzymon Janc 
36112763eda6SSzymon Janc 	BT_DBG("%s", hdev->name);
36122763eda6SSzymon Janc 
36132763eda6SSzymon Janc 	hci_dev_lock(hdev);
36142763eda6SSzymon Janc 
3615a8b2d5c2SJohan Hedberg 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
3616e1ba1f15SSzymon Janc 		goto unlock;
3617e1ba1f15SSzymon Janc 
36182763eda6SSzymon Janc 	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
36192763eda6SSzymon Janc 	if (data) {
36202763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_reply cp;
36212763eda6SSzymon Janc 
36222763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
36232763eda6SSzymon Janc 		memcpy(cp.hash, data->hash, sizeof(cp.hash));
36242763eda6SSzymon Janc 		memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
36252763eda6SSzymon Janc 
36262763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
36272763eda6SSzymon Janc 			     &cp);
36282763eda6SSzymon Janc 	} else {
36292763eda6SSzymon Janc 		struct hci_cp_remote_oob_data_neg_reply cp;
36302763eda6SSzymon Janc 
36312763eda6SSzymon Janc 		bacpy(&cp.bdaddr, &ev->bdaddr);
36322763eda6SSzymon Janc 		hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
36332763eda6SSzymon Janc 			     &cp);
36342763eda6SSzymon Janc 	}
36352763eda6SSzymon Janc 
3636e1ba1f15SSzymon Janc unlock:
36372763eda6SSzymon Janc 	hci_dev_unlock(hdev);
36382763eda6SSzymon Janc }
36392763eda6SSzymon Janc 
36406039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
3641fcd89c09SVille Tervo {
3642fcd89c09SVille Tervo 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
3643fcd89c09SVille Tervo 	struct hci_conn *conn;
3644fcd89c09SVille Tervo 
36459f1db00cSAndrei Emeltchenko 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
3646fcd89c09SVille Tervo 
3647fcd89c09SVille Tervo 	hci_dev_lock(hdev);
3648fcd89c09SVille Tervo 
36494f72b329SAndrzej Kaczmarek 	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
3650b62f328bSVille Tervo 	if (!conn) {
3651b62f328bSVille Tervo 		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
3652b62f328bSVille Tervo 		if (!conn) {
3653b62f328bSVille Tervo 			BT_ERR("No memory for new connection");
3654230fd16aSAndre Guedes 			goto unlock;
3655b62f328bSVille Tervo 		}
365629b7988aSAndre Guedes 
365729b7988aSAndre Guedes 		conn->dst_type = ev->bdaddr_type;
3658b9b343d2SAndre Guedes 
3659b9b343d2SAndre Guedes 		if (ev->role == LE_CONN_ROLE_MASTER) {
3660b9b343d2SAndre Guedes 			conn->out = true;
3661b9b343d2SAndre Guedes 			conn->link_mode |= HCI_LM_MASTER;
3662b9b343d2SAndre Guedes 		}
3663b62f328bSVille Tervo 	}
3664fcd89c09SVille Tervo 
3665cd17decbSAndre Guedes 	if (ev->status) {
3666cd17decbSAndre Guedes 		mgmt_connect_failed(hdev, &conn->dst, conn->type,
3667cd17decbSAndre Guedes 				    conn->dst_type, ev->status);
3668cd17decbSAndre Guedes 		hci_proto_connect_cfm(conn, ev->status);
3669cd17decbSAndre Guedes 		conn->state = BT_CLOSED;
3670cd17decbSAndre Guedes 		hci_conn_del(conn);
3671cd17decbSAndre Guedes 		goto unlock;
3672cd17decbSAndre Guedes 	}
3673cd17decbSAndre Guedes 
3674b644ba33SJohan Hedberg 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
3675b644ba33SJohan Hedberg 		mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
367695b23582SSzymon Janc 				      conn->dst_type, 0, NULL, 0, NULL);
367783bc71b4SVinicius Costa Gomes 
36787b5c0d52SVinicius Costa Gomes 	conn->sec_level = BT_SECURITY_LOW;
3679fcd89c09SVille Tervo 	conn->handle = __le16_to_cpu(ev->handle);
3680fcd89c09SVille Tervo 	conn->state = BT_CONNECTED;
3681fcd89c09SVille Tervo 
3682fcd89c09SVille Tervo 	hci_conn_hold_device(conn);
3683fcd89c09SVille Tervo 	hci_conn_add_sysfs(conn);
3684fcd89c09SVille Tervo 
3685fcd89c09SVille Tervo 	hci_proto_connect_cfm(conn, ev->status);
3686fcd89c09SVille Tervo 
3687fcd89c09SVille Tervo unlock:
3688fcd89c09SVille Tervo 	hci_dev_unlock(hdev);
3689fcd89c09SVille Tervo }
3690fcd89c09SVille Tervo 
36916039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
36929aa04c91SAndre Guedes {
3693e95beb41SAndre Guedes 	u8 num_reports = skb->data[0];
3694e95beb41SAndre Guedes 	void *ptr = &skb->data[1];
36953c9e9195SAndre Guedes 	s8 rssi;
36969aa04c91SAndre Guedes 
36979aa04c91SAndre Guedes 	hci_dev_lock(hdev);
36989aa04c91SAndre Guedes 
3699e95beb41SAndre Guedes 	while (num_reports--) {
3700e95beb41SAndre Guedes 		struct hci_ev_le_advertising_info *ev = ptr;
3701e95beb41SAndre Guedes 
37023c9e9195SAndre Guedes 		rssi = ev->data[ev->length];
37033c9e9195SAndre Guedes 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
370404124681SGustavo F. Padovan 				  NULL, rssi, 0, 1, ev->data, ev->length);
37053c9e9195SAndre Guedes 
3706e95beb41SAndre Guedes 		ptr += sizeof(*ev) + ev->length + 1;
37079aa04c91SAndre Guedes 	}
37089aa04c91SAndre Guedes 
37099aa04c91SAndre Guedes 	hci_dev_unlock(hdev);
37109aa04c91SAndre Guedes }
37119aa04c91SAndre Guedes 
37126039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
3713a7a595f6SVinicius Costa Gomes {
3714a7a595f6SVinicius Costa Gomes 	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
3715a7a595f6SVinicius Costa Gomes 	struct hci_cp_le_ltk_reply cp;
3716bea710feSVinicius Costa Gomes 	struct hci_cp_le_ltk_neg_reply neg;
3717a7a595f6SVinicius Costa Gomes 	struct hci_conn *conn;
3718c9839a11SVinicius Costa Gomes 	struct smp_ltk *ltk;
3719a7a595f6SVinicius Costa Gomes 
37209f1db00cSAndrei Emeltchenko 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
3721a7a595f6SVinicius Costa Gomes 
3722a7a595f6SVinicius Costa Gomes 	hci_dev_lock(hdev);
3723a7a595f6SVinicius Costa Gomes 
3724a7a595f6SVinicius Costa Gomes 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
3725bea710feSVinicius Costa Gomes 	if (conn == NULL)
3726bea710feSVinicius Costa Gomes 		goto not_found;
3727a7a595f6SVinicius Costa Gomes 
3728bea710feSVinicius Costa Gomes 	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
3729bea710feSVinicius Costa Gomes 	if (ltk == NULL)
3730bea710feSVinicius Costa Gomes 		goto not_found;
3731bea710feSVinicius Costa Gomes 
3732bea710feSVinicius Costa Gomes 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
3733a7a595f6SVinicius Costa Gomes 	cp.handle = cpu_to_le16(conn->handle);
3734c9839a11SVinicius Costa Gomes 
3735c9839a11SVinicius Costa Gomes 	if (ltk->authenticated)
3736c9839a11SVinicius Costa Gomes 		conn->sec_level = BT_SECURITY_HIGH;
3737a7a595f6SVinicius Costa Gomes 
3738a7a595f6SVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
3739a7a595f6SVinicius Costa Gomes 
3740c9839a11SVinicius Costa Gomes 	if (ltk->type & HCI_SMP_STK) {
3741c9839a11SVinicius Costa Gomes 		list_del(&ltk->list);
3742c9839a11SVinicius Costa Gomes 		kfree(ltk);
3743c9839a11SVinicius Costa Gomes 	}
3744c9839a11SVinicius Costa Gomes 
3745a7a595f6SVinicius Costa Gomes 	hci_dev_unlock(hdev);
3746bea710feSVinicius Costa Gomes 
3747bea710feSVinicius Costa Gomes 	return;
3748bea710feSVinicius Costa Gomes 
3749bea710feSVinicius Costa Gomes not_found:
3750bea710feSVinicius Costa Gomes 	neg.handle = ev->handle;
3751bea710feSVinicius Costa Gomes 	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
3752bea710feSVinicius Costa Gomes 	hci_dev_unlock(hdev);
3753a7a595f6SVinicius Costa Gomes }
3754a7a595f6SVinicius Costa Gomes 
37556039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3756fcd89c09SVille Tervo {
3757fcd89c09SVille Tervo 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
3758fcd89c09SVille Tervo 
3759fcd89c09SVille Tervo 	skb_pull(skb, sizeof(*le_ev));
3760fcd89c09SVille Tervo 
3761fcd89c09SVille Tervo 	switch (le_ev->subevent) {
3762fcd89c09SVille Tervo 	case HCI_EV_LE_CONN_COMPLETE:
3763fcd89c09SVille Tervo 		hci_le_conn_complete_evt(hdev, skb);
3764fcd89c09SVille Tervo 		break;
3765fcd89c09SVille Tervo 
37669aa04c91SAndre Guedes 	case HCI_EV_LE_ADVERTISING_REPORT:
37679aa04c91SAndre Guedes 		hci_le_adv_report_evt(hdev, skb);
37689aa04c91SAndre Guedes 		break;
37699aa04c91SAndre Guedes 
3770a7a595f6SVinicius Costa Gomes 	case HCI_EV_LE_LTK_REQ:
3771a7a595f6SVinicius Costa Gomes 		hci_le_ltk_request_evt(hdev, skb);
3772a7a595f6SVinicius Costa Gomes 		break;
3773a7a595f6SVinicius Costa Gomes 
3774fcd89c09SVille Tervo 	default:
3775fcd89c09SVille Tervo 		break;
3776fcd89c09SVille Tervo 	}
3777fcd89c09SVille Tervo }
3778fcd89c09SVille Tervo 
37799495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
37809495b2eeSAndrei Emeltchenko {
37819495b2eeSAndrei Emeltchenko 	struct hci_ev_channel_selected *ev = (void *) skb->data;
37829495b2eeSAndrei Emeltchenko 	struct hci_conn *hcon;
37839495b2eeSAndrei Emeltchenko 
37849495b2eeSAndrei Emeltchenko 	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
37859495b2eeSAndrei Emeltchenko 
37869495b2eeSAndrei Emeltchenko 	skb_pull(skb, sizeof(*ev));
37879495b2eeSAndrei Emeltchenko 
37889495b2eeSAndrei Emeltchenko 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
37899495b2eeSAndrei Emeltchenko 	if (!hcon)
37909495b2eeSAndrei Emeltchenko 		return;
37919495b2eeSAndrei Emeltchenko 
37929495b2eeSAndrei Emeltchenko 	amp_read_loc_assoc_final_data(hdev, hcon);
37939495b2eeSAndrei Emeltchenko }
37949495b2eeSAndrei Emeltchenko 
37951da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
37961da177e4SLinus Torvalds {
3797a9de9248SMarcel Holtmann 	struct hci_event_hdr *hdr = (void *) skb->data;
3798a9de9248SMarcel Holtmann 	__u8 event = hdr->evt;
37991da177e4SLinus Torvalds 
38001da177e4SLinus Torvalds 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
38011da177e4SLinus Torvalds 
3802a9de9248SMarcel Holtmann 	switch (event) {
38031da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_COMPLETE:
38041da177e4SLinus Torvalds 		hci_inquiry_complete_evt(hdev, skb);
38051da177e4SLinus Torvalds 		break;
38061da177e4SLinus Torvalds 
38071da177e4SLinus Torvalds 	case HCI_EV_INQUIRY_RESULT:
38081da177e4SLinus Torvalds 		hci_inquiry_result_evt(hdev, skb);
38091da177e4SLinus Torvalds 		break;
38101da177e4SLinus Torvalds 
3811a9de9248SMarcel Holtmann 	case HCI_EV_CONN_COMPLETE:
3812a9de9248SMarcel Holtmann 		hci_conn_complete_evt(hdev, skb);
381321d9e30eSMarcel Holtmann 		break;
381421d9e30eSMarcel Holtmann 
38151da177e4SLinus Torvalds 	case HCI_EV_CONN_REQUEST:
38161da177e4SLinus Torvalds 		hci_conn_request_evt(hdev, skb);
38171da177e4SLinus Torvalds 		break;
38181da177e4SLinus Torvalds 
38191da177e4SLinus Torvalds 	case HCI_EV_DISCONN_COMPLETE:
38201da177e4SLinus Torvalds 		hci_disconn_complete_evt(hdev, skb);
38211da177e4SLinus Torvalds 		break;
38221da177e4SLinus Torvalds 
38231da177e4SLinus Torvalds 	case HCI_EV_AUTH_COMPLETE:
38241da177e4SLinus Torvalds 		hci_auth_complete_evt(hdev, skb);
38251da177e4SLinus Torvalds 		break;
38261da177e4SLinus Torvalds 
3827a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_NAME:
3828a9de9248SMarcel Holtmann 		hci_remote_name_evt(hdev, skb);
3829a9de9248SMarcel Holtmann 		break;
3830a9de9248SMarcel Holtmann 
38311da177e4SLinus Torvalds 	case HCI_EV_ENCRYPT_CHANGE:
38321da177e4SLinus Torvalds 		hci_encrypt_change_evt(hdev, skb);
38331da177e4SLinus Torvalds 		break;
38341da177e4SLinus Torvalds 
3835a9de9248SMarcel Holtmann 	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
3836a9de9248SMarcel Holtmann 		hci_change_link_key_complete_evt(hdev, skb);
3837a9de9248SMarcel Holtmann 		break;
3838a9de9248SMarcel Holtmann 
3839a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_FEATURES:
3840a9de9248SMarcel Holtmann 		hci_remote_features_evt(hdev, skb);
3841a9de9248SMarcel Holtmann 		break;
3842a9de9248SMarcel Holtmann 
3843a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_VERSION:
3844a9de9248SMarcel Holtmann 		hci_remote_version_evt(hdev, skb);
3845a9de9248SMarcel Holtmann 		break;
3846a9de9248SMarcel Holtmann 
3847a9de9248SMarcel Holtmann 	case HCI_EV_QOS_SETUP_COMPLETE:
3848a9de9248SMarcel Holtmann 		hci_qos_setup_complete_evt(hdev, skb);
3849a9de9248SMarcel Holtmann 		break;
3850a9de9248SMarcel Holtmann 
3851a9de9248SMarcel Holtmann 	case HCI_EV_CMD_COMPLETE:
3852a9de9248SMarcel Holtmann 		hci_cmd_complete_evt(hdev, skb);
3853a9de9248SMarcel Holtmann 		break;
3854a9de9248SMarcel Holtmann 
3855a9de9248SMarcel Holtmann 	case HCI_EV_CMD_STATUS:
3856a9de9248SMarcel Holtmann 		hci_cmd_status_evt(hdev, skb);
3857a9de9248SMarcel Holtmann 		break;
3858a9de9248SMarcel Holtmann 
3859a9de9248SMarcel Holtmann 	case HCI_EV_ROLE_CHANGE:
3860a9de9248SMarcel Holtmann 		hci_role_change_evt(hdev, skb);
3861a9de9248SMarcel Holtmann 		break;
3862a9de9248SMarcel Holtmann 
3863a9de9248SMarcel Holtmann 	case HCI_EV_NUM_COMP_PKTS:
3864a9de9248SMarcel Holtmann 		hci_num_comp_pkts_evt(hdev, skb);
3865a9de9248SMarcel Holtmann 		break;
3866a9de9248SMarcel Holtmann 
3867a9de9248SMarcel Holtmann 	case HCI_EV_MODE_CHANGE:
3868a9de9248SMarcel Holtmann 		hci_mode_change_evt(hdev, skb);
38691da177e4SLinus Torvalds 		break;
38701da177e4SLinus Torvalds 
38711da177e4SLinus Torvalds 	case HCI_EV_PIN_CODE_REQ:
38721da177e4SLinus Torvalds 		hci_pin_code_request_evt(hdev, skb);
38731da177e4SLinus Torvalds 		break;
38741da177e4SLinus Torvalds 
38751da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_REQ:
38761da177e4SLinus Torvalds 		hci_link_key_request_evt(hdev, skb);
38771da177e4SLinus Torvalds 		break;
38781da177e4SLinus Torvalds 
38791da177e4SLinus Torvalds 	case HCI_EV_LINK_KEY_NOTIFY:
38801da177e4SLinus Torvalds 		hci_link_key_notify_evt(hdev, skb);
38811da177e4SLinus Torvalds 		break;
38821da177e4SLinus Torvalds 
38831da177e4SLinus Torvalds 	case HCI_EV_CLOCK_OFFSET:
38841da177e4SLinus Torvalds 		hci_clock_offset_evt(hdev, skb);
38851da177e4SLinus Torvalds 		break;
38861da177e4SLinus Torvalds 
3887a8746417SMarcel Holtmann 	case HCI_EV_PKT_TYPE_CHANGE:
3888a8746417SMarcel Holtmann 		hci_pkt_type_change_evt(hdev, skb);
3889a8746417SMarcel Holtmann 		break;
3890a8746417SMarcel Holtmann 
389185a1e930SMarcel Holtmann 	case HCI_EV_PSCAN_REP_MODE:
389285a1e930SMarcel Holtmann 		hci_pscan_rep_mode_evt(hdev, skb);
389385a1e930SMarcel Holtmann 		break;
389485a1e930SMarcel Holtmann 
3895a9de9248SMarcel Holtmann 	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
3896a9de9248SMarcel Holtmann 		hci_inquiry_result_with_rssi_evt(hdev, skb);
3897a9de9248SMarcel Holtmann 		break;
3898a9de9248SMarcel Holtmann 
3899a9de9248SMarcel Holtmann 	case HCI_EV_REMOTE_EXT_FEATURES:
3900a9de9248SMarcel Holtmann 		hci_remote_ext_features_evt(hdev, skb);
3901a9de9248SMarcel Holtmann 		break;
3902a9de9248SMarcel Holtmann 
3903a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_COMPLETE:
3904a9de9248SMarcel Holtmann 		hci_sync_conn_complete_evt(hdev, skb);
3905a9de9248SMarcel Holtmann 		break;
3906a9de9248SMarcel Holtmann 
3907a9de9248SMarcel Holtmann 	case HCI_EV_SYNC_CONN_CHANGED:
3908a9de9248SMarcel Holtmann 		hci_sync_conn_changed_evt(hdev, skb);
3909a9de9248SMarcel Holtmann 		break;
3910a9de9248SMarcel Holtmann 
391104837f64SMarcel Holtmann 	case HCI_EV_SNIFF_SUBRATE:
391204837f64SMarcel Holtmann 		hci_sniff_subrate_evt(hdev, skb);
391304837f64SMarcel Holtmann 		break;
391404837f64SMarcel Holtmann 
3915a9de9248SMarcel Holtmann 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
3916a9de9248SMarcel Holtmann 		hci_extended_inquiry_result_evt(hdev, skb);
39171da177e4SLinus Torvalds 		break;
39181da177e4SLinus Torvalds 
39191c2e0041SJohan Hedberg 	case HCI_EV_KEY_REFRESH_COMPLETE:
39201c2e0041SJohan Hedberg 		hci_key_refresh_complete_evt(hdev, skb);
39211c2e0041SJohan Hedberg 		break;
39221c2e0041SJohan Hedberg 
39230493684eSMarcel Holtmann 	case HCI_EV_IO_CAPA_REQUEST:
39240493684eSMarcel Holtmann 		hci_io_capa_request_evt(hdev, skb);
39250493684eSMarcel Holtmann 		break;
39260493684eSMarcel Holtmann 
392703b555e1SJohan Hedberg 	case HCI_EV_IO_CAPA_REPLY:
392803b555e1SJohan Hedberg 		hci_io_capa_reply_evt(hdev, skb);
392903b555e1SJohan Hedberg 		break;
393003b555e1SJohan Hedberg 
3931a5c29683SJohan Hedberg 	case HCI_EV_USER_CONFIRM_REQUEST:
3932a5c29683SJohan Hedberg 		hci_user_confirm_request_evt(hdev, skb);
3933a5c29683SJohan Hedberg 		break;
3934a5c29683SJohan Hedberg 
39351143d458SBrian Gix 	case HCI_EV_USER_PASSKEY_REQUEST:
39361143d458SBrian Gix 		hci_user_passkey_request_evt(hdev, skb);
39371143d458SBrian Gix 		break;
39381143d458SBrian Gix 
393992a25256SJohan Hedberg 	case HCI_EV_USER_PASSKEY_NOTIFY:
394092a25256SJohan Hedberg 		hci_user_passkey_notify_evt(hdev, skb);
394192a25256SJohan Hedberg 		break;
394292a25256SJohan Hedberg 
394392a25256SJohan Hedberg 	case HCI_EV_KEYPRESS_NOTIFY:
394492a25256SJohan Hedberg 		hci_keypress_notify_evt(hdev, skb);
394592a25256SJohan Hedberg 		break;
394692a25256SJohan Hedberg 
39470493684eSMarcel Holtmann 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
39480493684eSMarcel Holtmann 		hci_simple_pair_complete_evt(hdev, skb);
39490493684eSMarcel Holtmann 		break;
39500493684eSMarcel Holtmann 
395141a96212SMarcel Holtmann 	case HCI_EV_REMOTE_HOST_FEATURES:
395241a96212SMarcel Holtmann 		hci_remote_host_features_evt(hdev, skb);
395341a96212SMarcel Holtmann 		break;
395441a96212SMarcel Holtmann 
3955fcd89c09SVille Tervo 	case HCI_EV_LE_META:
3956fcd89c09SVille Tervo 		hci_le_meta_evt(hdev, skb);
3957fcd89c09SVille Tervo 		break;
3958fcd89c09SVille Tervo 
39599495b2eeSAndrei Emeltchenko 	case HCI_EV_CHANNEL_SELECTED:
39609495b2eeSAndrei Emeltchenko 		hci_chan_selected_evt(hdev, skb);
39619495b2eeSAndrei Emeltchenko 		break;
39629495b2eeSAndrei Emeltchenko 
39632763eda6SSzymon Janc 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
39642763eda6SSzymon Janc 		hci_remote_oob_data_request_evt(hdev, skb);
39652763eda6SSzymon Janc 		break;
39662763eda6SSzymon Janc 
396725e89e99SAndrei Emeltchenko 	case HCI_EV_NUM_COMP_BLOCKS:
396825e89e99SAndrei Emeltchenko 		hci_num_comp_blocks_evt(hdev, skb);
396925e89e99SAndrei Emeltchenko 		break;
397025e89e99SAndrei Emeltchenko 
39711da177e4SLinus Torvalds 	default:
39729f1db00cSAndrei Emeltchenko 		BT_DBG("%s event 0x%2.2x", hdev->name, event);
39731da177e4SLinus Torvalds 		break;
39741da177e4SLinus Torvalds 	}
39751da177e4SLinus Torvalds 
39761da177e4SLinus Torvalds 	kfree_skb(skb);
39771da177e4SLinus Torvalds 	hdev->stat.evt_rx++;
39781da177e4SLinus Torvalds }
3979